From b8d574093dfdfee3a2a0b7bf85e5a617c5d1c0f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Sun, 11 Oct 2020 15:45:50 +0200 Subject: [PATCH] Small rework of connecting infill with perimeters using hooks Hooks are preferably generated in the direction of printed perimeters. Small refactoring of the algorithm. Some parts of the algorithm are better documented. --- src/libslic3r/Fill/FillBase.cpp | 66 ++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index d68c770ab..85f37de32 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -833,6 +833,7 @@ void mark_boundary_segments_touching_infill( } } +#if 0 static double compute_distance_to_consumed_point(const std::vector & boundary, const std::vector> &boundary_data, size_t contour_idx, @@ -855,20 +856,24 @@ static double compute_distance_to_consumed_point(const std::vector & return total_distance; } +#endif -static std::pair get_hook_path(const std::vector & boundary, +// Returns possible path for an added hook. The path shrinks to max_lenght, by the closest consumed point or by the closest point in not_connected +// Also returns not shrink path's length to closest consumed point or closest point in not_connected +static std::pair get_hook_path(const std::vector &boundary, const std::vector> &boundary_data, size_t contour_idx, size_t point_index, bool forward, int hook_length, - std::vector & not_connected) + std::unordered_set ¬_connected) { double total_distance = 0; Points points; points.emplace_back(boundary[contour_idx][point_index]); + // Follow the path around the boundary to consumed point or to the point in not_connected do { if (forward) point_index = (point_index == (boundary[contour_idx].size() - 1)) ? 0 : (point_index + 1); @@ -879,8 +884,9 @@ static std::pair get_hook_path(const std::vector & total_distance += (successor - points.back()).cast().norm(); points.emplace_back(successor); } while (!boundary_data[contour_idx][point_index].point_consumed && total_distance < hook_length && - std::find(not_connected.begin(), not_connected.end(), points.back()) == not_connected.end()); + not_connected.find(points.back()) == not_connected.end()); + // If the path is longer than hook_length, shrink it to this its length if (total_distance > hook_length) { Vec2d vector = (points.back() - points[points.size() - 2]).cast(); double vector_length = vector.norm(); @@ -1081,46 +1087,46 @@ void Fill::connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary_ }; if (hook_length != 0) { - std::vector not_connect_points; + // Create a set of points which has not been connected by the previous part of the algorithm + std::unordered_set not_connect_points; for (const std::pair &contour_point : map_infill_end_point_to_boundary) if (contour_point.first != boundary_idx_unconnected && !boundary_data[contour_point.first][contour_point.second].point_consumed) - not_connect_points.emplace_back(boundary[contour_point.first][contour_point.second]); + not_connect_points.emplace(boundary[contour_point.first][contour_point.second]); for (size_t endpoint_idx = 0; endpoint_idx < map_infill_end_point_to_boundary.size(); ++endpoint_idx) { - Polyline & polyline = infill_ordered[get_merged_index(endpoint_idx / 2)]; + Polyline &polyline = infill_ordered[get_merged_index(endpoint_idx / 2)]; const std::pair &contour_point = map_infill_end_point_to_boundary[endpoint_idx]; - if (contour_point.first != boundary_idx_unconnected && - !boundary_data[contour_point.first][contour_point.second].point_consumed) { - Point boundary_point = boundary[contour_point.first][contour_point.second]; - auto [points_forward, total_length_forward] = get_hook_path(boundary, boundary_data, contour_point.first, - contour_point.second, true, hook_length, not_connect_points); - auto [points_backward, total_length_backward] = get_hook_path(boundary, boundary_data, contour_point.first, - contour_point.second, false, hook_length, not_connect_points); - - Points points; - if (total_length_forward < hook_length && total_length_backward < hook_length) { - continue; - } else if (total_length_forward < total_length_backward && total_length_forward >= hook_length) { - points = std::move(points_forward); - } else if (total_length_backward < total_length_forward && total_length_backward >= hook_length) { - points = std::move(points_backward); - } else if (total_length_forward > total_length_backward) { - points = std::move(points_forward); + if (contour_point.first != boundary_idx_unconnected && !boundary_data[contour_point.first][contour_point.second].point_consumed) { + Point boundary_point = boundary[contour_point.first][contour_point.second]; + auto [points_forward, forward_free_length] = get_hook_path(boundary, boundary_data, contour_point.first, contour_point.second, true, + hook_length, not_connect_points); + Points hook_points; + // Check if the hook could fit in space in the direction of perimeters + if (forward_free_length >= hook_length) { + hook_points = std::move(points_forward); } else { - points = std::move(points_backward); + auto [points_backward, backward_free_length] = get_hook_path(boundary, boundary_data, contour_point.first, contour_point.second, + false, hook_length, not_connect_points); + // Check if the hook could fit in space in the opposite direction of perimeters. + // In this direction could be another hook. Because of it, it is required free space of size at least 2 * hook_length + if (backward_free_length >= (2 * hook_length)) + hook_points = std::move(points_backward); + else + continue; } + // Identify if the front point or back point of the polyline is touching the boundary if ((boundary_point - polyline.points.front()).cast().squaredNorm() <= (SCALED_EPSILON * SCALED_EPSILON)) { - Points merge_points; - merge_points.reserve(polyline.points.size() + points.size() - 1); + Points merged_points; + merged_points.reserve(polyline.points.size() + hook_points.size() - 1); - for (auto it = points.rbegin(); it != points.rend() - 1; ++it) merge_points.emplace_back(*it); + for (auto it = hook_points.rbegin(); it != hook_points.rend() - 1; ++it) merged_points.emplace_back(*it); - append(merge_points, std::move(polyline.points)); - polyline.points = std::move(merge_points); + append(merged_points, std::move(polyline.points)); + polyline.points = std::move(merged_points); } else { - for (auto it = points.begin() + 1; it != points.end(); ++it) polyline.points.emplace_back(*it); + for (auto it = hook_points.begin() + 1; it != hook_points.end(); ++it) polyline.points.emplace_back(*it); } } }