diff --git a/src/libslic3r/Arachne/WallToolPaths.cpp b/src/libslic3r/Arachne/WallToolPaths.cpp index 803d6d2c14..6204a0546a 100644 --- a/src/libslic3r/Arachne/WallToolPaths.cpp +++ b/src/libslic3r/Arachne/WallToolPaths.cpp @@ -18,6 +18,8 @@ #include +//#define ARACHNE_STITCH_PATCH_DEBUG + namespace Slic3r::Arachne { @@ -549,7 +551,7 @@ void WallToolPaths::stitchToolPaths(std::vector &toolpaths, VariableWidthLines stitched_polylines; VariableWidthLines closed_polygons; PolylineStitcher::stitch(wall_lines, stitched_polylines, closed_polygons, stitch_distance); -#ifdef DEBUG +#ifdef ARACHNE_STITCH_PATCH_DEBUG for (const ExtrusionLine& line : stitched_polylines) { if ( ! line.is_odd && line.polylineLength() > 3 * stitch_distance && line.size() > 3) { BOOST_LOG_TRIVIAL(error) << "Some even contour lines could not be closed into polygons!"; @@ -608,7 +610,7 @@ void WallToolPaths::stitchToolPaths(std::vector &toolpaths, } } } -#endif // DEBUG +#endif // ARACHNE_STITCH_PATCH_DEBUG wall_lines = stitched_polylines; // replace input toolpaths with stitched polylines for (ExtrusionLine& wall_polygon : closed_polygons) diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp index 0b9c9a7b17..c594b8b91e 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp @@ -232,6 +232,35 @@ int64_t ExtrusionLine::calculateExtrusionAreaDeviationError(ExtrusionJunction A, } } +bool ExtrusionLine::is_contour() const +{ + if (!this->is_closed) + return false; + + Polygon poly; + poly.points.reserve(this->junctions.size()); + for (const ExtrusionJunction &junction : this->junctions) + poly.points.emplace_back(junction.p); + + // Arachne produces contour with clockwise orientation and holes with counterclockwise orientation. + return poly.is_clockwise(); +} + +double ExtrusionLine::area() const +{ + assert(this->is_closed); + double a = 0.; + if (this->junctions.size() >= 3) { + Vec2d p1 = this->junctions.back().p.cast(); + for (const ExtrusionJunction &junction : this->junctions) { + Vec2d p2 = junction.p.cast(); + a += cross2(p1, p2); + p1 = p2; + } + } + return 0.5 * a; +} + } // namespace Slic3r::Arachne namespace Slic3r { diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp index a7189cebd2..7ac1a3c4c8 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp @@ -189,6 +189,10 @@ struct ExtrusionLine * \param weighted_average_width The weighted average of the widths of the two colinear extrusion segments * */ static int64_t calculateExtrusionAreaDeviationError(ExtrusionJunction A, ExtrusionJunction B, ExtrusionJunction C, coord_t& weighted_average_width); + + bool is_contour() const; + + double area() const; }; static inline Slic3r::ThickPolyline to_thick_polyline(const Arachne::ExtrusionLine &line_junctions) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index b2215ee06a..75bdc12ae3 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -354,6 +354,8 @@ static ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Path &subject, con struct PerimeterGeneratorArachneExtrusion { Arachne::ExtrusionLine *extrusion = nullptr; + // Indicates if closed ExtrusionLine is a contour or a hole. Used it only when ExtrusionLine is a closed loop. + bool is_contour = false; // Should this extrusion be fuzzyfied on path generation? bool fuzzify = false; }; @@ -414,11 +416,18 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p // Append paths to collection. if (!paths.empty()) { - if (extrusion->is_closed) - extrusion_coll.entities.emplace_back(new ExtrusionLoop(std::move(paths))); - else + if (extrusion->is_closed) { + ExtrusionLoop extrusion_loop(std::move(paths)); + // Restore the orientation of the extrusion loop. + if (pg_extrusion.is_contour) + extrusion_loop.make_counter_clockwise(); + else + extrusion_loop.make_clockwise(); + + extrusion_coll.append(std::move(extrusion_loop)); + } else for (ExtrusionPath &path : paths) - extrusion_coll.entities.emplace_back(new ExtrusionPath(std::move(path))); + extrusion_coll.append(ExtrusionPath(std::move(path))); } } @@ -541,7 +550,7 @@ void PerimeterGenerator::process_arachne() } auto &best_path = all_extrusions[best_candidate]; - ordered_extrusions.push_back({best_path, false}); + ordered_extrusions.push_back({best_path, best_path->is_contour(), false}); processed[best_candidate] = true; for (size_t unlocked_idx : blocking[best_candidate]) blocked[unlocked_idx]--;