From 6582182e0c47ffd231c2d84808715a4209108fe2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 13 Dec 2016 19:22:23 +0100 Subject: [PATCH] Adapted to the new ClipperUtils.hpp interface by @alexrj --- lib/Slic3r/Geometry/Clipper.pm | 6 +- lib/Slic3r/Print/Object.pm | 2 +- xs/src/libslic3r/BridgeDetector.cpp | 134 ++- xs/src/libslic3r/BridgeDetector.hpp | 1 - xs/src/libslic3r/ClipperUtils.cpp | 956 ++++++---------------- xs/src/libslic3r/ClipperUtils.hpp | 260 +++--- xs/src/libslic3r/EdgeGrid.hpp | 3 +- xs/src/libslic3r/ExPolygon.cpp | 29 +- xs/src/libslic3r/ExtrusionEntity.cpp | 18 +- xs/src/libslic3r/ExtrusionEntity.hpp | 20 + xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp | 2 +- xs/src/libslic3r/Fill/FillBase.cpp | 3 +- xs/src/libslic3r/Fill/FillConcentric.cpp | 2 +- xs/src/libslic3r/Fill/FillHoneycomb.cpp | 4 +- xs/src/libslic3r/Fill/FillPlanePath.cpp | 2 +- xs/src/libslic3r/Fill/FillRectilinear.cpp | 2 +- xs/src/libslic3r/GCode.cpp | 3 +- xs/src/libslic3r/Layer.cpp | 15 +- xs/src/libslic3r/LayerRegion.cpp | 3 +- xs/src/libslic3r/MotionPlanner.cpp | 8 +- xs/src/libslic3r/PerimeterGenerator.cpp | 43 +- xs/src/libslic3r/Polygon.cpp | 7 +- xs/src/libslic3r/Print.cpp | 11 +- xs/src/libslic3r/PrintObject.cpp | 14 +- xs/src/libslic3r/SupportMaterial.cpp | 33 +- xs/src/libslic3r/TriangleMesh.cpp | 17 +- xs/src/perlglue.cpp | 3 +- xs/t/11_clipper.t | 48 +- xs/xsp/Clipper.xsp | 69 +- xs/xsp/Polyline.xsp | 2 +- xs/xsp/Surface.xsp | 2 +- 31 files changed, 600 insertions(+), 1122 deletions(-) diff --git a/lib/Slic3r/Geometry/Clipper.pm b/lib/Slic3r/Geometry/Clipper.pm index 16dfa6f6b..37fc89914 100644 --- a/lib/Slic3r/Geometry/Clipper.pm +++ b/lib/Slic3r/Geometry/Clipper.pm @@ -5,9 +5,9 @@ use warnings; require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw(offset offset_ex - diff_ex diff union_ex intersection_ex xor_ex JT_ROUND JT_MITER - JT_SQUARE is_counter_clockwise union_pt offset2 offset2_ex + diff_ex diff union_ex intersection_ex JT_ROUND JT_MITER + JT_SQUARE is_counter_clockwise offset2 offset2_ex intersection intersection_pl diff_pl union - union_pt_chained diff_ppl intersection_ppl); + union_pt_chained); 1; diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 18768b828..720294cd0 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -7,7 +7,7 @@ use List::Util qw(min max sum first); use Slic3r::Flow ':roles'; use Slic3r::Geometry qw(X Y Z PI scale unscale chained_path epsilon); use Slic3r::Geometry::Clipper qw(diff diff_ex intersection intersection_ex union union_ex - offset offset_ex offset2 offset2_ex intersection_ppl JT_MITER); + offset offset_ex offset2 offset2_ex JT_MITER); use Slic3r::Print::State ':steps'; use Slic3r::Surface ':types'; diff --git a/xs/src/libslic3r/BridgeDetector.cpp b/xs/src/libslic3r/BridgeDetector.cpp index 7e54bcf69..fa27134dc 100644 --- a/xs/src/libslic3r/BridgeDetector.cpp +++ b/xs/src/libslic3r/BridgeDetector.cpp @@ -40,13 +40,13 @@ void BridgeDetector::initialize() this->angle = -1.; // Outset our bridge by an arbitrary amout; we'll use this outer margin for detecting anchors. - Polygons grown = offset(this->expolygons, float(this->spacing)); + Polygons grown = offset(to_polygons(this->expolygons), float(this->spacing)); // Detect possible anchoring edges of this bridging region. // Detect what edges lie on lower slices by turning bridge contour and holes // into polylines and then clipping them with each lower slice's contour. // Currently _edges are only used to set a candidate direction of the bridge (see bridge_direction_candidates()). - intersection(to_polylines(grown), this->lower_slices.contours(), &this->_edges); + this->_edges = intersection_pl(to_polylines(grown), this->lower_slices.contours()); #ifdef SLIC3R_DEBUG printf(" bridge has " PRINTF_ZU " support(s)\n", this->_edges.size()); @@ -117,7 +117,7 @@ BridgeDetector::detect_angle() double total_length = 0; double max_length = 0; { - Lines clipped_lines = intersection(lines, clip_area); + Lines clipped_lines = intersection_ln(lines, clip_area); for (size_t i = 0; i < clipped_lines.size(); ++i) { const Line &line = clipped_lines[i]; if (expolygons_contain(this->_anchor_regions, line.a) && expolygons_contain(this->_anchor_regions, line.b)) { @@ -203,76 +203,72 @@ std::vector BridgeDetector::bridge_direction_candidates() const return angles; } -void -BridgeDetector::coverage(double angle, Polygons* coverage) const +Polygons BridgeDetector::coverage(double angle) const { - if (angle == -1) angle = this->angle; - if (angle == -1) return; + if (angle == -1) + angle = this->angle; - // Get anchors, convert them to Polygons and rotate them. - Polygons anchors = to_polygons(this->_anchor_regions); - polygons_rotate(anchors, PI/2.0 - angle); - Polygons covered; - for (ExPolygons::const_iterator it_expoly = this->expolygons.begin(); it_expoly != this->expolygons.end(); ++ it_expoly) - { - // Clone our expolygon and rotate it so that we work with vertical lines. - ExPolygon expolygon = *it_expoly; - expolygon.rotate(PI/2.0 - angle); + + if (angle != -1) { + + // Get anchors, convert them to Polygons and rotate them. + Polygons anchors = to_polygons(this->_anchor_regions); + polygons_rotate(anchors, PI/2.0 - angle); - /* Outset the bridge expolygon by half the amount we used for detecting anchors; - we'll use this one to generate our trapezoids and be sure that their vertices - are inside the anchors and not on their contours leading to false negatives. */ - ExPolygons grown = offset_ex(expolygon, 0.5f * float(this->spacing)); - - // Compute trapezoids according to a vertical orientation - Polygons trapezoids; - for (ExPolygons::const_iterator it = grown.begin(); it != grown.end(); ++it) - it->get_trapezoids2(&trapezoids, PI/2.0); - - for (Polygons::iterator trapezoid = trapezoids.begin(); trapezoid != trapezoids.end(); ++trapezoid) { - Lines supported = intersection(trapezoid->lines(), anchors); - size_t n_supported = 0; - // not nice, we need a more robust non-numeric check - for (size_t i = 0; i < supported.size(); ++i) - if (supported[i].length() >= this->spacing) - ++ n_supported; - if (n_supported >= 2) - covered.push_back(STDMOVE(*trapezoid)); + for (ExPolygons::const_iterator it_expoly = this->expolygons.begin(); it_expoly != this->expolygons.end(); ++ it_expoly) + { + // Clone our expolygon and rotate it so that we work with vertical lines. + ExPolygon expolygon = *it_expoly; + expolygon.rotate(PI/2.0 - angle); + + /* Outset the bridge expolygon by half the amount we used for detecting anchors; + we'll use this one to generate our trapezoids and be sure that their vertices + are inside the anchors and not on their contours leading to false negatives. */ + ExPolygons grown = offset_ex(expolygon, 0.5f * float(this->spacing)); + + // Compute trapezoids according to a vertical orientation + Polygons trapezoids; + for (ExPolygons::const_iterator it = grown.begin(); it != grown.end(); ++it) + it->get_trapezoids2(&trapezoids, PI/2.0); + + for (Polygons::iterator trapezoid = trapezoids.begin(); trapezoid != trapezoids.end(); ++trapezoid) { + Lines supported = intersection_ln(trapezoid->lines(), anchors); + size_t n_supported = 0; + // not nice, we need a more robust non-numeric check + for (size_t i = 0; i < supported.size(); ++i) + if (supported[i].length() >= this->spacing) + ++ n_supported; + if (n_supported >= 2) + covered.push_back(STDMOVE(*trapezoid)); + } } + + // Unite the trapezoids before rotation, as the rotation creates tiny gaps and intersections between the trapezoids + // instead of exact overlaps. + covered = union_(covered); + + // Intersect trapezoids with actual bridge area to remove extra margins and append it to result. + polygons_rotate(covered, -(PI/2.0 - angle)); + covered = intersection(covered, to_polygons(this->expolygons)); + + /* + if (0) { + my @lines = map @{$_->lines}, @$trapezoids; + $_->rotate(-(PI/2 - $angle), [0,0]) for @lines; + + require "Slic3r/SVG.pm"; + Slic3r::SVG::output( + "coverage_" . rad2deg($angle) . ".svg", + expolygons => [$self->expolygon], + green_expolygons => $self->_anchor_regions, + red_expolygons => $coverage, + lines => \@lines, + ); + } + */ } - - // Unite the trapezoids before rotation, as the rotation creates tiny gaps and intersections between the trapezoids - // instead of exact overlaps. - covered = union_(covered); - - // Intersect trapezoids with actual bridge area to remove extra margins and append it to result. - polygons_rotate(covered, -(PI/2.0 - angle)); - intersection(covered, to_polygons(this->expolygons), coverage); - - /* - if (0) { - my @lines = map @{$_->lines}, @$trapezoids; - $_->rotate(-(PI/2 - $angle), [0,0]) for @lines; - - require "Slic3r/SVG.pm"; - Slic3r::SVG::output( - "coverage_" . rad2deg($angle) . ".svg", - expolygons => [$self->expolygon], - green_expolygons => $self->_anchor_regions, - red_expolygons => $coverage, - lines => \@lines, - ); - } - */ -} - -Polygons -BridgeDetector::coverage(double angle) const -{ - Polygons pp; - this->coverage(angle, &pp); - return pp; + return covered; } /* This method returns the bridge edges (as polylines) that are not supported @@ -288,9 +284,7 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const for (ExPolygons::const_iterator it_expoly = this->expolygons.begin(); it_expoly != this->expolygons.end(); ++ it_expoly) { // get unsupported bridge edges (both contour and holes) - Polylines unuspported_polylines; - diff(to_polylines(*it_expoly), grown_lower, &unuspported_polylines); - Lines unsupported_lines = to_lines(unuspported_polylines); + Lines unsupported_lines = to_lines(diff_pl(to_polylines(*it_expoly), grown_lower)); /* Split into individual segments and filter out edges parallel to the bridging angle TODO: angle tolerance should probably be based on segment length and flow width, so that we build supports whenever there's a chance that at least one or two bridge diff --git a/xs/src/libslic3r/BridgeDetector.hpp b/xs/src/libslic3r/BridgeDetector.hpp index 825ce10b6..b04db63e4 100644 --- a/xs/src/libslic3r/BridgeDetector.hpp +++ b/xs/src/libslic3r/BridgeDetector.hpp @@ -32,7 +32,6 @@ public: BridgeDetector(ExPolygon _expolygon, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width); BridgeDetector(const ExPolygons &_expolygons, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width); bool detect_angle(); - void coverage(double angle, Polygons* coverage) const; Polygons coverage(double angle = -1) const; void unsupported_edges(double angle, Polylines* unsupported) const; Polylines unsupported_edges(double angle = -1) const; diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp index 5cc143540..e0de33586 100644 --- a/xs/src/libslic3r/ClipperUtils.cpp +++ b/xs/src/libslic3r/ClipperUtils.cpp @@ -25,144 +25,35 @@ bool clipper_export_enabled = false; // For debugging the Clipper library, for providing bug reports to the Clipper author. bool export_clipper_input_polygons_bin(const char *path, const ClipperLib::Paths &input_subject, const ClipperLib::Paths &input_clip) { - FILE *pfile = fopen(path, "wb"); - if (pfile == NULL) - return false; + FILE *pfile = fopen(path, "wb"); + if (pfile == NULL) + return false; - uint32_t sz = uint32_t(input_subject.size()); - fwrite(&sz, 1, sizeof(sz), pfile); - for (size_t i = 0; i < input_subject.size(); ++i) { - const ClipperLib::Path &path = input_subject[i]; - sz = uint32_t(path.size()); - ::fwrite(&sz, 1, sizeof(sz), pfile); - ::fwrite(path.data(), sizeof(ClipperLib::IntPoint), sz, pfile); - } - sz = uint32_t(input_clip.size()); - ::fwrite(&sz, 1, sizeof(sz), pfile); - for (size_t i = 0; i < input_clip.size(); ++i) { - const ClipperLib::Path &path = input_clip[i]; - sz = uint32_t(path.size()); - ::fwrite(&sz, 1, sizeof(sz), pfile); - ::fwrite(path.data(), sizeof(ClipperLib::IntPoint), sz, pfile); - } - ::fclose(pfile); - return true; + uint32_t sz = uint32_t(input_subject.size()); + fwrite(&sz, 1, sizeof(sz), pfile); + for (size_t i = 0; i < input_subject.size(); ++i) { + const ClipperLib::Path &path = input_subject[i]; + sz = uint32_t(path.size()); + ::fwrite(&sz, 1, sizeof(sz), pfile); + ::fwrite(path.data(), sizeof(ClipperLib::IntPoint), sz, pfile); + } + sz = uint32_t(input_clip.size()); + ::fwrite(&sz, 1, sizeof(sz), pfile); + for (size_t i = 0; i < input_clip.size(); ++i) { + const ClipperLib::Path &path = input_clip[i]; + sz = uint32_t(path.size()); + ::fwrite(&sz, 1, sizeof(sz), pfile); + ::fwrite(path.data(), sizeof(ClipperLib::IntPoint), sz, pfile); + } + ::fclose(pfile); + return true; err: - ::fclose(pfile); - return false; + ::fclose(pfile); + return false; } #endif /* CLIPPER_UTILS_DEBUG */ -//----------------------------------------------------------- -// legacy code from Clipper documentation -void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons* expolygons) -{ - size_t cnt = expolygons->size(); - expolygons->resize(cnt + 1); - ClipperPath_to_Slic3rMultiPoint(polynode.Contour, &(*expolygons)[cnt].contour); - (*expolygons)[cnt].holes.resize(polynode.ChildCount()); - for (int i = 0; i < polynode.ChildCount(); ++i) - { - ClipperPath_to_Slic3rMultiPoint(polynode.Childs[i]->Contour, &(*expolygons)[cnt].holes[i]); - //Add outer polygons contained by (nested within) holes ... - for (int j = 0; j < polynode.Childs[i]->ChildCount(); ++j) - AddOuterPolyNodeToExPolygons(*polynode.Childs[i]->Childs[j], expolygons); - } -} - -void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons* expolygons) -{ - PROFILE_FUNC(); - expolygons->clear(); - for (int i = 0; i < polytree.ChildCount(); ++i) - AddOuterPolyNodeToExPolygons(*polytree.Childs[i], expolygons); -} -//----------------------------------------------------------- - -template -void -ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input, T* output) -{ - PROFILE_FUNC(); - output->points.clear(); - output->points.reserve(input.size()); - for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit) - output->points.push_back(Slic3r::Point( (*pit).X, (*pit).Y )); -} -template void ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input, Slic3r::Polygon* output); - -template -void -ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input, T* output) -{ - PROFILE_FUNC(); - output->clear(); - output->reserve(input.size()); - for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it) { - typename T::value_type p; - ClipperPath_to_Slic3rMultiPoint(*it, &p); - output->push_back(p); - } -} - -void -ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, Slic3r::ExPolygons* output) -{ - PROFILE_FUNC(); - - // init Clipper - ClipperLib::Clipper clipper; - clipper.Clear(); - - // perform union - clipper.AddPaths(input, ClipperLib::ptSubject, true); - ClipperLib::PolyTree polytree; - clipper.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); // offset results work with both EvenOdd and NonZero - - // write to ExPolygons object - output->clear(); - PolyTreeToExPolygons(polytree, output); -} - -void -Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input, ClipperLib::Path* output) -{ - PROFILE_FUNC(); - - output->clear(); - output->reserve(input.points.size()); - for (Slic3r::Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) - output->push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); -} - -void -Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input, ClipperLib::Path* output) -{ - PROFILE_FUNC(); - - output->clear(); - output->reserve(input.points.size()); - for (Slic3r::Points::const_reverse_iterator pit = input.points.rbegin(); pit != input.points.rend(); ++pit) - output->push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); -} - -template -void -Slic3rMultiPoints_to_ClipperPaths(const T &input, ClipperLib::Paths* output) -{ - PROFILE_FUNC(); - - output->clear(); - output->reserve(input.size()); - for (typename T::const_iterator it = input.begin(); it != input.end(); ++it) { - // std::vector< IntPoint >, IntPoint is a pair of int64_t - ClipperLib::Path p; - Slic3rMultiPoint_to_ClipperPath(*it, &p); - output->push_back(p); - } -} - void scaleClipperPolygon(ClipperLib::Path &polygon) { PROFILE_FUNC(); @@ -205,130 +96,129 @@ void unscaleClipperPolygons(ClipperLib::Paths &polygons) } } -void -offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta, - ClipperLib::JoinType joinType, double miterLimit) +//----------------------------------------------------------- +// legacy code from Clipper documentation +void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, ExPolygons* expolygons) +{ + size_t cnt = expolygons->size(); + expolygons->resize(cnt + 1); + (*expolygons)[cnt].contour = ClipperPath_to_Slic3rMultiPoint(polynode.Contour); + (*expolygons)[cnt].holes.resize(polynode.ChildCount()); + for (int i = 0; i < polynode.ChildCount(); ++i) + { + (*expolygons)[cnt].holes[i] = ClipperPath_to_Slic3rMultiPoint(polynode.Childs[i]->Contour); + //Add outer polygons contained by (nested within) holes ... + for (int j = 0; j < polynode.Childs[i]->ChildCount(); ++j) + AddOuterPolyNodeToExPolygons(*polynode.Childs[i]->Childs[j], expolygons); + } +} + +ExPolygons +PolyTreeToExPolygons(ClipperLib::PolyTree& polytree) { - PROFILE_FUNC(); - // read input - ClipperLib::Paths input; - Slic3rMultiPoints_to_ClipperPaths(polygons, &input); + ExPolygons retval; + for (int i = 0; i < polytree.ChildCount(); ++i) + AddOuterPolyNodeToExPolygons(*polytree.Childs[i], &retval); + return retval; +} +//----------------------------------------------------------- + +template +T +ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input) +{ + T retval; + for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit) + retval.points.push_back(Point( (*pit).X, (*pit).Y )); + return retval; +} + +template +T +ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input) +{ + T retval; + for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it) + retval.push_back(ClipperPath_to_Slic3rMultiPoint(*it)); + return retval; +} + +ExPolygons +ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input) +{ + // init Clipper + ClipperLib::Clipper clipper; + clipper.Clear(); + // perform union + clipper.AddPaths(input, ClipperLib::ptSubject, true); + ClipperLib::PolyTree polytree; + clipper.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); // offset results work with both EvenOdd and NonZero + + // write to ExPolygons object + return PolyTreeToExPolygons(polytree); +} + +ClipperLib::Path +Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input) +{ + ClipperLib::Path retval; + for (Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) + retval.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); + return retval; +} + +ClipperLib::Path +Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input) +{ + ClipperLib::Path output; + output.reserve(input.points.size()); + for (Slic3r::Points::const_reverse_iterator pit = input.points.rbegin(); pit != input.points.rend(); ++pit) + output.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); + return output; +} + +template +ClipperLib::Paths +Slic3rMultiPoints_to_ClipperPaths(const T &input) +{ + ClipperLib::Paths retval; + for (typename T::const_iterator it = input.begin(); it != input.end(); ++it) + retval.push_back(Slic3rMultiPoint_to_ClipperPath(*it)); + return retval; +} + +ClipperLib::Paths _offset(ClipperLib::Paths &input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit) +{ // scale input scaleClipperPolygons(input); // perform offset ClipperLib::ClipperOffset co; - if (joinType == jtRound) { - co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE); - } else { + if (joinType == jtRound) + co.ArcTolerance = miterLimit; + else co.MiterLimit = miterLimit; - } - { - PROFILE_BLOCK(offset_AddPaths); - co.AddPaths(input, joinType, ClipperLib::etClosedPolygon); - } - { - PROFILE_BLOCK(offset_Execute); - co.Execute(*retval, delta * float(CLIPPER_OFFSET_SCALE)); - } + co.AddPaths(input, joinType, endType); + ClipperLib::Paths retval; + co.Execute(retval, delta * float(CLIPPER_OFFSET_SCALE)); // unscale output - unscaleClipperPolygons(*retval); + unscaleClipperPolygons(retval); + return retval; } -void -offset(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta, - ClipperLib::JoinType joinType, double miterLimit) +ClipperLib::Paths _offset(ClipperLib::Path &input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit) { - // perform offset - ClipperLib::Paths output; - offset(polygons, &output, delta, joinType, miterLimit); - - // convert into ExPolygons - ClipperPaths_to_Slic3rMultiPoints(output, retval); -} - -Slic3r::Polygons -offset(const Slic3r::Polygons &polygons, const float delta, - ClipperLib::JoinType joinType, double miterLimit) -{ - Slic3r::Polygons pp; - offset(polygons, &pp, delta, joinType, miterLimit); - return pp; -} - -void -offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const float delta, - ClipperLib::JoinType joinType, double miterLimit) -{ - // read input - ClipperLib::Paths input; - Slic3rMultiPoints_to_ClipperPaths(polylines, &input); - - // scale input - scaleClipperPolygons(input); - - // perform offset - ClipperLib::ClipperOffset co; - if (joinType == jtRound) { - co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE); - } else { - co.MiterLimit = miterLimit; - } - co.AddPaths(input, joinType, ClipperLib::etOpenButt); - co.Execute(*retval, delta * float(CLIPPER_OFFSET_SCALE)); - - // unscale output - unscaleClipperPolygons(*retval); -} - -void -offset(const Slic3r::Polylines &polylines, Slic3r::Polygons* retval, const float delta, - ClipperLib::JoinType joinType, double miterLimit) -{ - // perform offset - ClipperLib::Paths output; - offset(polylines, &output, delta, joinType, miterLimit); - - // convert into ExPolygons - ClipperPaths_to_Slic3rMultiPoints(output, retval); -} - -void -offset(const Slic3r::Surface &surface, Slic3r::Surfaces* retval, const float delta, - ClipperLib::JoinType joinType, double miterLimit) -{ - // perform offset - Slic3r::ExPolygons expp; - offset(surface.expolygon, &expp, delta, joinType, miterLimit); - - // clone the input surface for each expolygon we got - retval->clear(); - retval->reserve(expp.size()); - for (ExPolygons::iterator it = expp.begin(); it != expp.end(); ++it) { - Surface s = surface; // clone - s.expolygon = *it; - retval->push_back(s); - } -} - -void -offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta, - ClipperLib::JoinType joinType, double miterLimit) -{ - // perform offset - ClipperLib::Paths output; - offset(polygons, &output, delta, joinType, miterLimit); - - // convert into ExPolygons - ClipperPaths_to_Slic3rExPolygons(output, retval); + ClipperLib::Paths paths; + paths.push_back(input); + return _offset(paths, endType, delta, joinType, miterLimit); } // This is a safe variant of the polygon offset, tailored for a single ExPolygon: // a single polygon with multiple non-overlapping holes. // Each contour and hole is offsetted separately, then the holes are subtracted from the outer contours. -void offset(const Slic3r::ExPolygon &expolygon, ClipperLib::Paths* retval, const float delta, +ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit) { // printf("new ExPolygon offset\n"); @@ -336,8 +226,7 @@ void offset(const Slic3r::ExPolygon &expolygon, ClipperLib::Paths* retval, const const float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE); ClipperLib::Paths contours; { - ClipperLib::Path input; - Slic3rMultiPoint_to_ClipperPath(expolygon.contour, &input); + ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath(expolygon.contour); scaleClipperPolygon(input); ClipperLib::ClipperOffset co; if (joinType == jtRound) @@ -353,8 +242,7 @@ void offset(const Slic3r::ExPolygon &expolygon, ClipperLib::Paths* retval, const { holes.reserve(expolygon.holes.size()); for (Polygons::const_iterator it_hole = expolygon.holes.begin(); it_hole != expolygon.holes.end(); ++ it_hole) { - ClipperLib::Path input; - Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole, &input); + ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole); scaleClipperPolygon(input); ClipperLib::ClipperOffset co; if (joinType == jtRound) @@ -375,43 +263,18 @@ void offset(const Slic3r::ExPolygon &expolygon, ClipperLib::Paths* retval, const clipper.Clear(); clipper.AddPaths(contours, ClipperLib::ptSubject, true); clipper.AddPaths(holes, ClipperLib::ptClip, true); - clipper.Execute(ClipperLib::ctDifference, *retval, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero); } // 4) Unscale the output. - unscaleClipperPolygons(*retval); -} - -Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, - ClipperLib::JoinType joinType, double miterLimit) -{ - // perform offset - ClipperLib::Paths output; - offset(expolygon, &output, delta, joinType, miterLimit); - - // convert into ExPolygons - Slic3r::Polygons retval; - ClipperPaths_to_Slic3rMultiPoints(output, &retval); - return retval; -} - -Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, - ClipperLib::JoinType joinType, double miterLimit) -{ - // perform offset - ClipperLib::Paths output; - offset(expolygon, &output, delta, joinType, miterLimit); - - // convert into ExPolygons - Slic3r::ExPolygons retval; - ClipperPaths_to_Slic3rExPolygons(output, &retval); - return retval; + unscaleClipperPolygons(output); + return output; } // This is a safe variant of the polygon offset, tailored for a single ExPolygon: // a single polygon with multiple non-overlapping holes. // Each contour and hole is offsetted separately, then the holes are subtracted from the outer contours. -void offset(const Slic3r::ExPolygons &expolygons, ClipperLib::Paths* retval, const float delta, +ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit) { // printf("new ExPolygon offset\n"); @@ -429,8 +292,7 @@ void offset(const Slic3r::ExPolygons &expolygons, ClipperLib::Paths* retval, con for (Slic3r::ExPolygons::const_iterator it_expoly = expolygons.begin(); it_expoly != expolygons.end(); ++ it_expoly) { // 1) Offset the outer contour. { - ClipperLib::Path input; - Slic3rMultiPoint_to_ClipperPath(it_expoly->contour, &input); + ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath(it_expoly->contour); scaleClipperPolygon(input); ClipperLib::ClipperOffset co; if (joinType == jtRound) @@ -446,8 +308,7 @@ void offset(const Slic3r::ExPolygons &expolygons, ClipperLib::Paths* retval, con // 2) Offset the holes one by one, collect the results. { for (Polygons::const_iterator it_hole = it_expoly->holes.begin(); it_hole != it_expoly->holes.end(); ++ it_hole) { - ClipperLib::Path input; - Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole, &input); + ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole); scaleClipperPolygon(input); ClipperLib::ClipperOffset co; if (joinType == jtRound) @@ -469,71 +330,20 @@ void offset(const Slic3r::ExPolygons &expolygons, ClipperLib::Paths* retval, con clipper.Clear(); clipper.AddPaths(contours, ClipperLib::ptSubject, true); clipper.AddPaths(holes, ClipperLib::ptClip, true); - clipper.Execute(ClipperLib::ctDifference, *retval, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero); } // 4) Unscale the output. - unscaleClipperPolygons(*retval); + unscaleClipperPolygons(output); + return output; } -Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, - ClipperLib::JoinType joinType, double miterLimit) +ClipperLib::Paths +_offset2(const Polygons &polygons, const float delta1, const float delta2, + const ClipperLib::JoinType joinType, const double miterLimit) { - // perform offset - ClipperLib::Paths output; - offset(expolygons, &output, delta, joinType, miterLimit); - - // convert into ExPolygons - Slic3r::Polygons retval; - ClipperPaths_to_Slic3rMultiPoints(output, &retval); - return retval; -} - -Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, - ClipperLib::JoinType joinType, double miterLimit) -{ - // perform offset - ClipperLib::Paths output; - offset(expolygons, &output, delta, joinType, miterLimit); - - // convert into ExPolygons - Slic3r::ExPolygons retval; - ClipperPaths_to_Slic3rExPolygons(output, &retval); - return retval; -} - -Slic3r::ExPolygons -offset_ex(const Slic3r::Polygons &polygons, const float delta, - ClipperLib::JoinType joinType, double miterLimit) -{ - Slic3r::ExPolygons expp; - offset(polygons, &expp, delta, joinType, miterLimit); - return expp; -} - -void -offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1, - const float delta2, const ClipperLib::JoinType joinType, const double miterLimit) -{ - if (delta1 * delta2 >= 0) { - // Both deltas are the same signum - offset(polygons, retval, delta1 + delta2, joinType, miterLimit); - return; - } -#ifdef CLIPPER_UTILS_DEBUG - BoundingBox bbox = get_extents(polygons); - coordf_t stroke_width = scale_(0.005); - static int iRun = 0; - ++ iRun; - bool flipY = false; - SVG svg(debug_out_path("offset2-%d.svg", iRun), bbox, scale_(1.), flipY); - for (Slic3r::Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++ it) - svg.draw(it->lines(), "gray", stroke_width); -#endif /* CLIPPER_UTILS_DEBUG */ - // read input - ClipperLib::Paths input; - Slic3rMultiPoints_to_ClipperPaths(polygons, &input); + ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polygons); // scale input scaleClipperPolygons(input); @@ -541,7 +351,7 @@ offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float // prepare ClipperOffset object ClipperLib::ClipperOffset co; if (joinType == jtRound) { - co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE); + co.ArcTolerance = miterLimit; } else { co.MiterLimit = miterLimit; } @@ -550,74 +360,48 @@ offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float ClipperLib::Paths output1; co.AddPaths(input, joinType, ClipperLib::etClosedPolygon); co.Execute(output1, delta1 * float(CLIPPER_OFFSET_SCALE)); -#ifdef CLIPPER_UTILS_DEBUG - svg.draw(output1, 1. / double(CLIPPER_OFFSET_SCALE), "red", stroke_width); -#endif /* CLIPPER_UTILS_DEBUG */ // perform second offset co.Clear(); co.AddPaths(output1, joinType, ClipperLib::etClosedPolygon); - co.Execute(*retval, delta2 * float(CLIPPER_OFFSET_SCALE)); -#ifdef CLIPPER_UTILS_DEBUG - svg.draw(*retval, 1. / double(CLIPPER_OFFSET_SCALE), "green", stroke_width); -#endif /* CLIPPER_UTILS_DEBUG */ - + ClipperLib::Paths retval; + co.Execute(retval, delta2 * float(CLIPPER_OFFSET_SCALE)); + // unscale output - unscaleClipperPolygons(*retval); + unscaleClipperPolygons(retval); + return retval; } -void -offset2(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta1, - const float delta2, const ClipperLib::JoinType joinType, const double miterLimit) +Polygons +offset2(const Polygons &polygons, const float delta1, const float delta2, + const ClipperLib::JoinType joinType, const double miterLimit) { // perform offset - ClipperLib::Paths output; - offset2(polygons, &output, delta1, delta2, joinType, miterLimit); + ClipperLib::Paths output = _offset2(polygons, delta1, delta2, joinType, miterLimit); // convert into ExPolygons - ClipperPaths_to_Slic3rMultiPoints(output, retval); + return ClipperPaths_to_Slic3rMultiPoints(output); } -Slic3r::Polygons -offset2(const Slic3r::Polygons &polygons, const float delta1, - const float delta2, const ClipperLib::JoinType joinType, const double miterLimit) -{ - Slic3r::Polygons pp; - offset2(polygons, &pp, delta1, delta2, joinType, miterLimit); - return pp; -} - -void -offset2(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta1, - const float delta2, const ClipperLib::JoinType joinType, const double miterLimit) +ExPolygons +offset2_ex(const Polygons &polygons, const float delta1, const float delta2, + const ClipperLib::JoinType joinType, const double miterLimit) { // perform offset - ClipperLib::Paths output; - offset2(polygons, &output, delta1, delta2, joinType, miterLimit); + ClipperLib::Paths output = _offset2(polygons, delta1, delta2, joinType, miterLimit); // convert into ExPolygons - ClipperPaths_to_Slic3rExPolygons(output, retval); -} - -Slic3r::ExPolygons -offset2_ex(const Slic3r::Polygons &polygons, const float delta1, - const float delta2, const ClipperLib::JoinType joinType, const double miterLimit) -{ - Slic3r::ExPolygons expp; - offset2(polygons, &expp, delta1, delta2, joinType, miterLimit); - return expp; + return ClipperPaths_to_Slic3rExPolygons(output); } template -void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, - const Slic3r::Polygons &clip, T* retval, const ClipperLib::PolyFillType fillType, const bool safety_offset_) +T +_clipper_do(const ClipperLib::ClipType clipType, const Polygons &subject, + const Polygons &clip, const ClipperLib::PolyFillType fillType, const bool safety_offset_) { - PROFILE_BLOCK(_clipper_do_polygons); - // read input - ClipperLib::Paths input_subject, input_clip; - Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject); - Slic3rMultiPoints_to_ClipperPaths(clip, &input_clip); + ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject); + ClipperLib::Paths input_clip = Slic3rMultiPoints_to_ClipperPaths(clip); // perform safety offset if (safety_offset_) { @@ -633,36 +417,23 @@ void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polygons &su clipper.Clear(); // add polygons - { - PROFILE_BLOCK(_clipper_do_polygons_AddPaths); - clipper.AddPaths(input_subject, ClipperLib::ptSubject, true); - clipper.AddPaths(input_clip, ClipperLib::ptClip, true); - -#ifdef CLIPPER_UTILS_DEBUG - if (clipper_export_enabled) { - static int iRun = 0; - export_clipper_input_polygons_bin(debug_out_path("_clipper_do_polygons_AddPaths-polygons-%d", ++iRun).c_str(), input_subject, input_clip); - } -#endif /* CLIPPER_UTILS_DEBUG */ - } + clipper.AddPaths(input_subject, ClipperLib::ptSubject, true); + clipper.AddPaths(input_clip, ClipperLib::ptClip, true); // perform operation - { - PROFILE_BLOCK(_clipper_do_polygons_Execute); - clipper.Execute(clipType, *retval, fillType, fillType); - } + T retval; + clipper.Execute(clipType, retval, fillType, fillType); + return retval; } -void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, - const Slic3r::Polygons &clip, ClipperLib::PolyTree* retval, const ClipperLib::PolyFillType fillType, +ClipperLib::PolyTree +_clipper_do(const ClipperLib::ClipType clipType, const Polylines &subject, + const Polygons &clip, const ClipperLib::PolyFillType fillType, const bool safety_offset_) { - PROFILE_BLOCK(_clipper_do_polylines); - // read input - ClipperLib::Paths input_subject, input_clip; - Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject); - Slic3rMultiPoints_to_ClipperPaths(clip, &input_clip); + ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject); + ClipperLib::Paths input_clip = Slic3rMultiPoints_to_ClipperPaths(clip); // perform safety offset if (safety_offset_) safety_offset(&input_clip); @@ -672,298 +443,126 @@ void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polylines &s clipper.Clear(); // add polygons - { - PROFILE_BLOCK(_clipper_do_polylines_AddPaths); - clipper.AddPaths(input_subject, ClipperLib::ptSubject, false); - clipper.AddPaths(input_clip, ClipperLib::ptClip, true); - } + clipper.AddPaths(input_subject, ClipperLib::ptSubject, false); + clipper.AddPaths(input_clip, ClipperLib::ptClip, true); // perform operation - { - PROFILE_BLOCK(_clipper_do_polylines_Execute); - clipper.Execute(clipType, *retval, fillType, fillType); - } + ClipperLib::PolyTree retval; + clipper.Execute(clipType, retval, fillType, fillType); + return retval; } -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, - const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_) +Polygons +_clipper(ClipperLib::ClipType clipType, const Polygons &subject, + const Polygons &clip, bool safety_offset_) +{ + return ClipperPaths_to_Slic3rMultiPoints(_clipper_do(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_)); +} + +ExPolygons +_clipper_ex(ClipperLib::ClipType clipType, const Polygons &subject, + const Polygons &clip, bool safety_offset_) +{ + return PolyTreeToExPolygons(_clipper_do(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_)); +} + +Polylines +_clipper_pl(ClipperLib::ClipType clipType, const Polylines &subject, + const Polygons &clip, bool safety_offset_) { - PROFILE_FUNC(); - // perform operation ClipperLib::Paths output; - _clipper_do(clipType, subject, clip, &output, ClipperLib::pftNonZero, safety_offset_); - - // convert into Polygons - ClipperPaths_to_Slic3rMultiPoints(output, retval); + ClipperLib::PolyTreeToPaths(_clipper_do(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_), output); + return ClipperPaths_to_Slic3rMultiPoints(output); } -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, - const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_) -{ - PROFILE_FUNC(); - // perform operation - ClipperLib::PolyTree polytree; - _clipper_do(clipType, subject, clip, &polytree, ClipperLib::pftNonZero, safety_offset_); - - // convert into ExPolygons - PolyTreeToExPolygons(polytree, retval); -} - -void _clipper_pl(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, - const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_) -{ - PROFILE_FUNC(); - // perform operation - ClipperLib::PolyTree polytree; - _clipper_do(clipType, subject, clip, &polytree, ClipperLib::pftNonZero, safety_offset_); - - // convert into Polylines - ClipperLib::Paths output; - ClipperLib::PolyTreeToPaths(polytree, output); - ClipperPaths_to_Slic3rMultiPoints(output, retval); -} - -void _clipper_ln(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, - const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_) -{ - // convert Lines to Polylines - Slic3r::Polylines polylines; - polylines.reserve(subject.size()); - for (Slic3r::Lines::const_iterator line = subject.begin(); line != subject.end(); ++line) - polylines.push_back(*line); - - // perform operation - _clipper_pl(clipType, polylines, clip, &polylines, safety_offset_); - - // convert Polylines to Lines - for (Slic3r::Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) - retval->push_back(*polyline); -} - -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, - const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_) +Polylines +_clipper_pl(ClipperLib::ClipType clipType, const Polygons &subject, + const Polygons &clip, bool safety_offset_) { // transform input polygons into polylines - Slic3r::Polylines polylines; + Polylines polylines; polylines.reserve(subject.size()); - for (Slic3r::Polygons::const_iterator polygon = subject.begin(); polygon != subject.end(); ++polygon) + for (Polygons::const_iterator polygon = subject.begin(); polygon != subject.end(); ++polygon) polylines.push_back(*polygon); // implicit call to split_at_first_point() // perform clipping - _clipper_pl(clipType, polylines, clip, retval, safety_offset_); + Polylines retval = _clipper_pl(clipType, polylines, clip, safety_offset_); /* If the split_at_first_point() call above happens to split the polygon inside the clipping area we would get two consecutive polylines instead of a single one, so we go through them in order to recombine continuous polylines. */ - for (size_t i = 0; i < retval->size(); ++i) { - for (size_t j = i+1; j < retval->size(); ++j) { - if ((*retval)[i].points.back().coincides_with((*retval)[j].points.front())) { + for (size_t i = 0; i < retval.size(); ++i) { + for (size_t j = i+1; j < retval.size(); ++j) { + if (retval[i].points.back().coincides_with(retval[j].points.front())) { /* If last point of i coincides with first point of j, append points of j to i and delete j */ - (*retval)[i].points.insert((*retval)[i].points.end(), (*retval)[j].points.begin()+1, (*retval)[j].points.end()); - retval->erase(retval->begin() + j); + retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end()); + retval.erase(retval.begin() + j); --j; - } else if ((*retval)[i].points.front().coincides_with((*retval)[j].points.back())) { + } else if (retval[i].points.front().coincides_with(retval[j].points.back())) { /* If first point of i coincides with last point of j, prepend points of j to i and delete j */ - (*retval)[i].points.insert((*retval)[i].points.begin(), (*retval)[j].points.begin(), (*retval)[j].points.end()-1); - retval->erase(retval->begin() + j); + retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1); + retval.erase(retval.begin() + j); --j; - } else if ((*retval)[i].points.front().coincides_with((*retval)[j].points.front())) { + } else if (retval[i].points.front().coincides_with(retval[j].points.front())) { /* Since Clipper does not preserve orientation of polylines, also check the case when first point of i coincides with first point of j. */ - (*retval)[j].reverse(); - (*retval)[i].points.insert((*retval)[i].points.begin(), (*retval)[j].points.begin(), (*retval)[j].points.end()-1); - retval->erase(retval->begin() + j); + retval[j].reverse(); + retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1); + retval.erase(retval.begin() + j); --j; - } else if ((*retval)[i].points.back().coincides_with((*retval)[j].points.back())) { + } else if (retval[i].points.back().coincides_with(retval[j].points.back())) { /* Since Clipper does not preserve orientation of polylines, also check the case when last point of i coincides with last point of j. */ - (*retval)[j].reverse(); - (*retval)[i].points.insert((*retval)[i].points.end(), (*retval)[j].points.begin()+1, (*retval)[j].points.end()); - retval->erase(retval->begin() + j); + retval[j].reverse(); + retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end()); + retval.erase(retval.begin() + j); --j; } } - } -} - -template -void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_) -{ - _clipper(ClipperLib::ctDifference, subject, clip, retval, safety_offset_); -} -template void diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); -template void diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_); -template void diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); - -template -void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_) -{ - Slic3r::Polygons pp; - for (Slic3r::ExPolygons::const_iterator ex = clip.begin(); ex != clip.end(); ++ex) { - Slic3r::Polygons ppp = *ex; - pp.insert(pp.end(), ppp.begin(), ppp.end()); } - diff(subject, pp, retval, safety_offset_); -} -template void diff(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); - -template -void diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_) -{ - Slic3r::Polygons pp; - for (Slic3r::ExPolygons::const_iterator ex = subject.begin(); ex != subject.end(); ++ex) { - Slic3r::Polygons ppp = *ex; - pp.insert(pp.end(), ppp.begin(), ppp.end()); - } - diff(pp, clip, retval, safety_offset_); -} - -Slic3r::Polygons -diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_) -{ - Slic3r::Polygons pp; - diff(subject, clip, &pp, safety_offset_); - return pp; -} - -template -Slic3r::ExPolygons -diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_) -{ - Slic3r::ExPolygons expp; - diff(subject, clip, &expp, safety_offset_); - return expp; -} -template Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_); -template Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_); -template Slic3r::ExPolygons diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_); - -template -void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_) -{ - _clipper(ClipperLib::ctIntersection, subject, clip, retval, safety_offset_); -} -template void intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); -template void intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_); -template void intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); - -template -SubjectType intersection(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_) -{ - SubjectType pp; - intersection(subject, clip, &pp, safety_offset_); - return pp; -} - -template Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_); -template Slic3r::Polylines intersection(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_); -template Slic3r::Lines intersection(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_); - -Slic3r::ExPolygons -intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_) -{ - Slic3r::ExPolygons expp; - intersection(subject, clip, &expp, safety_offset_); - return expp; -} - -template -bool intersects(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_) -{ - SubjectType retval; - intersection(subject, clip, &retval, safety_offset_); - return !retval.empty(); -} -template bool intersects(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_); -template bool intersects(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_); -template bool intersects(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_); - -void xor_(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, - bool safety_offset_) -{ - _clipper(ClipperLib::ctXor, subject, clip, retval, safety_offset_); -} - -template -void union_(const Slic3r::Polygons &subject, T* retval, bool safety_offset_) -{ - Slic3r::Polygons p; - _clipper(ClipperLib::ctUnion, subject, p, retval, safety_offset_); -} -template void union_(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retval, bool safety_offset_); -template void union_(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_); - -Slic3r::Polygons -union_(const Slic3r::Polygons &subject, bool safety_offset) -{ - Polygons pp; - union_(subject, &pp, safety_offset); - return pp; -} - -Slic3r::ExPolygons -union_ex(const Slic3r::Polygons &subject, bool safety_offset) -{ - ExPolygons expp; - union_(subject, &expp, safety_offset); - return expp; -} - -Slic3r::ExPolygons -union_ex(const Slic3r::Surfaces &subject, bool safety_offset) -{ - Polygons pp; - for (Slic3r::Surfaces::const_iterator s = subject.begin(); s != subject.end(); ++s) { - Polygons spp = *s; - pp.insert(pp.end(), spp.begin(), spp.end()); - } - return union_ex(pp, safety_offset); -} - -void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset) -{ - Polygons pp = subject1; - pp.insert(pp.end(), subject2.begin(), subject2.end()); - union_(pp, retval, safety_offset); -} - -Slic3r::Polygons -union_(const Slic3r::ExPolygons &subject1, const Slic3r::ExPolygons &subject2, bool safety_offset) -{ - Polygons pp; - for (Slic3r::ExPolygons::const_iterator it = subject1.begin(); it != subject1.end(); ++it) { - Polygons spp = *it; - pp.insert(pp.end(), spp.begin(), spp.end()); - } - for (Slic3r::ExPolygons::const_iterator it = subject2.begin(); it != subject2.end(); ++it) { - Polygons spp = *it; - pp.insert(pp.end(), spp.begin(), spp.end()); - } - Polygons retval; - union_(pp, &retval, safety_offset); return retval; } -void union_pt(const Slic3r::Polygons &subject, ClipperLib::PolyTree* retval, bool safety_offset_) +Lines +_clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons &clip, + bool safety_offset_) { - Slic3r::Polygons clip; - _clipper_do(ClipperLib::ctUnion, subject, clip, retval, ClipperLib::pftEvenOdd, safety_offset_); + // convert Lines to Polylines + Polylines polylines; + polylines.reserve(subject.size()); + for (Lines::const_iterator line = subject.begin(); line != subject.end(); ++line) + polylines.push_back(*line); + + // perform operation + polylines = _clipper_pl(clipType, polylines, clip, safety_offset_); + + // convert Polylines to Lines + Lines retval; + for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) + retval.push_back(*polyline); + return retval; } -void union_pt_chained(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_) +ClipperLib::PolyTree +union_pt(const Polygons &subject, bool safety_offset_) { - ClipperLib::PolyTree pt; - union_pt(subject, &pt, safety_offset_); - if (&subject == retval) - // It is safe to use the same variable for input and output, because this function makes - // a temporary copy of the results. - retval->clear(); - traverse_pt(pt.Childs, retval); + return _clipper_do(ClipperLib::ctUnion, subject, Polygons(), ClipperLib::pftEvenOdd, safety_offset_); } -static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval) +Polygons +union_pt_chained(const Polygons &subject, bool safety_offset_) +{ + ClipperLib::PolyTree polytree = union_pt(subject, safety_offset_); + + Polygons retval; + traverse_pt(polytree.Childs, &retval); + return retval; +} + +void +traverse_pt(ClipperLib::PolyNodes &nodes, Polygons* retval) { /* use a nearest neighbor search to order these children TODO: supply start_near to chained_path() too? */ @@ -985,21 +584,19 @@ static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval) // traverse the next depth traverse_pt((*it)->Childs, retval); - Polygon p; - ClipperPath_to_Slic3rMultiPoint((*it)->Contour, &p); + Polygon p = ClipperPath_to_Slic3rMultiPoint((*it)->Contour); retval->push_back(p); if ((*it)->IsHole()) retval->back().reverse(); // ccw } } -void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool preserve_collinear) +Polygons +simplify_polygons(const Polygons &subject, bool preserve_collinear) { - PROFILE_FUNC(); - // convert into Clipper polygons - ClipperLib::Paths input_subject, output; - Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject); + ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject); + ClipperLib::Paths output; if (preserve_collinear) { ClipperLib::Clipper c; c.PreserveCollinear(true); @@ -1011,23 +608,18 @@ void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::Polygons* retval } // convert into Slic3r polygons - ClipperPaths_to_Slic3rMultiPoints(output, retval); + return ClipperPaths_to_Slic3rMultiPoints(output); } -void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retval, bool preserve_collinear) +ExPolygons +simplify_polygons_ex(const Polygons &subject, bool preserve_collinear) { - PROFILE_FUNC(); - if (!preserve_collinear) { - Polygons polygons; - simplify_polygons(subject, &polygons, preserve_collinear); - union_(polygons, retval); - return; + return union_ex(simplify_polygons(subject, preserve_collinear)); } // convert into Clipper polygons - ClipperLib::Paths input_subject; - Slic3rMultiPoints_to_ClipperPaths(subject, &input_subject); + ClipperLib::Paths input_subject = Slic3rMultiPoints_to_ClipperPaths(subject); ClipperLib::PolyTree polytree; @@ -1038,7 +630,7 @@ void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retv c.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftNonZero, ClipperLib::pftNonZero); // convert into ExPolygons - PolyTreeToExPolygons(polytree, retval); + return PolyTreeToExPolygons(polytree); } void safety_offset(ClipperLib::Paths* paths) @@ -1051,15 +643,15 @@ void safety_offset(ClipperLib::Paths* paths) // perform offset (delta = scale 1e-05) ClipperLib::ClipperOffset co; #ifdef CLIPPER_UTILS_DEBUG - if (clipper_export_enabled) { - static int iRun = 0; - export_clipper_input_polygons_bin(debug_out_path("safety_offset-polygons-%d", ++iRun).c_str(), *paths, ClipperLib::Paths()); - } + if (clipper_export_enabled) { + static int iRun = 0; + export_clipper_input_polygons_bin(debug_out_path("safety_offset-polygons-%d", ++iRun).c_str(), *paths, ClipperLib::Paths()); + } #endif /* CLIPPER_UTILS_DEBUG */ ClipperLib::Paths out; for (size_t i = 0; i < paths->size(); ++ i) { ClipperLib::Path &path = (*paths)[i]; - co.Clear(); + co.Clear(); co.MiterLimit = 2; bool ccw = ClipperLib::Orientation(path); if (! ccw) @@ -1092,23 +684,19 @@ void safety_offset(ClipperLib::Paths* paths) Polygons top_level_islands(const Slic3r::Polygons &polygons) { - ClipperLib::Paths input; - Slic3rMultiPoints_to_ClipperPaths(polygons, &input); // init Clipper ClipperLib::Clipper clipper; clipper.Clear(); // perform union - clipper.AddPaths(input, ClipperLib::ptSubject, true); + clipper.AddPaths(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::ptSubject, true); ClipperLib::PolyTree polytree; clipper.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd); // Convert only the top level islands to the output. Polygons out; out.reserve(polytree.ChildCount()); - for (int i = 0; i < polytree.ChildCount(); ++i) { - out.push_back(Polygon()); - ClipperPath_to_Slic3rMultiPoint(polytree.Childs[i]->Contour, &out.back()); - } + for (int i = 0; i < polytree.ChildCount(); ++i) + out.push_back(ClipperPath_to_Slic3rMultiPoint(polytree.Childs[i]->Contour)); return out; } -} // namespace Slic3r \ No newline at end of file +} \ No newline at end of file diff --git a/xs/src/libslic3r/ClipperUtils.hpp b/xs/src/libslic3r/ClipperUtils.hpp index 8efebdfad..0a28c3932 100644 --- a/xs/src/libslic3r/ClipperUtils.hpp +++ b/xs/src/libslic3r/ClipperUtils.hpp @@ -20,166 +20,198 @@ void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPoly void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons); //----------------------------------------------------------- -void Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input, ClipperLib::Path* output); +ClipperLib::Path Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input); template -void Slic3rMultiPoints_to_ClipperPaths(const T &input, ClipperLib::Paths* output); +ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const T &input); template -void ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input, T* output); +T ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input); template -void ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input, T* output); -void ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, Slic3r::ExPolygons* output); - -void scaleClipperPolygons(ClipperLib::Paths &polygons, const double scale); +T ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input); +Slic3r::ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input); // offset Polygons -void offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); -void offset(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); -Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); - -// This is a safe variant of the polygon offset, tailored for a single ExPolygon: -// a single polygon with multiple non-overlapping holes. -// Each contour and hole is offsetted separately, then the holes are subtracted from the outer contours. -void offset(const Slic3r::ExPolygon &expolygon, ClipperLib::Paths* retval, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); -void offset(const Slic3r::ExPolygons &expolygons, ClipperLib::Paths* retval, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); -Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); -Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); -Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, - double scale, ClipperLib::JoinType joinType, double miterLimit); -Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, - double scale, ClipperLib::JoinType joinType, double miterLimit); +ClipperLib::Paths _offset(ClipperLib::Path &input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit); +ClipperLib::Paths _offset(ClipperLib::Paths &input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit); +inline Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) + { return ClipperPaths_to_Slic3rMultiPoints(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); } +inline Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) + { return ClipperPaths_to_Slic3rMultiPoints(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); } // offset Polylines -void offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtSquare, - double miterLimit = 3); -void offset(const Slic3r::Polylines &polylines, Slic3r::Polygons* retval, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtSquare, - double miterLimit = 3); -void offset(const Slic3r::Surface &surface, Slic3r::Surfaces* retval, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtSquare, - double miterLimit = 3); +inline Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3) + { return ClipperPaths_to_Slic3rMultiPoints(_offset(Slic3rMultiPoint_to_ClipperPath(polyline), ClipperLib::etOpenButt, delta, joinType, miterLimit)); } +inline Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3) + { return ClipperPaths_to_Slic3rMultiPoints(_offset(Slic3rMultiPoints_to_ClipperPaths(polylines), ClipperLib::etOpenButt, delta, joinType, miterLimit)); } -void offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); -Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, - ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); +// offset expolygons and surfaces +ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit); +ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit); +inline Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) + { return ClipperPaths_to_Slic3rMultiPoints(_offset(expolygon, delta, joinType, miterLimit)); } +inline Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) + { return ClipperPaths_to_Slic3rMultiPoints(_offset(expolygons, delta, joinType, miterLimit)); } +inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) + { return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); } +inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) + { return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); } +inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) + { return ClipperPaths_to_Slic3rExPolygons(_offset(expolygon, delta, joinType, miterLimit)); } +inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3) + { return ClipperPaths_to_Slic3rExPolygons(_offset(expolygons, delta, joinType, miterLimit)); } -void offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1, - const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); -void offset2(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta1, +ClipperLib::Paths _offset2(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); -void offset2(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta1, - const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1, const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); template -void _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, - const Slic3r::Polygons &clip, T* retval, bool safety_offset_); -void _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, - const Slic3r::Polygons &clip, ClipperLib::Paths* retval, bool safety_offset_); -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, - const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_); -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, - const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); -void _clipper_pl(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, - const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); -void _clipper_ln(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, - const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_); +T _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, + const Slic3r::Polygons &clip, const ClipperLib::PolyFillType fillType, bool safety_offset_ = false); -template -void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false); +ClipperLib::PolyTree _clipper_do(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, + const Slic3r::Polygons &clip, const ClipperLib::PolyFillType fillType, bool safety_offset_ = false); -template -void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_ = false); +Slic3r::Polygons _clipper(ClipperLib::ClipType clipType, + const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); +Slic3r::ExPolygons _clipper_ex(ClipperLib::ClipType clipType, + const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); +Slic3r::Polylines _clipper_pl(ClipperLib::ClipType clipType, + const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); +Slic3r::Polylines _clipper_pl(ClipperLib::ClipType clipType, + const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); +Slic3r::Lines _clipper_ln(ClipperLib::ClipType clipType, + const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); -Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); - -template -Slic3r::ExPolygons diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_ = false); - -inline void diff(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_ = false) +// diff +inline Slic3r::Polygons +diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) { - _clipper_pl(ClipperLib::ctDifference, subject, clip, retval, safety_offset_); + return _clipper(ClipperLib::ctDifference, subject, clip, safety_offset_); } -inline void diff(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_ = false) +inline Slic3r::ExPolygons +diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) { - _clipper_ln(ClipperLib::ctDifference, subject, clip, retval, safety_offset_); + return _clipper_ex(ClipperLib::ctDifference, subject, clip, safety_offset_); } -template -void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false); - -inline void intersection(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_ = false) +inline Slic3r::ExPolygons +diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false) { - _clipper_pl(ClipperLib::ctIntersection, subject, clip, retval, safety_offset_); + return _clipper_ex(ClipperLib::ctDifference, to_polygons(subject), to_polygons(clip), safety_offset_); } -inline void intersection(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_ = false) +inline Slic3r::Polygons +diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false) { - _clipper_ln(ClipperLib::ctIntersection, subject, clip, retval, safety_offset_); + return _clipper(ClipperLib::ctDifference, to_polygons(subject), to_polygons(clip), safety_offset_); } -template -SubjectType intersection(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); +inline Slic3r::Polylines +diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper_pl(ClipperLib::ctDifference, subject, clip, safety_offset_); +} -Slic3r::ExPolygons -intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); +inline Slic3r::Polylines +diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper_pl(ClipperLib::ctDifference, subject, clip, safety_offset_); +} -template -bool intersects(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); +inline Slic3r::Lines +diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper_ln(ClipperLib::ctDifference, subject, clip, safety_offset_); +} + +// intersection +inline Slic3r::Polygons +intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper(ClipperLib::ctIntersection, subject, clip, safety_offset_); +} + +inline Slic3r::ExPolygons +intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper_ex(ClipperLib::ctIntersection, subject, clip, safety_offset_); +} + +inline Slic3r::ExPolygons +intersection_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false) +{ + return _clipper_ex(ClipperLib::ctIntersection, to_polygons(subject), to_polygons(clip), safety_offset_); +} + +inline Slic3r::Polygons +intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false) +{ + return _clipper(ClipperLib::ctIntersection, to_polygons(subject), to_polygons(clip), safety_offset_); +} + +inline Slic3r::Polylines +intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_); +} inline Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) { - Slic3r::Polylines polylines_out; - _clipper_pl(ClipperLib::ctIntersection, subject, clip, &polylines_out, safety_offset_); - return polylines_out; + return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_); } -void xor_(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, - bool safety_offset_ = false); +inline Slic3r::Lines +intersection_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper_ln(ClipperLib::ctIntersection, subject, clip, safety_offset_); +} -template -void union_(const Slic3r::Polygons &subject, T* retval, bool safety_offset_ = false); +// union +inline Slic3r::Polygons +union_(const Slic3r::Polygons &subject, bool safety_offset_ = false) +{ + return _clipper(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_); +} -Slic3r::Polygons union_(const Slic3r::Polygons &subject, bool safety_offset = false); -Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool safety_offset = false); -Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject, bool safety_offset = false); +inline Slic3r::Polygons +union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2, bool safety_offset_ = false) +{ + return _clipper(ClipperLib::ctUnion, subject, subject2, safety_offset_); +} -void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset = false); -Slic3r::Polygons union_(const Slic3r::ExPolygons &subject1, const Slic3r::ExPolygons &subject2, bool safety_offset = false); +inline Slic3r::ExPolygons +union_ex(const Slic3r::Polygons &subject, bool safety_offset_ = false) +{ + return _clipper_ex(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_); +} -void union_pt(const Slic3r::Polygons &subject, ClipperLib::PolyTree* retval, bool safety_offset_ = false); -void union_pt_chained(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_ = false); -static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval); +inline Slic3r::ExPolygons +union_ex(const Slic3r::ExPolygons &subject, bool safety_offset_ = false) +{ + return _clipper_ex(ClipperLib::ctUnion, to_polygons(subject), Slic3r::Polygons(), safety_offset_); +} -void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool preserve_collinear = false); -void simplify_polygons(const Slic3r::Polygons &subject, Slic3r::ExPolygons* retval, bool preserve_collinear = false); +inline Slic3r::ExPolygons +union_ex(const Slic3r::Surfaces &subject, bool safety_offset_ = false) +{ + return _clipper_ex(ClipperLib::ctUnion, to_polygons(subject), Slic3r::Polygons(), safety_offset_); +} + + +ClipperLib::PolyTree union_pt(const Slic3r::Polygons &subject, bool safety_offset_ = false); +Slic3r::Polygons union_pt_chained(const Slic3r::Polygons &subject, bool safety_offset_ = false); +void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval); + +/* OTHER */ +Slic3r::Polygons simplify_polygons(const Slic3r::Polygons &subject, bool preserve_collinear = false); +Slic3r::ExPolygons simplify_polygons_ex(const Slic3r::Polygons &subject, bool preserve_collinear = false); void safety_offset(ClipperLib::Paths* paths); @@ -187,4 +219,4 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons); } -#endif +#endif \ No newline at end of file diff --git a/xs/src/libslic3r/EdgeGrid.hpp b/xs/src/libslic3r/EdgeGrid.hpp index f194b4644..2473ce423 100644 --- a/xs/src/libslic3r/EdgeGrid.hpp +++ b/xs/src/libslic3r/EdgeGrid.hpp @@ -12,8 +12,9 @@ namespace Slic3r { namespace EdgeGrid { -struct Grid +class Grid { +public: Grid(); ~Grid(); diff --git a/xs/src/libslic3r/ExPolygon.cpp b/xs/src/libslic3r/ExPolygon.cpp index fbb616ebb..06ba28ed2 100644 --- a/xs/src/libslic3r/ExPolygon.cpp +++ b/xs/src/libslic3r/ExPolygon.cpp @@ -99,9 +99,7 @@ ExPolygon::contains(const Line &line) const bool ExPolygon::contains(const Polyline &polyline) const { - Polylines pl_out; - diff((Polylines)polyline, *this, &pl_out); - return pl_out.empty(); + return diff_pl((Polylines)polyline, *this).empty(); } bool @@ -115,8 +113,7 @@ ExPolygon::contains(const Polylines &polylines) const svg.draw_outline(*this); svg.draw(polylines, "blue"); #endif - Polylines pl_out; - diff(polylines, *this, &pl_out); + Polylines pl_out = diff_pl(polylines, *this); #if 0 svg.draw(pl_out, "red"); #endif @@ -162,8 +159,7 @@ ExPolygon::overlaps(const ExPolygon &other) const svg.draw_outline(*this); svg.draw_outline(other, "blue"); #endif - Polylines pl_out; - intersection((Polylines)other, *this, &pl_out); + Polylines pl_out = intersection_pl((Polylines)other, *this); #if 0 svg.draw(pl_out, "red"); #endif @@ -396,11 +392,8 @@ ExPolygon::get_trapezoids2(Polygons* polygons) const poly[3].y = bb.max.y; // intersect with this expolygon - Polygons trapezoids; - intersection(poly, *this, &trapezoids); - // append results to return value - polygons->insert(polygons->end(), trapezoids.begin(), trapezoids.end()); + polygons_append(*polygons, intersection(poly, to_polygons(*this))); } } @@ -434,16 +427,13 @@ ExPolygon::triangulate_pp(Polygons* polygons) const // convert polygons std::list input; - Polygons pp = *this; - simplify_polygons(pp, &pp, true); - ExPolygons expp; - union_(pp, &expp); + ExPolygons expp = union_ex(simplify_polygons(to_polygons(*this), true)); for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) { // contour { TPPLPoly p; - p.Init(ex->contour.points.size()); + p.Init(int(ex->contour.points.size())); //printf(PRINTF_ZU "\n0\n", ex->contour.points.size()); for (Points::const_iterator point = ex->contour.points.begin(); point != ex->contour.points.end(); ++point) { p[ point-ex->contour.points.begin() ].x = point->x; @@ -480,8 +470,8 @@ ExPolygon::triangulate_pp(Polygons* polygons) const Polygon p; p.points.resize(num_points); for (long i = 0; i < num_points; ++i) { - p.points[i].x = (*poly)[i].x; - p.points[i].y = (*poly)[i].y; + p.points[i].x = coord_t((*poly)[i].x); + p.points[i].y = coord_t((*poly)[i].y); } polygons->push_back(p); } @@ -490,8 +480,7 @@ ExPolygon::triangulate_pp(Polygons* polygons) const void ExPolygon::triangulate_p2t(Polygons* polygons) const { - ExPolygons expp; - simplify_polygons(*this, &expp, true); + ExPolygons expp = simplify_polygons_ex(*this, true); for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) { // TODO: prevent duplicate points diff --git a/xs/src/libslic3r/ExtrusionEntity.cpp b/xs/src/libslic3r/ExtrusionEntity.cpp index 624cdccbc..9f59ca386 100644 --- a/xs/src/libslic3r/ExtrusionEntity.cpp +++ b/xs/src/libslic3r/ExtrusionEntity.cpp @@ -13,19 +13,13 @@ namespace Slic3r { void ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const { - // perform clipping - Polylines clipped; - intersection(this->polyline, collection, &clipped); - return this->_inflate_collection(clipped, retval); + this->_inflate_collection(intersection_pl(this->polyline, collection), retval); } void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const { - // perform clipping - Polylines clipped; - diff(this->polyline, collection, &clipped); - return this->_inflate_collection(clipped, retval); + this->_inflate_collection(diff_pl(this->polyline, collection), retval); } void @@ -58,9 +52,7 @@ ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCo void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const { - Polygons tmp; - offset(this->polyline, &tmp, scale_(this->width/2) + scaled_epsilon); - polygons_append(out, STDMOVE(tmp)); + polygons_append(out, offset(this->polyline, float(scale_(this->width/2)) + scaled_epsilon)); } void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const @@ -68,9 +60,7 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scale // Instantiating the Flow class to get the line spacing. // Don't know the nozzle diameter, setting to zero. It shall not matter it shall be optimized out by the compiler. Flow flow(this->width, this->height, 0.f, this->is_bridge()); - Polygons tmp; - offset(this->polyline, &tmp, 0.5f * flow.scaled_spacing() + scaled_epsilon); - polygons_append(out, STDMOVE(tmp)); + polygons_append(out, offset(this->polyline, 0.5f * float(flow.scaled_spacing()) + scaled_epsilon)); } bool diff --git a/xs/src/libslic3r/ExtrusionEntity.hpp b/xs/src/libslic3r/ExtrusionEntity.hpp index 7ce053a10..dfc28d035 100644 --- a/xs/src/libslic3r/ExtrusionEntity.hpp +++ b/xs/src/libslic3r/ExtrusionEntity.hpp @@ -194,6 +194,26 @@ class ExtrusionLoop : public ExtrusionEntity Polyline as_polyline() const { return this->polygon().split_at_first_point(); } }; +inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) +{ + dst.reserve(dst.size() + polylines.size()); + for (Polylines::const_iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) { + dst.push_back(ExtrusionPath(role, mm3_per_mm, width, height)); + dst.back().polyline = *it_polyline; + } +} + +#if SLIC3R_CPPVER >= 11 +inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) +{ + dst.reserve(dst.size() + polylines.size()); + for (Polylines::const_iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) { + dst.push_back(ExtrusionPath(role, mm3_per_mm, width, height)); + dst.back().polyline = std::move(*it_polyline); + } +} +#endif // SLIC3R_CPPVER >= 11 + inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) { dst.reserve(dst.size() + polylines.size()); diff --git a/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp b/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp index c37328c69..c763952d6 100644 --- a/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp +++ b/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp @@ -168,7 +168,7 @@ void Fill3DHoneycomb::_fill_surface_single( it->translate(bb.min.x, bb.min.y); // clip pattern to boundaries - intersection(polylines, (Polygons)expolygon, &polylines); + polylines = intersection_pl(polylines, (Polygons)expolygon); // connect lines if (! params.dont_connect && ! polylines.empty()) { // prevent calling leftmost_point() on empty collections diff --git a/xs/src/libslic3r/Fill/FillBase.cpp b/xs/src/libslic3r/Fill/FillBase.cpp index d19615aa9..7258e11fe 100644 --- a/xs/src/libslic3r/Fill/FillBase.cpp +++ b/xs/src/libslic3r/Fill/FillBase.cpp @@ -45,8 +45,7 @@ Fill* Fill::new_from_type(const std::string &type) Polylines Fill::fill_surface(const Surface *surface, const FillParams ¶ms) { // Perform offset. - Slic3r::ExPolygons expp; - offset(surface->expolygon, &expp, -0.5*scale_(this->spacing)); + Slic3r::ExPolygons expp = offset_ex(surface->expolygon, float(-0.5*scale_(this->spacing))); // Create the infills for each of the regions. Polylines polylines_out; for (size_t i = 0; i < expp.size(); ++ i) diff --git a/xs/src/libslic3r/Fill/FillConcentric.cpp b/xs/src/libslic3r/Fill/FillConcentric.cpp index 27914866d..156e3478a 100644 --- a/xs/src/libslic3r/Fill/FillConcentric.cpp +++ b/xs/src/libslic3r/Fill/FillConcentric.cpp @@ -33,7 +33,7 @@ void FillConcentric::_fill_surface_single( // generate paths from the outermost to the innermost, to avoid // adhesion problems of the first central tiny loops - union_pt_chained(loops, &loops, false); + loops = union_pt_chained(loops, false); // split paths using a nearest neighbor search size_t iPathFirst = polylines_out.size(); diff --git a/xs/src/libslic3r/Fill/FillHoneycomb.cpp b/xs/src/libslic3r/Fill/FillHoneycomb.cpp index b264d80cc..22dea85da 100644 --- a/xs/src/libslic3r/Fill/FillHoneycomb.cpp +++ b/xs/src/libslic3r/Fill/FillHoneycomb.cpp @@ -93,7 +93,7 @@ void FillHoneycomb::_fill_surface_single( Polylines p; for (Polygons::iterator it = polygons.begin(); it != polygons.end(); ++ it) p.push_back((Polyline)(*it)); - intersection(p, (Polygons)expolygon, &paths); + paths = intersection_pl(p, to_polygons(expolygon)); } // connect paths @@ -122,7 +122,7 @@ void FillHoneycomb::_fill_surface_single( } // clip paths again to prevent connection segments from crossing the expolygon boundaries - intersection(paths, to_polygons(offset_ex(expolygon, SCALED_EPSILON)), &paths); + paths = intersection_pl(paths, to_polygons(offset_ex(expolygon, SCALED_EPSILON))); // Move the polylines to the output, avoid a deep copy. size_t j = polylines_out.size(); polylines_out.resize(j + paths.size(), Polyline()); diff --git a/xs/src/libslic3r/Fill/FillPlanePath.cpp b/xs/src/libslic3r/Fill/FillPlanePath.cpp index 34e155a06..f71ef95a1 100644 --- a/xs/src/libslic3r/Fill/FillPlanePath.cpp +++ b/xs/src/libslic3r/Fill/FillPlanePath.cpp @@ -44,7 +44,7 @@ void FillPlanePath::_fill_surface_single( coord_t(floor(it->x * distance_between_lines + 0.5)), coord_t(floor(it->y * distance_between_lines + 0.5)))); // intersection(polylines_src, offset((Polygons)expolygon, scale_(0.02)), &polylines); - intersection(polylines, (Polygons)expolygon, &polylines); + polylines = intersection_pl(polylines, to_polygons(expolygon)); /* if (1) { diff --git a/xs/src/libslic3r/Fill/FillRectilinear.cpp b/xs/src/libslic3r/Fill/FillRectilinear.cpp index 5559a5437..991adc0b3 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear.cpp @@ -63,7 +63,7 @@ void FillRectilinear::_fill_surface_single( pts.push_back(it->a); pts.push_back(it->b); } - Polylines polylines = intersection(polylines_src, offset((Polygons)expolygon, scale_(0.02)), false); + Polylines polylines = intersection_pl(polylines_src, offset(to_polygons(expolygon), scale_(0.02)), false); // FIXME Vojtech: This is only performed for horizontal lines, not for the vertical lines! const float INFILL_OVERLAP_OVER_SPACING = 0.3f; diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index ee76e75d9..e23e53465 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -315,8 +315,7 @@ GCode::change_layer(const Layer &layer) // avoid computing islands and overhangs if they're not needed if (this->config.avoid_crossing_perimeters) { - ExPolygons islands; - union_(layer.slices, &islands, true); + ExPolygons islands = union_ex(layer.slices, true); this->avoid_crossing_perimeters.init_layer_mp(islands); } diff --git a/xs/src/libslic3r/Layer.cpp b/xs/src/libslic3r/Layer.cpp index d3399d46e..929460169 100644 --- a/xs/src/libslic3r/Layer.cpp +++ b/xs/src/libslic3r/Layer.cpp @@ -105,7 +105,7 @@ Layer::make_slices() FOREACH_LAYERREGION(this, layerm) { polygons_append(slices_p, to_polygons((*layerm)->slices)); } - union_(slices_p, &slices); + slices = union_ex(slices_p); } this->slices.expolygons.clear(); @@ -132,15 +132,11 @@ Layer::merge_slices() if (this->regions.size() == 1) { // Optimization, also more robust. Don't merge classified pieces of layerm->slices, // but use the non-split islands of a layer. For a single region print, these shall be equal. - this->regions.front()->slices.surfaces.clear(); - surfaces_append(this->regions.front()->slices.surfaces, this->slices.expolygons, stInternal); + this->regions.front()->slices.set(this->slices.expolygons, stInternal); } else { FOREACH_LAYERREGION(this, layerm) { - ExPolygons expp; // without safety offset, artifacts are generated (GH #2494) - union_(to_polygons(STDMOVE((*layerm)->slices.surfaces)), &expp, true); - (*layerm)->slices.surfaces.clear(); - surfaces_append((*layerm)->slices.surfaces, expp, stInternal); + (*layerm)->slices.set(union_ex(to_polygons(STDMOVE((*layerm)->slices.surfaces)), true), stInternal); } } } @@ -223,7 +219,7 @@ Layer::make_perimeters() } // merge the surfaces assigned to each group for (std::map::const_iterator it = slices.begin(); it != slices.end(); ++it) - surfaces_append(new_slices.surfaces, union_ex(it->second, true), it->second.front()); + new_slices.append(union_ex(it->second, true), it->second.front()); } // make perimeters @@ -236,8 +232,7 @@ Layer::make_perimeters() // Separate the fill surfaces. ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices); (*l)->fill_expolygons = expp; - (*l)->fill_surfaces.surfaces.clear(); - surfaces_append((*l)->fill_surfaces.surfaces, STDMOVE(expp), fill_surfaces.surfaces.front()); + (*l)->fill_surfaces.set(STDMOVE(expp), fill_surfaces.surfaces.front()); } } } diff --git a/xs/src/libslic3r/LayerRegion.cpp b/xs/src/libslic3r/LayerRegion.cpp index 618396963..f0063114a 100644 --- a/xs/src/libslic3r/LayerRegion.cpp +++ b/xs/src/libslic3r/LayerRegion.cpp @@ -52,8 +52,7 @@ void LayerRegion::slices_to_fill_surfaces_clipped() Polygons fill_boundaries = to_polygons(this->fill_expolygons); this->fill_surfaces.surfaces.clear(); for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++ surface) - surfaces_append( - this->fill_surfaces.surfaces, + this->fill_surfaces.append( intersection_ex(to_polygons(surface->expolygon), fill_boundaries), surface->surface_type); } diff --git a/xs/src/libslic3r/MotionPlanner.cpp b/xs/src/libslic3r/MotionPlanner.cpp index 21afb37c4..9fc1695c0 100644 --- a/xs/src/libslic3r/MotionPlanner.cpp +++ b/xs/src/libslic3r/MotionPlanner.cpp @@ -142,7 +142,7 @@ MotionPlanner::shortest_path(const Point &from, const Point &to) { // grow our environment slightly in order for simplify_by_visibility() // to work best by considering moves on boundaries valid as well - ExPolygonCollection grown_env(offset_ex(env.env, +SCALED_EPSILON)); + ExPolygonCollection grown_env(offset_ex(env.env.expolygons, +SCALED_EPSILON)); if (island_idx == -1) { /* If 'from' or 'to' are not inside our env, they were connected using the @@ -155,12 +155,12 @@ MotionPlanner::shortest_path(const Point &from, const Point &to) if (!grown_env.contains(from)) { // delete second point while the line connecting first to third crosses the // boundaries as many times as the current first to second - while (polyline.points.size() > 2 && intersection((Lines)Line(from, polyline.points[2]), grown_env).size() == 1) { + while (polyline.points.size() > 2 && intersection_ln((Lines)Line(from, polyline.points[2]), grown_env).size() == 1) { polyline.points.erase(polyline.points.begin() + 1); } } if (!grown_env.contains(to)) { - while (polyline.points.size() > 2 && intersection((Lines)Line(*(polyline.points.end() - 3), to), grown_env).size() == 1) { + while (polyline.points.size() > 2 && intersection_ln((Lines)Line(*(polyline.points.end() - 3), to), grown_env).size() == 1) { polyline.points.erase(polyline.points.end() - 2); } } @@ -294,7 +294,7 @@ MotionPlannerEnv::nearest_env_point(const Point &from, const Point &to) const size_t result = from.nearest_waypoint_index(pp, to); // as we assume 'from' is outside env, any node will require at least one crossing - if (intersection((Lines)Line(from, pp[result]), this->island).size() > 1) { + if (intersection_ln((Lines)Line(from, pp[result]), this->island).size() > 1) { // discard result pp.erase(pp.begin() + result); } else { diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp index 299e4c787..730e5e501 100644 --- a/xs/src/libslic3r/PerimeterGenerator.cpp +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -314,8 +314,7 @@ PerimeterGenerator::process() coord_t min_perimeter_infill_spacing = ispacing * (1 - INSET_OVERLAP_TOLERANCE); // append infill areas to fill_surfaces - surfaces_append( - this->fill_surfaces->surfaces, + this->fill_surfaces->append( offset2_ex( pp, -inset -min_perimeter_infill_spacing/2, @@ -353,36 +352,24 @@ PerimeterGenerator::_traverse_loops(const PerimeterGeneratorLoops &loops, if (this->config->overhangs && this->layer_id > 0 && !(this->object_config->support_material && this->object_config->support_material_contact_distance.value == 0)) { // get non-overhang paths by intersecting this loop with the grown lower slices - { - Polylines polylines; - intersection((Polygons)loop->polygon, this->_lower_slices_p, &polylines); - - for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) { - ExtrusionPath path(role); - path.polyline = *polyline; - path.mm3_per_mm = is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm; - path.width = is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width; - path.height = this->layer_height; - paths.push_back(path); - } - } + extrusion_paths_append( + paths, + intersection_pl(loop->polygon, this->_lower_slices_p), + role, + is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm, + is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width, + this->layer_height); // get overhang paths by checking what parts of this loop fall // outside the grown lower slices (thus where the distance between // the loop centerline and original lower slices is >= half nozzle diameter - { - Polylines polylines; - diff((Polygons)loop->polygon, this->_lower_slices_p, &polylines); - - for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) { - ExtrusionPath path(erOverhangPerimeter); - path.polyline = *polyline; - path.mm3_per_mm = this->_mm3_per_mm_overhang; - path.width = this->overhang_flow.width; - path.height = this->overhang_flow.height; - paths.push_back(path); - } - } + extrusion_paths_append( + paths, + diff_pl(loop->polygon, this->_lower_slices_p), + erOverhangPerimeter, + this->_mm3_per_mm_overhang, + this->overhang_flow.width, + this->overhang_flow.height); // reapply the nearest point search for starting point // We allow polyline reversal because Clipper may have randomly diff --git a/xs/src/libslic3r/Polygon.cpp b/xs/src/libslic3r/Polygon.cpp index 056c285ec..60ccd792d 100644 --- a/xs/src/libslic3r/Polygon.cpp +++ b/xs/src/libslic3r/Polygon.cpp @@ -112,9 +112,7 @@ double Polygon::area() const bool Polygon::is_counter_clockwise() const { - ClipperLib::Path p; - Slic3rMultiPoint_to_ClipperPath(*this, &p); - return ClipperLib::Orientation(p); + return ClipperLib::Orientation(Slic3rMultiPoint_to_ClipperPath(*this)); } bool @@ -190,8 +188,7 @@ Polygon::simplify(double tolerance) const Polygons pp; pp.push_back(p); - simplify_polygons(pp, &pp); - return pp; + return simplify_polygons(pp); } void diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index f396409e7..3583c627b 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -608,20 +608,15 @@ Print::validate() const object->model_object()->instances.front()->transform_polygon(&convex_hull); // grow convex hull with the clearance margin - { - Polygons grown_hull; - offset(convex_hull, &grown_hull, scale_(this->config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)); - convex_hull = grown_hull.front(); - } + convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front(); // now we check that no instance of convex_hull intersects any of the previously checked object instances for (Points::const_iterator copy = object->_shifted_copies.begin(); copy != object->_shifted_copies.end(); ++copy) { Polygon p = convex_hull; p.translate(*copy); - if (intersects(a, p)) + if (! intersection(a, p).empty()) return "Some objects are too close; your extruder will collide with them."; - - union_(a, p, &a); + polygons_append(a, p); } } } diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 90449d64f..8d6ddaf21 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -449,7 +449,7 @@ void PrintObject::detect_surfaces_type() { Polygons topbottom = to_polygons(top); polygons_append(topbottom, to_polygons(bottom)); - surfaces_append(layerm->slices.surfaces, + layerm->slices.append( #if 0 offset2_ex(diff(layerm_slices_surfaces, topbottom, true), -offset, offset), #else @@ -458,8 +458,8 @@ void PrintObject::detect_surfaces_type() stInternal); } - surfaces_append(layerm->slices.surfaces, STDMOVE(top)); - surfaces_append(layerm->slices.surfaces, STDMOVE(bottom)); + layerm->slices.append(STDMOVE(top)); + layerm->slices.append(STDMOVE(bottom)); // Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n", // $layerm->layer->id, scalar(@bottom), scalar(@top), scalar(@internal) if $Slic3r::debug; @@ -865,7 +865,7 @@ PrintObject::bridge_over_infill() #endif // compute the remaning internal solid surfaces as difference - ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, true); + ExPolygons not_to_bridge = diff_ex(internal_solid, to_polygons(to_bridge), true); to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true); // build the new collection of fill_surfaces @@ -1011,7 +1011,7 @@ void PrintObject::_slice() if (my_parts.empty()) continue; // Remove such parts from original region. - other_layerm->slices.set(diff_ex(other_slices, my_parts), stInternal); + other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal); // Append new parts to our region. layerm->slices.append(std::move(my_parts), stInternal); } @@ -1039,7 +1039,7 @@ end: if (layer->regions.size() == 1) { // single region LayerRegion *layerm = layer->regions.front(); - layerm->slices.set(offset_ex(to_polygons(std::move(layerm->slices.surfaces)), delta), stInternal); + layerm->slices.set(offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta), stInternal); } else { if (delta < 0) { // multiple regions, shrinking @@ -1060,7 +1060,7 @@ end: Polygons processed; for (size_t region_id = 0;; ++ region_id) { LayerRegion *layerm = layer->regions[region_id]; - ExPolygons slices = offset_ex(to_polygons(layerm->slices.surfaces), delta); + ExPolygons slices = offset_ex(to_expolygons(layerm->slices.surfaces), delta); if (region_id > 0) // Trim by the slices of already processed regions. slices = diff_ex(to_polygons(std::move(slices)), processed); diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp index 47ce5d6db..8bf9e9fc7 100644 --- a/xs/src/libslic3r/SupportMaterial.cpp +++ b/xs/src/libslic3r/SupportMaterial.cpp @@ -575,7 +575,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ // workaround for Clipper bug, see Slic3r::Polygon::clip_as_polyline() for (Polylines::iterator it = overhang_perimeters.begin(); it != overhang_perimeters.end(); ++ it) it->points[0].x += 1; - diff(overhang_perimeters, lower_grown_slices, &overhang_perimeters); + overhang_perimeters = diff_pl(overhang_perimeters, lower_grown_slices); // only consider straight overhangs // only consider overhangs having endpoints inside layer's slices @@ -588,13 +588,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ if (it->is_straight()) { it->extend_start(fw); it->extend_end(fw); - if (layer.slices.contains(it->first_point()) && layer.slices.contains(it->last_point())) { + if (layer.slices.contains(it->first_point()) && layer.slices.contains(it->last_point())) // Offset a polyline into a polygon. - Polylines tmp; tmp.push_back(*it); - Polygons out; - offset(tmp, &out, 0.5f * w + 10.f); - polygons_append(bridged_perimeters, out); - } + polygons_append(bridged_perimeters, offset(*it, 0.5f * w + 10.f)); } } bridged_perimeters = union_(bridged_perimeters); @@ -611,13 +607,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ Polygons unsupported_bridge_polygons; for (Polylines::const_iterator it = layerm.unsupported_bridge_edges.polylines.begin(); - it != layerm.unsupported_bridge_edges.polylines.end(); ++ it) { + it != layerm.unsupported_bridge_edges.polylines.end(); ++ it) // Offset a polyline into a polygon. - Polylines tmp; tmp.push_back(*it); - Polygons out; - offset(tmp, &out, scale_(SUPPORT_MATERIAL_MARGIN)); - polygons_append(unsupported_bridge_polygons, out); - } + polygons_append(unsupported_bridge_polygons, offset(*it, scale_(SUPPORT_MATERIAL_MARGIN))); polygons_append(diff_polygons, intersection(unsupported_bridge_polygons, bridges)); } else { // just remove bridged areas @@ -1596,10 +1588,8 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const // Positions of the loop centers. Polygons circles; Polygons overhang_with_margin = offset(overhang_polygons, 0.5f * flow.scaled_width()); - for (Polygons::const_iterator it_contact = top_contact_polygons.begin(); it_contact != top_contact_polygons.end(); ++ it_contact) { - Polylines tmp; - tmp.push_back(it_contact->split_at_first_point()); - if (! intersection(tmp, overhang_with_margin).empty()) { + for (Polygons::const_iterator it_contact = top_contact_polygons.begin(); it_contact != top_contact_polygons.end(); ++ it_contact) + if (! intersection_pl(it_contact->split_at_first_point(), overhang_with_margin).empty()) { external_loops.push_back(*it_contact); Points positions_new = it_contact->equally_spaced_points(circle_distance); for (Points::const_iterator it_center = positions_new.begin(); it_center != positions_new.end(); ++ it_center) { @@ -1609,7 +1599,6 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const circle_new.points[i].translate(*it_center); } } - } // Apply a pattern to the loop. loops0 = diff(external_loops, circles); } @@ -1628,7 +1617,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const loop_lines.reserve(loop_polygons.size()); for (Polygons::const_iterator it = loop_polygons.begin(); it != loop_polygons.end(); ++ it) loop_lines.push_back(it->split_at_first_point()); - loop_lines = intersection(loop_lines, offset(overhang_polygons, scale_(SUPPORT_MATERIAL_MARGIN))); + loop_lines = intersection_pl(loop_lines, offset(overhang_polygons, scale_(SUPPORT_MATERIAL_MARGIN))); } // add the contact infill area to the interface area @@ -1636,9 +1625,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const // extrusions are left inside the circles; however it creates // a very large gap between loops and contact_infill_polygons, so maybe another // solution should be found to achieve both goals - Polygons thick_loop_lines; - offset(loop_lines, &thick_loop_lines, float(circle_radius * 1.1)); - top_contact_layer.layer->polygons = diff(top_contact_layer.layer->polygons, std::move(thick_loop_lines)); + top_contact_layer.layer->polygons = diff(top_contact_layer.layer->polygons, offset(loop_lines, float(circle_radius * 1.1))); // Transform loops into ExtrusionPath objects. extrusion_entities_append_paths( @@ -1857,7 +1844,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( // TODO: use brim ordering algorithm Polygons to_infill_polygons = to_polygons(to_infill); // TODO: use offset2_ex() - to_infill = offset_ex(to_infill_polygons, - flow.scaled_spacing()); + to_infill = offset_ex(to_infill, - flow.scaled_spacing()); extrusion_entities_append_paths( support_layer.support_fills.entities, to_polylines(STDMOVE(to_infill_polygons)), diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index d372b33ea..71e34f3b8 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -370,10 +370,7 @@ TriangleMesh::horizontal_projection() const } // the offset factor was tuned using groovemount.stl - offset(pp, &pp, 0.01 / SCALING_FACTOR); - ExPolygons retval; - union_(pp, &retval, true); - return retval; + return union_ex(offset(pp, 0.01 / SCALING_FACTOR), true); } Polygon @@ -852,17 +849,15 @@ TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) c of the loops, since the Orientation() function provided by Clipper would do the same, thus repeating the calculation */ Polygons::const_iterator loop = loops.begin() + *loop_idx; - if (area[*loop_idx] > +EPSILON) { + if (area[*loop_idx] > +EPSILON) p_slices.push_back(*loop); - } else if (area[*loop_idx] < -EPSILON) { - diff(p_slices, *loop, &p_slices); - } + else if (area[*loop_idx] < -EPSILON) + p_slices = diff(p_slices, *loop); } // perform a safety offset to merge very close facets (TODO: find test case for this) double safety_offset = scale_(0.0499); - ExPolygons ex_slices; - offset2(p_slices, &ex_slices, +safety_offset, -safety_offset); + ExPolygons ex_slices = offset2_ex(p_slices, +safety_offset, -safety_offset); #ifdef SLIC3R_TRIANGLEMESH_DEBUG size_t holes_count = 0; @@ -874,7 +869,7 @@ TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) c #endif // append to the supplied collection - slices->insert(slices->end(), ex_slices.begin(), ex_slices.end()); + expolygons_append(*slices, ex_slices); } void diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index 1544a2608..df4eab4c8 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -532,8 +532,7 @@ SV* polynode2perl(const ClipperLib::PolyNode& node) { HV* hv = newHV(); - Slic3r::Polygon p; - ClipperPath_to_Slic3rMultiPoint(node.Contour, &p); + Slic3r::Polygon p = ClipperPath_to_Slic3rMultiPoint(node.Contour); if (node.IsHole()) { (void)hv_stores( hv, "hole", Slic3r::perl_to_SV_clone_ref(p) ); } else { diff --git a/xs/t/11_clipper.t b/xs/t/11_clipper.t index 8709c0108..321d3048c 100644 --- a/xs/t/11_clipper.t +++ b/xs/t/11_clipper.t @@ -5,7 +5,7 @@ use warnings; use List::Util qw(sum); use Slic3r::XS; -use Test::More tests => 23; +use Test::More tests => 16; my $square = Slic3r::Polygon->new( # ccw [200, 100], @@ -121,41 +121,6 @@ if (0) { # Clipper does not preserve polyline orientation is_deeply $result->[0]->pp, [[200,150], [100,150]], 'clipped line orientation is preserved'; } -if (0) { # Clipper does not preserve polyline orientation - my $result = Slic3r::Geometry::Clipper::intersection_ppl([$hole_in_square], [$square]); - is_deeply $result->[0]->pp, $hole_in_square->split_at_first_point->pp, - 'intersection_ppl - clipping cw polygon as polyline preserves winding order'; -} - -{ - my $square2 = $square->clone; - $square2->translate(50,50); - { - my $result = Slic3r::Geometry::Clipper::intersection_ppl([$square2], [$square]); - is scalar(@$result), 1, 'intersection_ppl - result contains a single line'; - is scalar(@{$result->[0]}), 3, 'intersection_ppl - result contains expected number of points'; - # Clipper does not preserve polyline orientation so we only check the middle point - ###ok $result->[0][0]->coincides_with(Slic3r::Point->new(150,200)), 'intersection_ppl - expected point order'; - ok $result->[0][1]->coincides_with(Slic3r::Point->new(150,150)), 'intersection_ppl - expected point order'; - ###ok $result->[0][2]->coincides_with(Slic3r::Point->new(200,150)), 'intersection_ppl - expected point order'; - } -} - -{ - my $square2 = $square->clone; - $square2->reverse; - $square2->translate(50,50); - { - my $result = Slic3r::Geometry::Clipper::intersection_ppl([$square2], [$square]); - is scalar(@$result), 1, 'intersection_ppl - result contains a single line'; - is scalar(@{$result->[0]}), 3, 'intersection_ppl - result contains expected number of points'; - # Clipper does not preserve polyline orientation so we only check the middle point - ###ok $result->[0][0]->coincides_with(Slic3r::Point->new(200,150)), 'intersection_ppl - expected point order'; - ok $result->[0][1]->coincides_with(Slic3r::Point->new(150,150)), 'intersection_ppl - expected point order'; - ###ok $result->[0][2]->coincides_with(Slic3r::Point->new(150,200)), 'intersection_ppl - expected point order'; - } -} - { # Clipper bug #96 (our issue #2028) my $subject = Slic3r::Polyline->new( @@ -168,17 +133,6 @@ if (0) { # Clipper does not preserve polyline orientation is scalar(@$result), 1, 'intersection_pl - result is not empty'; } -{ - my $subject = Slic3r::Polygon->new( - [44730000,31936670],[55270000,31936670],[55270000,25270000],[74730000,25270000],[74730000,44730000],[68063296,44730000],[68063296,55270000],[74730000,55270000],[74730000,74730000],[55270000,74730000],[55270000,68063296],[44730000,68063296],[44730000,74730000],[25270000,74730000],[25270000,55270000],[31936670,55270000],[31936670,44730000],[25270000,44730000],[25270000,25270000],[44730000,25270000] - ); - my $clip = [ - Slic3r::Polygon->new([75200000,45200000],[54800000,45200000],[54800000,24800000],[75200000,24800000]), - ]; - my $result = Slic3r::Geometry::Clipper::intersection_ppl([$subject], $clip); - is scalar(@$result), 1, 'intersection_ppl - result is not empty'; -} - { # Clipper bug #122 my $subject = [ diff --git a/xs/xsp/Clipper.xsp b/xs/xsp/Clipper.xsp index 6a28ea3ca..7457c8540 100644 --- a/xs/xsp/Clipper.xsp +++ b/xs/xsp/Clipper.xsp @@ -27,7 +27,7 @@ offset(polygons, delta, joinType = ClipperLib::jtMiter, miterLimit = 3) ClipperLib::JoinType joinType double miterLimit CODE: - offset(polygons, &RETVAL, delta, joinType, miterLimit); + RETVAL = offset(polygons, delta, joinType, miterLimit); OUTPUT: RETVAL @@ -38,7 +38,7 @@ offset_ex(polygons, delta, joinType = ClipperLib::jtMiter, miterLimit = 3) ClipperLib::JoinType joinType double miterLimit CODE: - offset(polygons, &RETVAL, delta, joinType, miterLimit); + RETVAL = offset_ex(polygons, delta, joinType, miterLimit); OUTPUT: RETVAL @@ -50,7 +50,7 @@ offset2(polygons, delta1, delta2, joinType = ClipperLib::jtMiter, miterLimit = 3 ClipperLib::JoinType joinType double miterLimit CODE: - offset2(polygons, &RETVAL, delta1, delta2, joinType, miterLimit); + RETVAL = offset2(polygons, delta1, delta2, joinType, miterLimit); OUTPUT: RETVAL @@ -62,7 +62,7 @@ offset2_ex(polygons, delta1, delta2, joinType = ClipperLib::jtMiter, miterLimit ClipperLib::JoinType joinType double miterLimit CODE: - offset2(polygons, &RETVAL, delta1, delta2, joinType, miterLimit); + RETVAL = offset2_ex(polygons, delta1, delta2, joinType, miterLimit); OUTPUT: RETVAL @@ -72,7 +72,7 @@ diff(subject, clip, safety_offset = false) Polygons clip bool safety_offset CODE: - diff(subject, clip, &RETVAL, safety_offset); + RETVAL = diff(subject, clip, safety_offset); OUTPUT: RETVAL @@ -82,7 +82,7 @@ diff_ex(subject, clip, safety_offset = false) Polygons clip bool safety_offset CODE: - diff(subject, clip, &RETVAL, safety_offset); + RETVAL = diff_ex(subject, clip, safety_offset); OUTPUT: RETVAL @@ -91,16 +91,7 @@ diff_pl(subject, clip) Polylines subject Polygons clip CODE: - diff(subject, clip, &RETVAL); - OUTPUT: - RETVAL - -Polylines -diff_ppl(subject, clip) - Polygons subject - Polygons clip - CODE: - diff(subject, clip, &RETVAL); + RETVAL = diff_pl(subject, clip); OUTPUT: RETVAL @@ -110,7 +101,7 @@ intersection(subject, clip, safety_offset = false) Polygons clip bool safety_offset CODE: - intersection(subject, clip, &RETVAL, safety_offset); + RETVAL = intersection(subject, clip, safety_offset); OUTPUT: RETVAL @@ -120,7 +111,7 @@ intersection_ex(subject, clip, safety_offset = false) Polygons clip bool safety_offset CODE: - intersection(subject, clip, &RETVAL, safety_offset); + RETVAL = intersection_ex(subject, clip, safety_offset); OUTPUT: RETVAL @@ -129,26 +120,7 @@ intersection_pl(subject, clip) Polylines subject Polygons clip CODE: - intersection(subject, clip, &RETVAL); - OUTPUT: - RETVAL - -Polylines -intersection_ppl(subject, clip) - Polygons subject - Polygons clip - CODE: - intersection(subject, clip, &RETVAL); - OUTPUT: - RETVAL - -ExPolygons -xor_ex(subject, clip, safety_offset = false) - Polygons subject - Polygons clip - bool safety_offset - CODE: - xor_(subject, clip, &RETVAL, safety_offset); + RETVAL = intersection_pl(subject, clip); OUTPUT: RETVAL @@ -157,7 +129,7 @@ union(subject, safety_offset = false) Polygons subject bool safety_offset CODE: - union_(subject, &RETVAL, safety_offset); + RETVAL = union_(subject, safety_offset); OUTPUT: RETVAL @@ -166,20 +138,7 @@ union_ex(subject, safety_offset = false) Polygons subject bool safety_offset CODE: - union_(subject, &RETVAL, safety_offset); - OUTPUT: - RETVAL - -SV* -union_pt(subject, safety_offset = false) - Polygons subject - bool safety_offset - CODE: - // perform operation - ClipperLib::PolyTree polytree; - union_pt(subject, &polytree, safety_offset); - - RETVAL = polynode_children_2_perl(polytree); + RETVAL = union_ex(subject, safety_offset); OUTPUT: RETVAL @@ -188,7 +147,7 @@ union_pt_chained(subject, safety_offset = false) Polygons subject bool safety_offset CODE: - union_pt_chained(subject, &RETVAL, safety_offset); + RETVAL = union_pt_chained(subject, safety_offset); OUTPUT: RETVAL @@ -196,7 +155,7 @@ Polygons simplify_polygons(subject) Polygons subject CODE: - simplify_polygons(subject, &RETVAL); + RETVAL = simplify_polygons(subject); OUTPUT: RETVAL diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp index 176826290..60d7c6aca 100644 --- a/xs/xsp/Polyline.xsp +++ b/xs/xsp/Polyline.xsp @@ -85,7 +85,7 @@ Polyline::grow(delta, joinType = ClipperLib::jtSquare, miterLimit = 3) ClipperLib::JoinType joinType double miterLimit CODE: - offset(*THIS, &RETVAL, delta, joinType, miterLimit); + RETVAL = offset(*THIS, delta, joinType, miterLimit); OUTPUT: RETVAL diff --git a/xs/xsp/Surface.xsp b/xs/xsp/Surface.xsp index 4e3bbbb69..379774f0a 100644 --- a/xs/xsp/Surface.xsp +++ b/xs/xsp/Surface.xsp @@ -88,7 +88,7 @@ Surface::offset(delta, joinType = ClipperLib::jtMiter, miterLimit = 3) ClipperLib::JoinType joinType double miterLimit CODE: - offset(*THIS, &RETVAL, delta, joinType, miterLimit); + surfaces_append(RETVAL, offset_ex(THIS->expolygon, delta, joinType, miterLimit), *THIS); OUTPUT: RETVAL