From 3c9f3d2b6676365cff5c5ca406145c6f999d528e Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 6 Jan 2021 11:05:22 +0100 Subject: [PATCH] Fixing the infill order for concentric infill to outside-in. Relies to: Concentric Fill Start Point - New Feature Request #4948 Feature Request: Archimedean Chords - Option to define direction of travel (Inside-Out or Outside-In) #5214 --- src/libslic3r/ClipperUtils.cpp | 40 ++++++++++----------------- src/libslic3r/ClipperUtils.hpp | 2 +- src/libslic3r/Fill/FillConcentric.cpp | 8 +++--- src/libslic3r/Fill/FillConcentric.hpp | 2 +- src/libslic3r/Print.cpp | 5 +--- 5 files changed, 21 insertions(+), 36 deletions(-) diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index 59872ad66..305ea134f 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -716,45 +716,33 @@ static void traverse_pt_noholes(const ClipperLib::PolyNodes &nodes, Polygons *ou }); } -static void traverse_pt_old(ClipperLib::PolyNodes &nodes, Polygons* retval) +static void traverse_pt_outside_in(const ClipperLib::PolyNodes &nodes, Polygons *retval) { - /* use a nearest neighbor search to order these children - TODO: supply start_near to chained_path() too? */ - // collect ordering points Points ordering_points; ordering_points.reserve(nodes.size()); - for (ClipperLib::PolyNodes::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { - Point p((*it)->Contour.front().X, (*it)->Contour.front().Y); - ordering_points.push_back(p); - } - - // perform the ordering - ClipperLib::PolyNodes ordered_nodes = chain_clipper_polynodes(ordering_points, nodes); - - // push results recursively - for (ClipperLib::PolyNodes::iterator it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) { + for (const ClipperLib::PolyNode *node : nodes) + ordering_points.emplace_back(node->Contour.front().X, node->Contour.front().Y); + + // Perform the ordering, push results recursively. + //FIXME pass the last point to chain_clipper_polynodes? + for (const ClipperLib::PolyNode *node : chain_clipper_polynodes(ordering_points, nodes)) { + retval->emplace_back(ClipperPath_to_Slic3rPolygon(node->Contour)); + if (node->IsHole()) + // Orient a hole, which is clockwise oriented, to CCW. + retval->back().reverse(); // traverse the next depth - traverse_pt_old((*it)->Childs, retval); - retval->push_back(ClipperPath_to_Slic3rPolygon((*it)->Contour)); - if ((*it)->IsHole()) retval->back().reverse(); // ccw + traverse_pt_outside_in(node->Childs, retval); } } -Polygons union_pt_chained(const Polygons &subject, bool safety_offset_) +Polygons union_pt_chained_outside_in(const Polygons &subject, bool safety_offset_) { ClipperLib::PolyTree polytree = union_pt(subject, safety_offset_); Polygons retval; - traverse_pt_old(polytree.Childs, &retval); + traverse_pt_outside_in(polytree.Childs, &retval); return retval; - -// TODO: This needs to be tested: -// ClipperLib::PolyTree polytree = union_pt(subject, safety_offset_); - -// Polygons retval; -// traverse_pt_noholes(polytree.Childs, &retval); -// return retval; } Polygons simplify_polygons(const Polygons &subject, bool preserve_collinear) diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp index 0828ec21f..cd966435b 100644 --- a/src/libslic3r/ClipperUtils.hpp +++ b/src/libslic3r/ClipperUtils.hpp @@ -219,7 +219,7 @@ ClipperLib::PolyTree union_pt(const Slic3r::ExPolygons &subject, bool safety_off ClipperLib::PolyTree union_pt(Slic3r::Polygons &&subject, bool safety_offset_ = false); ClipperLib::PolyTree union_pt(Slic3r::ExPolygons &&subject, bool safety_offset_ = false); -Slic3r::Polygons union_pt_chained(const Slic3r::Polygons &subject, bool safety_offset_ = false); +Slic3r::Polygons union_pt_chained_outside_in(const Slic3r::Polygons &subject, bool safety_offset_ = false); ClipperLib::PolyNodes order_nodes(const ClipperLib::PolyNodes &nodes); diff --git a/src/libslic3r/Fill/FillConcentric.cpp b/src/libslic3r/Fill/FillConcentric.cpp index 87bddeb61..1b96c43a4 100644 --- a/src/libslic3r/Fill/FillConcentric.cpp +++ b/src/libslic3r/Fill/FillConcentric.cpp @@ -24,22 +24,22 @@ void FillConcentric::_fill_surface_single( this->spacing = unscale(distance); } - Polygons loops = (Polygons)expolygon; + Polygons loops = to_polygons(std::move(expolygon)); Polygons last = loops; while (! last.empty()) { last = offset2(last, -(distance + min_spacing/2), +min_spacing/2); - loops.insert(loops.end(), last.begin(), last.end()); + append(loops, last); } // generate paths from the outermost to the innermost, to avoid // adhesion problems of the first central tiny loops - loops = union_pt_chained(loops, false); + loops = union_pt_chained_outside_in(loops, false); // split paths using a nearest neighbor search size_t iPathFirst = polylines_out.size(); Point last_pos(0, 0); for (const Polygon &loop : loops) { - polylines_out.push_back(loop.split_at_index(last_pos.nearest_point_index(loop.points))); + polylines_out.emplace_back(loop.split_at_index(last_pos.nearest_point_index(loop.points))); last_pos = polylines_out.back().last_point(); } diff --git a/src/libslic3r/Fill/FillConcentric.hpp b/src/libslic3r/Fill/FillConcentric.hpp index 04c2f4e31..8bf01d11d 100644 --- a/src/libslic3r/Fill/FillConcentric.hpp +++ b/src/libslic3r/Fill/FillConcentric.hpp @@ -8,7 +8,7 @@ namespace Slic3r { class FillConcentric : public Fill { public: - ~FillConcentric() override {} + ~FillConcentric() override = default; protected: Fill* clone() const override { return new FillConcentric(*this); }; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 64fe751a3..693c4e5be 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1851,10 +1851,7 @@ void Print::_make_brim() } polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing()))); } - loops = union_pt_chained(loops, false); - // The function above produces ordering well suited for concentric infill (from outside to inside). - // For Brim, the ordering should be reversed (from inside to outside). - std::reverse(loops.begin(), loops.end()); + loops = union_pt_chained_outside_in(loops, false); // If there is a possibility that brim intersects skirt, go through loops and split those extrusions // The result is either the original Polygon or a list of Polylines