diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index 4c6e82c5f..ed76fc66a 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -718,6 +718,8 @@ Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfac { return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::SurfacesProvider(subject), ClipperUtils::SurfacesProvider(clip), do_safety_offset); } Slic3r::ExPolygons diff_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset) { return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::SurfacesPtrProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); } +Slic3r::ExPolygons diff_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset) + { return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::SurfacesPtrProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); } Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset) { return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); } diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp index 3dfc09c1a..5f495788b 100644 --- a/src/libslic3r/ClipperUtils.hpp +++ b/src/libslic3r/ClipperUtils.hpp @@ -373,6 +373,8 @@ inline Slic3r::Polygons shrink(const Slic3r::Polygons &polygons, const float d { assert(delta > 0); return offset(polygons, -delta, joinType, miterLimit); } inline Slic3r::ExPolygons shrink_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit) { assert(delta > 0); return offset_ex(polygons, -delta, joinType, miterLimit); } +inline Slic3r::ExPolygons shrink_ex(const Slic3r::ExPolygons &polygons, const float delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit) + { assert(delta > 0); return offset_ex(polygons, -delta, joinType, miterLimit); } // Wherever applicable, please use the opening() / closing() variants instead, they convey their purpose better. // Input polygons for negative offset shall be "normalized": There must be no overlap / intersections between the input polygons. @@ -433,6 +435,7 @@ Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::ExPoly Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::Surfaces &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::ExPolygons diff_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::ExPolygons diff_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); +Slic3r::ExPolygons diff_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polylines diff_pl(const Slic3r::Polyline &subject, const Slic3r::Polygons &clip); Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip); Slic3r::Polylines diff_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygon &clip); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index dab198406..0c20acc17 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1474,51 +1474,36 @@ void PrintObject::discover_vertical_shells() #ifdef SLIC3R_DEBUG_SLICE_PROCESSING Polygons shell_before = shell; #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ -#if 1 + ExPolygons regularized_shell; { // Open to remove (filter out) regions narrower than a bit less than an infill extrusion line width. // Such narrow regions are difficult to fill in with a gap fill algorithm (or Arachne), however they are most likely // not needed for print stability / quality. - const float narrow_ensure_vertical_wall_thickness_region_radius = 0.5f * 0.85f * min_perimeter_infill_spacing; + const float narrow_ensure_vertical_wall_thickness_region_radius = 0.5f * 0.65f * min_perimeter_infill_spacing; // Then close gaps narrower than 1.2 * line width, such gaps are difficult to fill in with sparse infill, // thus they will be merged into the solid infill. const float narrow_sparse_infill_region_radius = 0.5f * 1.2f * min_perimeter_infill_spacing; // Finally expand the infill a bit to remove tiny gaps between solid infill and the other regions. const float tiny_overlap_radius = 0.2f * min_perimeter_infill_spacing; - shell = shrink(opening(union_(shell), + regularized_shell = shrink_ex(offset2_ex(union_ex(shell), // Open to remove (filter out) regions narrower than an infill extrusion line width. - narrow_ensure_vertical_wall_thickness_region_radius, + -narrow_ensure_vertical_wall_thickness_region_radius, // Then close gaps narrower than 1.2 * line width, such gaps are difficult to fill in with sparse infill. narrow_ensure_vertical_wall_thickness_region_radius + narrow_sparse_infill_region_radius, ClipperLib::jtSquare), // Finally expand the infill a bit to remove tiny gaps between solid infill and the other regions. narrow_sparse_infill_region_radius - tiny_overlap_radius, ClipperLib::jtSquare); - // The opening operation may cause scattered tiny drops on the smooth parts of the model. - shell.erase(std::remove_if(shell.begin(), shell.end(), [&min_perimeter_infill_spacing](const Polygon& p){ - return p.area() < min_perimeter_infill_spacing * scaled(8.0); - }), shell.end()); + // The opening operation may cause scattered tiny drops on the smooth parts of the model, filter them out + regularized_shell.erase(std::remove_if(regularized_shell.begin(), regularized_shell.end(), + [&min_perimeter_infill_spacing](const ExPolygon &p) { + return p.area() < min_perimeter_infill_spacing * scaled(8.0); + }), + regularized_shell.end()); } - if (shell.empty()) + if (regularized_shell.empty()) continue; -#else - // Ensure each region is at least 3x infill line width wide, so it could be filled in. - // float margin = float(infill_line_spacing) * 3.f; - float margin = float(infill_line_spacing) * 1.5f; - // we use a higher miterLimit here to handle areas with acute angles - // in those cases, the default miterLimit would cut the corner and we'd - // get a triangle in $too_narrow; if we grow it below then the shell - // would have a different shape from the external surface and we'd still - // have the same angle, so the next shell would be grown even more and so on. - Polygons too_narrow = diff(shell, opening(shell, margin, ClipperLib::jtMiter, 5.), true); - if (! too_narrow.empty()) { - // grow the collapsing parts and add the extra area to the neighbor layer - // as well as to our original surfaces so that we support this - // additional area in the next shell too - // make sure our grown surfaces don't exceed the fill area - polygons_append(shell, intersection(offset(too_narrow, margin), polygonsInternal)); - } -#endif - ExPolygons new_internal_solid = intersection_ex(polygonsInternal, shell); + + ExPolygons new_internal_solid = intersection_ex(polygonsInternal, regularized_shell); #ifdef SLIC3R_DEBUG_SLICE_PROCESSING { Slic3r::SVG svg(debug_out_path("discover_vertical_shells-regularized-%d.svg", debug_idx), get_extents(shell_before)); @@ -1533,8 +1518,8 @@ void PrintObject::discover_vertical_shells() #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ // Trim the internal & internalvoid by the shell. - Slic3r::ExPolygons new_internal = diff_ex(layerm->fill_surfaces().filter_by_type(stInternal), shell); - Slic3r::ExPolygons new_internal_void = diff_ex(layerm->fill_surfaces().filter_by_type(stInternalVoid), shell); + Slic3r::ExPolygons new_internal = diff_ex(layerm->fill_surfaces().filter_by_type(stInternal), regularized_shell); + Slic3r::ExPolygons new_internal_void = diff_ex(layerm->fill_surfaces().filter_by_type(stInternalVoid), regularized_shell); #ifdef SLIC3R_DEBUG_SLICE_PROCESSING {