From 4b022b8287ddeb30d48d5bad2ae34a20f19e3b41 Mon Sep 17 00:00:00 2001 From: "xun.zhang" Date: Sat, 10 May 2025 16:41:38 +0800 Subject: [PATCH] ENH: smooth overhang degree in arachne mode jira: STUDIO-12110,STUDIO-11630 Signed-off-by: xun.zhang Change-Id: I4e430dd2cea4bd4ad206e699d574abed3a656ce2 --- src/libslic3r/Arachne/utils/ExtrusionLine.cpp | 16 ++++++-- src/libslic3r/Arachne/utils/ExtrusionLine.hpp | 7 ++-- src/libslic3r/MultiPoint.hpp | 5 ++- src/libslic3r/OverhangDetector.cpp | 41 +++++++++++-------- src/libslic3r/OverhangDetector.hpp | 3 +- src/libslic3r/PerimeterGenerator.cpp | 8 ++-- src/libslic3r/Polyline.hpp | 2 +- src/libslic3r/VariableWidth.cpp | 2 +- src/libslic3r/VariableWidth.hpp | 2 +- 9 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp index 923738cc8..ab2188fe0 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp @@ -278,7 +278,17 @@ double ExtrusionLine::area() const } // namespace Slic3r::Arachne namespace Slic3r { -void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, int overhang) + +void extrusion_paths_append(std::list &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, double overhang) +{ + for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) { + ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path); + ExtrusionPaths path = thick_polyline_to_multi_path(thick_polyline, role, flow, scaled(0.05), float(SCALED_EPSILON), overhang).paths; + dst.insert(dst.end(), std::make_move_iterator(path.begin()), std::make_move_iterator(path.end())); + } +} + +void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, double overhang) { for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) { ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path); @@ -286,13 +296,13 @@ void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extr } } -void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow, int overhang) +void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow, double overhang) { ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion); Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled(0.05), float(SCALED_EPSILON), overhang).paths); } -void extrusion_path_append(ExtrusionPaths &dst, const ThickPolyline &thick_polyline, const ExtrusionRole role, const Flow &flow, int overhang) +void extrusion_path_append(ExtrusionPaths &dst, const ThickPolyline &thick_polyline, const ExtrusionRole role, const Flow &flow, double overhang) { Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled(0.05), float(SCALED_EPSILON), overhang).paths); } diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp index 09bacdd8d..ac581eede 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp @@ -301,9 +301,10 @@ using VariableWidthLines = std::vector; // &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, double overhang = 0); +void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, double overhang = 0); +void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow, double overhang = 0); +void extrusion_path_append(ExtrusionPaths &dst, const ThickPolyline &thick_polyline, const ExtrusionRole role, const Flow &flow, double overhang = 0); } // namespace Slic3r #endif // UTILS_EXTRUSION_LINE_H diff --git a/src/libslic3r/MultiPoint.hpp b/src/libslic3r/MultiPoint.hpp index 605ce5512..63c28cc98 100644 --- a/src/libslic3r/MultiPoint.hpp +++ b/src/libslic3r/MultiPoint.hpp @@ -19,11 +19,12 @@ public: MultiPoint() {} MultiPoint(const MultiPoint &other) : points(other.points) {} - MultiPoint(MultiPoint &&other) : points(std::move(other.points)) {} + MultiPoint(MultiPoint &&other) noexcept : points(std::move(other.points)) {} MultiPoint(std::initializer_list list) : points(list) {} explicit MultiPoint(const Points &_points) : points(_points) {} + MultiPoint(Points&& _points) noexcept: points(std::move(_points)){} MultiPoint& operator=(const MultiPoint &other) { points = other.points; return *this; } - MultiPoint& operator=(MultiPoint &&other) { points = std::move(other.points); return *this; } + MultiPoint& operator=(MultiPoint &&other) noexcept { points = std::move(other.points); return *this; } void scale(double factor); void scale(double factor_x, double factor_y); void translate(double x, double y) { this->translate(Point(coord_t(x), coord_t(y))); } diff --git a/src/libslic3r/OverhangDetector.cpp b/src/libslic3r/OverhangDetector.cpp index ac5669e13..27bb33163 100644 --- a/src/libslic3r/OverhangDetector.cpp +++ b/src/libslic3r/OverhangDetector.cpp @@ -173,6 +173,7 @@ namespace Slic3r { const double nozzle_diameter) { ExtrusionPaths ret_paths; + std::list ret_path_list; ZPaths paths_in_range = clip_extrusion(extrusion_path, clip_paths, ClipperLib_Z::ctIntersection); //doing intersection first would be faster. paths_in_range = add_sampling_points(paths_in_range, scale_(2));// enough? @@ -184,13 +185,15 @@ namespace Slic3r { for (auto& p : path) { assert(p.z() != 0); } } - auto in_same_degree_range = [](double a, double b) -> bool { - int ceil_a = std::ceil(a); - int floor_a = std::floor(a); - int ceil_b = std::ceil(b); - int floor_b = std::floor(b); - return ceil_a == ceil_b && floor_a == floor_b; - }; + auto get_base_degree = [](double d){ + return std::floor(d/min_degree_gap_arachne) * min_degree_gap_arachne; + }; + + auto in_same_degree_range = [&](double a, double b) -> bool { + double base_a = get_base_degree(a); + double base_b = get_base_degree(b); + return std::abs(base_a - base_b) < EPSILON; + }; struct SplitPoint { @@ -199,11 +202,10 @@ namespace Slic3r { double degree; }; - auto get_split_points = [](const Point& pa, const Point& pb, const coord_t wa, const coord_t wb, const double da, const double db) -> std::vector { + auto get_split_points = [&](const Point& pa, const Point& pb, const coord_t wa, const coord_t wb, const double da, const double db) -> std::vector { std::vector ret; - - int start_d = (int)(std::ceil(std::min(da, db))); - int end_d = (int)(std::floor(std::max(da, db))); + double start_d = get_base_degree(std::min(da, db)) + min_degree_gap_arachne; + double end_d = get_base_degree(std::max(da, db)); if (start_d > end_d) return ret; @@ -211,7 +213,7 @@ namespace Slic3r { if (std::abs(delta_d) < 1e-6) return ret; if (da < db) { - for (int k = start_d; k <= end_d; ++k) { + for (double k = start_d; k <= end_d; k+=min_degree_gap_arachne) { const double t = (k - da) / delta_d; const Point pt = pa + (pb - pa) * t; const coord_t w = wa + coord_t((wb - wa) * t); @@ -219,14 +221,13 @@ namespace Slic3r { } } else { - for (int k = end_d; k >= start_d; --k) { + for (double k = end_d; k >= start_d; k-=min_degree_gap_arachne) { const double t = (k - da) / delta_d; const Point pt = pa + (pb - pa) * t; const coord_t w = wa + coord_t((wb - wa) * t); ret.emplace_back(SplitPoint{ pt, w, (double)k }); } } - return ret; }; @@ -287,11 +288,11 @@ namespace Slic3r { for (auto& split_point : split_points) { prev_line.push_back({ split_point.p.x(), split_point.p.y(), split_point.w }); double target_degree = 0; - if (prev_d < curr_d) - target_degree = split_point.degree - 1; + if( prev_d < curr_d) + target_degree = split_point.degree - min_degree_gap_arachne; else target_degree = split_point.degree; - extrusion_paths_append(ret_paths, { prev_line }, role, flow, target_degree); + extrusion_paths_append(ret_path_list , { prev_line }, role, flow, target_degree); prev_line.clear(); prev_line.push_back({ split_point.p.x(), split_point.p.y(), split_point.w }); } @@ -301,8 +302,12 @@ namespace Slic3r { prev_line.push_back(path[idx]); } } - if (prev_line.size() > 1) { extrusion_paths_append(ret_paths, { prev_line }, role, flow, std::floor(prev_d)); } + if (prev_line.size() > 1) { extrusion_paths_append(ret_path_list, { prev_line }, role, flow, get_base_degree(prev_d)); } } + + ret_paths.reserve(ret_path_list.size()); + ret_paths.insert(ret_paths.end(), std::make_move_iterator(ret_path_list.begin()), std::make_move_iterator(ret_path_list.end())); + return ret_paths; } diff --git a/src/libslic3r/OverhangDetector.hpp b/src/libslic3r/OverhangDetector.hpp index 002953b68..5ff07249d 100644 --- a/src/libslic3r/OverhangDetector.hpp +++ b/src/libslic3r/OverhangDetector.hpp @@ -10,7 +10,8 @@ using ZPath = ClipperLib_Z::Path; using ZPaths = ClipperLib_Z::Paths; static const int overhang_sampling_number = 6; -static const double min_degree_gap = 0.1; +static const double min_degree_gap_classic = 0.1; +static const double min_degree_gap_arachne = 0.25; static const int max_overhang_degree = overhang_sampling_number - 1; static const std::vector non_uniform_degree_map = { 0, 10, 25, 50, 75, 100}; static const int insert_point_count = 3; diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index e8b549bf2..5a910f5c1 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -243,14 +243,14 @@ static std::deque split_polyline_by_degree(const Polyline &p size_t poly_size = polyline_with_insert_points.size(); // BBS: merge degree in limited range //find first degee base - double degree_base = int(points_overhang[points_overhang.size() - 1] / min_degree_gap) * min_degree_gap + min_degree_gap; + double degree_base = int(points_overhang[points_overhang.size() - 1] / min_degree_gap_classic) * min_degree_gap_classic + min_degree_gap_classic; degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base; double short_poly_len = 0; for (int point_idx = points_overhang.size() - 2; point_idx > 0; --point_idx) { double degree = points_overhang[point_idx]; - if ( degree <= degree_base && degree >= degree_base - min_degree_gap ) + if ( degree <= degree_base && degree >= degree_base - min_degree_gap_classic ) continue; temp_copy.split_at_index(point_idx, &left, &right); @@ -258,7 +258,7 @@ static std::deque split_polyline_by_degree(const Polyline &p temp_copy = std::move(left); out.push_back(PolylineWithDegree(right, degree_base)); - degree_base = int(degree / min_degree_gap) * min_degree_gap + min_degree_gap; + degree_base = int(degree / min_degree_gap_classic) * min_degree_gap_classic + min_degree_gap_classic; degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base; } @@ -279,7 +279,7 @@ static void insert_point_to_line( double left_point_degree, { Line line_temp(left_point, right_point); double line_length = line_temp.length(); - if (std::abs(left_point_degree - right_point_degree) <= 0.5 * min_degree_gap || line_length list) : MultiPoint(list) { fitting_result.clear(); } diff --git a/src/libslic3r/VariableWidth.cpp b/src/libslic3r/VariableWidth.cpp index b7c5fd174..d1cf8759d 100644 --- a/src/libslic3r/VariableWidth.cpp +++ b/src/libslic3r/VariableWidth.cpp @@ -2,7 +2,7 @@ namespace Slic3r { -ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance, int overhang) +ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance, double overhang) { ExtrusionMultiPath multi_path; ExtrusionPath path(role); diff --git a/src/libslic3r/VariableWidth.hpp b/src/libslic3r/VariableWidth.hpp index 311df2ccc..f4ff508ac 100644 --- a/src/libslic3r/VariableWidth.hpp +++ b/src/libslic3r/VariableWidth.hpp @@ -6,7 +6,7 @@ #include "Flow.hpp" namespace Slic3r { - ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance, int overhang); + ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance, double overhang); void variable_width(const ThickPolylines& polylines, ExtrusionRole role, const Flow& flow, std::vector& out); }