From 6dadcee6abb55aee9d6867452b6da108eac603f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 8 Oct 2024 18:10:48 +0200 Subject: [PATCH] SPE-2486: Reimplement fuzzy skin to be applied only to perimeter parts instead of creating different LayerRegion. --- src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp | 94 +++++++++++++++++++ src/libslic3r/Feature/FuzzySkin/FuzzySkin.hpp | 4 + src/libslic3r/PerimeterGenerator.cpp | 18 ++-- 3 files changed, 104 insertions(+), 12 deletions(-) diff --git a/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp b/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp index ba27b6c734..9d2b9d3178 100644 --- a/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp +++ b/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp @@ -1,5 +1,6 @@ #include +#include "libslic3r/Algorithm/LineSegmentation/LineSegmentation.hpp" #include "libslic3r/Arachne/utils/ExtrusionJunction.hpp" #include "libslic3r/Arachne/utils/ExtrusionLine.hpp" #include "libslic3r/PerimeterGenerator.hpp" @@ -133,4 +134,97 @@ bool should_fuzzify(const PrintRegionConfig &config, const size_t layer_idx, con return is_contour ? fuzzify_contours : fuzzify_holes; } +Polygon apply_fuzzy_skin(const Polygon &polygon, const PrintRegionConfig &base_config, const PerimeterRegions &perimeter_regions, const size_t layer_idx, const size_t perimeter_idx, const bool is_contour) +{ + using namespace Slic3r::Algorithm::LineSegmentation; + + auto apply_fuzzy_skin_on_polygon = [&layer_idx, &perimeter_idx, &is_contour](const Polygon &polygon, const PrintRegionConfig &config) -> Polygon { + if (should_fuzzify(config, layer_idx, perimeter_idx, is_contour)) { + Polygon fuzzified_polygon = polygon; + fuzzy_polygon(fuzzified_polygon, scaled(config.fuzzy_skin_thickness.value), scaled(config.fuzzy_skin_point_dist.value)); + + return fuzzified_polygon; + } else { + return polygon; + } + }; + + if (perimeter_regions.empty()) { + return apply_fuzzy_skin_on_polygon(polygon, base_config); + } + + PolylineRegionSegments segments = polygon_segmentation(polygon, base_config, perimeter_regions); + if (segments.size() == 1) { + const PrintRegionConfig &config = segments.front().config; + return apply_fuzzy_skin_on_polygon(polygon, config); + } + + Polygon fuzzified_polygon; + for (PolylineRegionSegment &segment : segments) { + const PrintRegionConfig &config = segment.config; + if (should_fuzzify(config, layer_idx, perimeter_idx, is_contour)) { + fuzzy_polyline(segment.polyline.points, false, scaled(config.fuzzy_skin_thickness.value), scaled(config.fuzzy_skin_point_dist.value)); + } + + assert(!segment.polyline.empty()); + if (segment.polyline.empty()) { + continue; + } else if (!fuzzified_polygon.empty() && fuzzified_polygon.back() == segment.polyline.front()) { + // Remove the last point to avoid duplicate points. + fuzzified_polygon.points.pop_back(); + } + + Slic3r::append(fuzzified_polygon.points, std::move(segment.polyline.points)); + } + + assert(!fuzzified_polygon.empty()); + if (fuzzified_polygon.front() == fuzzified_polygon.back()) { + // Remove the last point to avoid duplicity between the first and the last point. + fuzzified_polygon.points.pop_back(); + } + + return fuzzified_polygon; +} + +Arachne::ExtrusionLine apply_fuzzy_skin(const Arachne::ExtrusionLine &extrusion, const PrintRegionConfig &base_config, const PerimeterRegions &perimeter_regions, const size_t layer_idx, const size_t perimeter_idx, const bool is_contour) +{ + using namespace Slic3r::Algorithm::LineSegmentation; + using namespace Slic3r::Arachne; + + if (perimeter_regions.empty()) { + if (should_fuzzify(base_config, layer_idx, perimeter_idx, is_contour)) { + ExtrusionLine fuzzified_extrusion = extrusion; + fuzzy_extrusion_line(fuzzified_extrusion, scaled(base_config.fuzzy_skin_thickness.value), scaled(base_config.fuzzy_skin_point_dist.value)); + + return fuzzified_extrusion; + } else { + return extrusion; + } + } + + ExtrusionRegionSegments segments = extrusion_segmentation(extrusion, base_config, perimeter_regions); + ExtrusionLine fuzzified_extrusion; + + for (ExtrusionRegionSegment &segment : segments) { + const PrintRegionConfig &config = segment.config; + if (should_fuzzify(config, layer_idx, perimeter_idx, is_contour)) { + fuzzy_extrusion_line(segment.extrusion, scaled(config.fuzzy_skin_thickness.value), scaled(config.fuzzy_skin_point_dist.value)); + } + + assert(!segment.extrusion.empty()); + if (segment.extrusion.empty()) { + continue; + } else if (!fuzzified_extrusion.empty() && fuzzified_extrusion.back().p == segment.extrusion.front().p) { + // Remove the last point to avoid duplicate points (We don't care if the width of both points is different.). + fuzzified_extrusion.junctions.pop_back(); + } + + Slic3r::append(fuzzified_extrusion.junctions, std::move(segment.extrusion.junctions)); + } + + assert(!fuzzified_extrusion.empty()); + + return fuzzified_extrusion; +} + } // namespace Slic3r::Feature::FuzzySkin diff --git a/src/libslic3r/Feature/FuzzySkin/FuzzySkin.hpp b/src/libslic3r/Feature/FuzzySkin/FuzzySkin.hpp index e852b4114f..fb5db546f3 100644 --- a/src/libslic3r/Feature/FuzzySkin/FuzzySkin.hpp +++ b/src/libslic3r/Feature/FuzzySkin/FuzzySkin.hpp @@ -17,6 +17,10 @@ void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy_skin_t bool should_fuzzify(const PrintRegionConfig &config, size_t layer_idx, size_t perimeter_idx, bool is_contour); +Polygon apply_fuzzy_skin(const Polygon &polygon, const PrintRegionConfig &base_config, const PerimeterRegions &perimeter_regions, size_t layer_idx, size_t perimeter_idx, bool is_contour); + +Arachne::ExtrusionLine apply_fuzzy_skin(const Arachne::ExtrusionLine &extrusion, const PrintRegionConfig &base_config, const PerimeterRegions &perimeter_regions, size_t layer_idx, size_t perimeter_idx, bool is_contour); + } // namespace Slic3r::Feature::FuzzySkin #endif // libslic3r_FuzzySkin_hpp_ diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 01f8dd7f8f..fa0e11b5a1 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -206,8 +206,7 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator // loops is an arrayref of ::Loop objects // turn each one into an ExtrusionLoop object - ExtrusionEntityCollection coll; - Polygon fuzzified; + ExtrusionEntityCollection coll; for (const PerimeterGeneratorLoop &loop : loops) { bool is_external = loop.is_external(); @@ -223,12 +222,8 @@ static ExtrusionEntityCollection traverse_loops_classic(const PerimeterGenerator loop_role = elrDefault; } - const bool fuzzify = should_fuzzify(params.config, params.layer_id, loop.depth, loop.is_contour); - const Polygon &polygon = fuzzify ? fuzzified : loop.polygon; - if (fuzzify) { - fuzzified = loop.polygon; - fuzzy_polygon(fuzzified, scaled(params.config.fuzzy_skin_thickness.value), scaled(params.config.fuzzy_skin_point_dist.value)); - } + // Apply fuzzy skin if it is enabled for at least some part of the polygon. + const Polygon polygon = apply_fuzzy_skin(loop.polygon, params.config, params.perimeter_regions, params.layer_id, loop.depth, loop.is_contour); ExtrusionPaths paths; if (params.config.overhangs && params.layer_id > params.object_config.raft_layers && @@ -425,7 +420,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P ExtrusionEntityCollection extrusion_coll; for (Arachne::PerimeterOrder::PerimeterExtrusion &pg_extrusion : pg_extrusions) { - Arachne::ExtrusionLine &extrusion = pg_extrusion.extrusion; + Arachne::ExtrusionLine extrusion = pg_extrusion.extrusion; if (extrusion.empty()) continue; @@ -433,9 +428,8 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P ExtrusionRole role_normal = is_external ? ExtrusionRole::ExternalPerimeter : ExtrusionRole::Perimeter; ExtrusionRole role_overhang = role_normal | ExtrusionRoleModifier::Bridge; - const bool fuzzify = should_fuzzify(params.config, params.layer_id, pg_extrusion.extrusion.inset_idx, !pg_extrusion.extrusion.is_closed || pg_extrusion.is_contour()); - if (fuzzify) - fuzzy_extrusion_line(extrusion, scaled(params.config.fuzzy_skin_thickness.value), scaled(params.config.fuzzy_skin_point_dist.value)); + // Apply fuzzy skin if it is enabled for at least some part of the ExtrusionLine. + extrusion = apply_fuzzy_skin(extrusion, params.config, params.perimeter_regions, params.layer_id, pg_extrusion.extrusion.inset_idx, !pg_extrusion.extrusion.is_closed || pg_extrusion.is_contour()); ExtrusionPaths paths; // detect overhanging/bridging perimeters