From f7f10f854cb0793f80023b4782a3a5843034318f Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 3 Jul 2024 18:08:06 +0200 Subject: [PATCH 1/3] Fuzzy skin: Allow 'inside' to be not just definite 2d holes. Expand the 'only fuzzy in outside' setting to also mean things the user reasonably could consider inside, instead of just completely closed holes. Take the (approximate) convex hull of the shape, take the difference to get candidate parts that could be considered to be inside of the shape -- then, for each part, determine where it touches the outside. The ratio between how much 'outside' outline and total outline of such a shape (as well as a general size of the hole if ther _is_ any 'outside') determines if points on the polygon thouching that part (outside of the original polygon but inside the approx convex hull) will get 'fuzzed' or not. part of CURA-11887 --- src/FffPolygonGenerator.cpp | 42 ++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/FffPolygonGenerator.cpp b/src/FffPolygonGenerator.cpp index 10a1336995..e8c62b544b 100644 --- a/src/FffPolygonGenerator.cpp +++ b/src/FffPolygonGenerator.cpp @@ -1081,6 +1081,7 @@ void FffPolygonGenerator::processFuzzyWalls(SliceMeshStorage& mesh) return; } + constexpr coord_t epsilon = 5; // the distance between two points that are considered to be the same const coord_t line_width = mesh.settings.get("line_width"); const bool apply_outside_only = mesh.settings.get("magic_fuzzy_skin_outside_only"); const coord_t fuzziness = mesh.settings.get("magic_fuzzy_skin_thickness"); @@ -1115,20 +1116,30 @@ void FffPolygonGenerator::processFuzzyWalls(SliceMeshStorage& mesh) if (apply_outside_only) { - hole_area = part.print_outline.getOutsidePolygons().offset(-line_width); - accumulate_is_in_hole = [&hole_area](const bool& prev_result, const ExtrusionJunction& junction) + hole_area.clear(); + const auto initial_hole_area = part.print_outline.approxConvexHull().difference(part.print_outline.offset(epsilon)).offset(line_width - epsilon); + const auto near_shape_area = part.print_outline.offset(line_width / 2 + epsilon); + + for (const auto& hole_part : initial_hole_area.splitIntoParts()) { - return prev_result || hole_area.inside(junction.p_); - }; + const auto thick_outline = hole_part.createTubeShape(line_width / 2, 0); + const auto total_area_size = thick_outline.area(); + const auto open_area_size = thick_outline.difference(near_shape_area).area(); + + constexpr double max_ratio = 0.45; // TODO: make this a setting + constexpr coord_t min_part_area = 1000000; // TODO: make this a setting + if ((open_area_size == 0 || hole_part.area() >= min_part_area) && (open_area_size / total_area_size) < max_ratio) + { + hole_area.push_back(hole_part); + } + } + } + else + { + hole_area = Shape(); } for (auto& line : toolpath) { - if (apply_outside_only && std::accumulate(line.begin(), line.end(), false, accumulate_is_in_hole)) - { - result_lines.push_back(line); - continue; - } - auto& result = result_lines.emplace_back(line.inset_idx_, line.is_odd_, line.is_closed_); // generate points in between p0 and p1 @@ -1142,6 +1153,17 @@ void FffPolygonGenerator::processFuzzyWalls(SliceMeshStorage& mesh) result.emplace_back(p1.p_, p1.w_, p1.perimeter_index_); continue; } + if (apply_outside_only && hole_area.inside(p1.p_) && hole_area.inside(p0->p_)) // avoid 'inside' + { + if (result.size() > 0 && result.back().p_ != p0->p_) + { + // Ensure the wall starts on the previous vertex. + result.emplace_back(p0->p_, p0->w_, p0->perimeter_index_); + } + result.emplace_back(p1.p_, p1.w_, p1.perimeter_index_); + p0 = &p1; + continue; + } // 'a' is the (next) new point between p0 and p1 const Point2LL p0p1 = p1.p_ - p0->p_; From 9f6afd301448be2ef7ac4c07691ff5597fa5b2fa Mon Sep 17 00:00:00 2001 From: rburema Date: Wed, 3 Jul 2024 16:09:07 +0000 Subject: [PATCH 2/3] Applied clang-format. --- src/FffPolygonGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FffPolygonGenerator.cpp b/src/FffPolygonGenerator.cpp index e8c62b544b..9ff4072fbe 100644 --- a/src/FffPolygonGenerator.cpp +++ b/src/FffPolygonGenerator.cpp @@ -1126,8 +1126,8 @@ void FffPolygonGenerator::processFuzzyWalls(SliceMeshStorage& mesh) const auto total_area_size = thick_outline.area(); const auto open_area_size = thick_outline.difference(near_shape_area).area(); - constexpr double max_ratio = 0.45; // TODO: make this a setting - constexpr coord_t min_part_area = 1000000; // TODO: make this a setting + constexpr double max_ratio = 0.45; // TODO: make this a setting + constexpr coord_t min_part_area = 1000000; // TODO: make this a setting if ((open_area_size == 0 || hole_part.area() >= min_part_area) && (open_area_size / total_area_size) < max_ratio) { hole_area.push_back(hole_part); From 1e48764ecdcb191a08998d3f00241a7b8bcc17ab Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 4 Jul 2024 09:15:47 +0200 Subject: [PATCH 3/3] Use new settings for 'inside' detection fuzzy-skin outside-only. Also make the ratio always true even when 0 by replacing < with <=, so fully enclosed areas don't get fuzzed/jittered ever if outside only is on. part CURA-11887 --- src/FffPolygonGenerator.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/FffPolygonGenerator.cpp b/src/FffPolygonGenerator.cpp index 9ff4072fbe..5371fdf74c 100644 --- a/src/FffPolygonGenerator.cpp +++ b/src/FffPolygonGenerator.cpp @@ -1084,6 +1084,8 @@ void FffPolygonGenerator::processFuzzyWalls(SliceMeshStorage& mesh) constexpr coord_t epsilon = 5; // the distance between two points that are considered to be the same const coord_t line_width = mesh.settings.get("line_width"); const bool apply_outside_only = mesh.settings.get("magic_fuzzy_skin_outside_only"); + const Ratio inside_max_part_ratio = mesh.settings.get("magic_fuzzy_skin_outside_convex_ratio"); + const double inside_min_part_area = MM2_2INT(mesh.settings.get("magic_fuzzy_skin_outside_min_area")); const coord_t fuzziness = mesh.settings.get("magic_fuzzy_skin_thickness"); const coord_t avg_dist_between_points = mesh.settings.get("magic_fuzzy_skin_point_dist"); const coord_t min_dist_between_points = avg_dist_between_points * 3 / 4; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value @@ -1125,10 +1127,7 @@ void FffPolygonGenerator::processFuzzyWalls(SliceMeshStorage& mesh) const auto thick_outline = hole_part.createTubeShape(line_width / 2, 0); const auto total_area_size = thick_outline.area(); const auto open_area_size = thick_outline.difference(near_shape_area).area(); - - constexpr double max_ratio = 0.45; // TODO: make this a setting - constexpr coord_t min_part_area = 1000000; // TODO: make this a setting - if ((open_area_size == 0 || hole_part.area() >= min_part_area) && (open_area_size / total_area_size) < max_ratio) + if ((open_area_size == 0 || hole_part.area() >= inside_min_part_area) && (open_area_size / total_area_size) <= inside_max_part_ratio) { hole_area.push_back(hole_part); }