From eafe57d8c6de37016eb5820caef4a960f112cb39 Mon Sep 17 00:00:00 2001 From: "songwei.li" Date: Wed, 3 Sep 2025 18:00:06 +0800 Subject: [PATCH] ENH: TimelapsePosPicker, make timelapsePos far away from the camera By using Manhattan distance, a penalty function is constructed by weighting the distance from the safe position to the camera and the distance from the current position, incentivizing safe positions to move away from the camera. The isometric line of the integrated Manhattan distance changes from a circle to a trapezoidal shape, with the Euclidean distance toward the camera being half that away from the camera. This ensures that when selecting a safe position, points with the same Euclidean distance from the current position receive a smaller penalty if they are farther away from the camera. jira: none Change-Id: I3c256cfc0c33cecade86c254613063adeac59f91 (cherry picked from commit f86ca36b471dd99d4c1bd21c4e6db3ee10eb5a6d) --- src/libslic3r/GCode/TimelapsePosPicker.cpp | 39 +++++++++++++++++----- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/GCode/TimelapsePosPicker.cpp b/src/libslic3r/GCode/TimelapsePosPicker.cpp index 63569d856f..0301d01122 100644 --- a/src/libslic3r/GCode/TimelapsePosPicker.cpp +++ b/src/libslic3r/GCode/TimelapsePosPicker.cpp @@ -380,19 +380,42 @@ namespace Slic3r { std::priority_queue max_heap; - double min_distance = std::numeric_limits::max(); - Point nearest_point = DefaultTimelapsePos; + const double candidate_point_segment = scale_(5), weight_of_camera=1./3.; + auto penaltyFunc = [&weight_of_camera](const Point &curr_post, const Point &CameraPos, const Point &candidatet) -> double { + // move distance + Camera occlusion penalty function + double ret_pen = (curr_post - candidatet).cwiseAbs().sum() - weight_of_camera * (CameraPos - candidatet).cwiseAbs().sum(); + return ret_pen; + }; for (const auto& expoly : safe_areas) { Polygons polys = to_polygons(expoly); for (auto& poly : polys) { for (size_t idx = 0; idx < poly.points.size(); ++idx) { - Line line(poly.points[idx], poly.points[next_idx_modulo(idx, poly.points)]); - Point candidate; - double dist = line.distance_to_squared(curr_pos, &candidate); - max_heap.push({ dist,candidate }); - if (max_heap.size() > MAX_CANDIDATE_SIZE) - max_heap.pop(); + double best_penalty = std::numeric_limits::max(); + Point best_candidate = DefaultTimelapsePos; // the best candidate form current line + //std::vector candidate_source; + if ((poly.points[idx] - poly.points[next_idx_modulo(idx, poly.points)]).cwiseAbs().sum() < candidate_point_segment) { + best_candidate = poly.points[idx]; // only check the start point if the line is short + best_penalty = penaltyFunc(curr_pos, DefaultCameraPos, best_candidate); + }else{ + Point direct_of_line = poly.points[next_idx_modulo(idx, poly.points)] - poly.points[idx]; + double length_L1 = direct_of_line.cwiseAbs().sum(); + int num_steps = static_cast(length_L1 / candidate_point_segment); // for long line use 5mm segmentation to check + // devide by length_L1 instead of steps, prevent lose accuracy for the step length + direct_of_line.x() = static_cast(static_cast (direct_of_line.x()) * candidate_point_segment / length_L1); + direct_of_line.y() = static_cast(static_cast (direct_of_line.y()) * candidate_point_segment / length_L1); + Point candidate; + for (int line_seg_i = 0; line_seg_i <= num_steps; ++line_seg_i) { + candidate=poly.points[idx] + direct_of_line * line_seg_i; + double dist = penaltyFunc(curr_pos, DefaultCameraPos, candidate); + if (dist < best_penalty) { + best_penalty = dist; + best_candidate = candidate; + }//only push the best point into heap for the whole line + } + } + max_heap.push({best_penalty, best_candidate}); + if (max_heap.size() > MAX_CANDIDATE_SIZE) max_heap.pop(); } } }