From 729ffc9dd676bd1e823180c8b802b44cf11a89b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 16 Dec 2021 08:56:29 +0100 Subject: Fixed that external travels led inside holes (around the perimeter) instead of inside the model when the avoid crossing perimeters was enabled. Caused by changed behaviour of offset/expand functions when called on CW polygons (holes) after 7ff76d07684858fd937ef2f5d863f105a10f798e. When it is called expand on CW polygons (holes), they shrunk instead of expanded. --- src/libslic3r/GCode/AvoidCrossingPerimeters.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp index 48b9515f7..1b55514ee 100644 --- a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp +++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp @@ -1034,24 +1034,30 @@ static Polygons get_boundary_external(const Layer &layer) #endif // Collect all holes for all printed objects and their instances, which will be printed at the same time as passed "layer". for (const PrintObject *object : layer.object()->print()->objects()) { - Polygons polygons_per_obj; + Polygons holes_per_obj; #ifdef INCLUDE_SUPPORTS_IN_BOUNDARY ExPolygons supports_per_obj; #endif if (const Layer *l = object->get_layer_at_printz(layer.print_z, EPSILON); l) - for (const ExPolygon &island : l->lslices) append(polygons_per_obj, island.holes); + for (const ExPolygon &island : l->lslices) + append(holes_per_obj, island.holes); if (support_layer) { auto *layer_below = object->get_first_layer_bellow_printz(layer.print_z, EPSILON); if (layer_below) - for (const ExPolygon &island : layer_below->lslices) append(polygons_per_obj, island.holes); + for (const ExPolygon &island : layer_below->lslices) + append(holes_per_obj, island.holes); #ifdef INCLUDE_SUPPORTS_IN_BOUNDARY append(supports_per_obj, support_layer->support_islands.expolygons); #endif } + // After 7ff76d07684858fd937ef2f5d863f105a10f798e, when expand is called on CW polygons (holes), they are shrunk + // instead of expanded because union that makes CCW from CW isn't called anymore. So let's make it CCW. + polygons_reverse(holes_per_obj); + for (const PrintInstance &instance : object->instances()) { size_t boundary_idx = boundary.size(); - append(boundary, polygons_per_obj); + append(boundary, holes_per_obj); for (; boundary_idx < boundary.size(); ++boundary_idx) boundary[boundary_idx].translate(instance.shift); #ifdef INCLUDE_SUPPORTS_IN_BOUNDARY -- cgit v1.2.3 From 285e2a32a2bc53465f6d8c885d3a6b99bcca2be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 16 Dec 2021 08:57:04 +0100 Subject: Fixed issues in inner_offset() in the avoid crossing perimeters that caused in some cases travels to follow the first perimeter instead of the second one. --- src/libslic3r/GCode/AvoidCrossingPerimeters.cpp | 52 ++++++++++++++++--------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp index 1b55514ee..417322584 100644 --- a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp +++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp @@ -731,34 +731,50 @@ static bool need_wipe(const GCode &gcodegen, } // Adds points around all vertices so that the offset affects only small sections around these vertices. -static void resample_polygon(Polygon &polygon, double dist_from_vertex) +static void resample_polygon(Polygon &polygon, double dist_from_vertex, double max_allowed_distance) { Points resampled_poly; resampled_poly.reserve(3 * polygon.size()); - resampled_poly.emplace_back(polygon.first_point()); - for (size_t pt_idx = 1; pt_idx < polygon.size(); ++pt_idx) { - const Point &p1 = polygon[pt_idx - 1]; - const Point &p2 = polygon[pt_idx]; - double line_length = (p2 - p1).cast().norm(); - Vector line_vec = ((p2 - p1).cast().normalized() * dist_from_vertex).cast(); - if (line_length > 2 * dist_from_vertex) { - resampled_poly.emplace_back(p1 + line_vec); - resampled_poly.emplace_back(p2 - line_vec); - } + for (size_t pt_idx = 0; pt_idx < polygon.size(); ++pt_idx) { resampled_poly.emplace_back(polygon[pt_idx]); + + const Point &p1 = polygon[pt_idx]; + const Point &p2 = polygon[next_idx_modulo(pt_idx, polygon.size())]; + const Vec2d line_vec = (p2 - p1).cast(); + double line_length = line_vec.norm(); + const Vector vertex_offset_vec = (line_vec.normalized() * dist_from_vertex).cast(); + if (line_length > 2 * dist_from_vertex && vertex_offset_vec != Vector(0, 0)) { + resampled_poly.emplace_back(p1 + vertex_offset_vec); + + const Vec2d new_vertex_vec = (p2 - p1 - 2 * vertex_offset_vec).cast(); + const double new_vertex_vec_length = new_vertex_vec.norm(); + if (new_vertex_vec_length > max_allowed_distance) { + const Vec2d &prev_point = resampled_poly.back().cast(); + const size_t parts_count = size_t(ceil(new_vertex_vec_length / max_allowed_distance)); + for (size_t part_idx = 1; part_idx < parts_count; ++part_idx) { + const double part_param = double(part_idx) / double(parts_count); + const Vec2d new_point = prev_point + new_vertex_vec * part_param; + resampled_poly.emplace_back(new_point.cast()); + } + } + + resampled_poly.emplace_back(p2 - vertex_offset_vec); + } } polygon.points = std::move(resampled_poly); } -static void resample_expolygon(ExPolygon &ex_polygon, double dist_from_vertex) +static void resample_expolygon(ExPolygon &ex_polygon, double dist_from_vertex, double max_allowed_distance) { - resample_polygon(ex_polygon.contour, dist_from_vertex); - for (Polygon &polygon : ex_polygon.holes) resample_polygon(polygon, dist_from_vertex); + resample_polygon(ex_polygon.contour, dist_from_vertex, max_allowed_distance); + for (Polygon &polygon : ex_polygon.holes) + resample_polygon(polygon, dist_from_vertex, max_allowed_distance); } -static void resample_expolygons(ExPolygons &ex_polygons, double dist_from_vertex) +static void resample_expolygons(ExPolygons &ex_polygons, double dist_from_vertex, double max_allowed_distance) { - for (ExPolygon &ex_poly : ex_polygons) resample_expolygon(ex_poly, dist_from_vertex); + for (ExPolygon &ex_poly : ex_polygons) + resample_expolygon(ex_poly, dist_from_vertex, max_allowed_distance); } static void precompute_polygon_distances(const Polygon &polygon, std::vector &polygon_distances_out) @@ -834,7 +850,7 @@ static std::vector contour_distance(const EdgeGrid::Grid &grid, double param_end = boundary_parameters.back(); const size_t ipt = it_contour_and_segment->second; if (contour.begin() + ipt + 1 < contour.end()) - param_hi += boundary_parameters[ipt > 0 ? ipt - 1 : 0]; + param_hi += boundary_parameters[ipt]; if (param_lo > param_hi) std::swap(param_lo, param_hi); assert(param_lo > -SCALED_EPSILON && param_lo <= param_end + SCALED_EPSILON); @@ -932,7 +948,7 @@ static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset) double min_contour_width = 2. * offset + SCALED_EPSILON; double search_radius = 2. * (offset + min_contour_width); ExPolygons ex_poly_result = ex_polygons; - resample_expolygons(ex_poly_result, offset / 2); + resample_expolygons(ex_poly_result, offset / 2, scaled(0.5)); for (ExPolygon &ex_poly : ex_poly_result) { BoundingBox bbox(get_extents(ex_poly)); -- cgit v1.2.3