diff --git a/lib/Slic3r/Geometry/Clipper.pm b/lib/Slic3r/Geometry/Clipper.pm index 652abb8dbe..a3239c2faa 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 + diff_ex diff union_ex intersection_ex JT_ROUND JT_MITER JT_SQUARE is_counter_clockwise union_pt offset2 offset2_ex intersection intersection_pl diff_pl union CLIPPER_OFFSET_SCALE - union_pt_chained diff_ppl intersection_ppl); + union_pt_chained intersection_ppl); 1; diff --git a/xs/src/libslic3r/BridgeDetector.cpp b/xs/src/libslic3r/BridgeDetector.cpp index 46d6ff1f34..f9061e405f 100644 --- a/xs/src/libslic3r/BridgeDetector.cpp +++ b/xs/src/libslic3r/BridgeDetector.cpp @@ -30,12 +30,11 @@ BridgeDetector::BridgeDetector(const ExPolygon &_expolygon, const ExPolygonColle { /* outset our bridge by an arbitrary amout; we'll use this outer margin for detecting anchors */ - Polygons grown; - offset((Polygons)this->expolygon, &grown, this->extrusion_width); + Polygons grown = offset(this->expolygon, this->extrusion_width); // 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 - intersection(grown, this->lower_slices.contours(), &this->_edges); + this->_edges = intersection_pl(grown, this->lower_slices.contours()); #ifdef SLIC3R_DEBUG printf(" bridge has %zu support(s)\n", this->_edges.size()); @@ -43,7 +42,7 @@ BridgeDetector::BridgeDetector(const ExPolygon &_expolygon, const ExPolygonColle // detect anchors as intersection between our bridge expolygon and the lower slices // safety offset required to avoid Clipper from detecting empty intersection while Boost actually found some edges - intersection(grown, this->lower_slices, &this->_anchors, true); + this->_anchors = intersection_ex(grown, this->lower_slices, true); /* if (0) { @@ -65,8 +64,7 @@ BridgeDetector::detect_angle() /* Outset the bridge expolygon by half the amount we used for detecting anchors; we'll use this one to clip our test lines and be sure that their endpoints are inside the anchors and not on their contours leading to false negatives. */ - Polygons clip_area; - offset(this->expolygon, &clip_area, +this->extrusion_width/2); + Polygons clip_area = offset(this->expolygon, +this->extrusion_width/2); /* we'll now try several directions using a rudimentary visibility check: bridge in several directions and then sum the length of lines having both @@ -131,8 +129,7 @@ BridgeDetector::detect_angle() for (coord_t y = bb.min.y; y <= bb.max.y; y += line_increment) lines.push_back(Line(Point(bb.min.x, y), Point(bb.max.x, y))); - Lines clipped_lines; - intersection(lines, my_clip_area, &clipped_lines); + Lines clipped_lines = intersection_ln(lines, my_clip_area); // remove any line not having both endpoints within anchors for (size_t i = 0; i < clipped_lines.size(); ++i) { @@ -194,11 +191,11 @@ BridgeDetector::detect_angle() return true; } -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) return Polygons(); // Clone our expolygon and rotate it so that we work with vertical lines. ExPolygon expolygon = this->expolygon; @@ -207,8 +204,7 @@ BridgeDetector::coverage(double angle, Polygons* coverage) const /* 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(expolygon, &grown, this->extrusion_width/2.0); + ExPolygons grown = offset_ex(expolygon, this->extrusion_width/2.0); // Compute trapezoids according to a vertical orientation Polygons trapezoids; @@ -226,9 +222,7 @@ BridgeDetector::coverage(double angle, Polygons* coverage) const Polygons covered; for (Polygons::const_iterator trapezoid = trapezoids.begin(); trapezoid != trapezoids.end(); ++trapezoid) { - Lines lines = trapezoid->lines(); - Lines supported; - intersection(lines, anchors, &supported); + Lines supported = intersection_ln(trapezoid->lines(), anchors); // not nice, we need a more robust non-numeric check for (size_t i = 0; i < supported.size(); ++i) { @@ -242,14 +236,13 @@ BridgeDetector::coverage(double angle, Polygons* coverage) const } // merge trapezoids and rotate them back - Polygons _coverage; - union_(covered, &_coverage); + Polygons _coverage = union_(covered); for (Polygons::iterator p = _coverage.begin(); p != _coverage.end(); ++p) p->rotate(-(PI/2.0 - angle), Point(0,0)); // intersect trapezoids with actual bridge area to remove extra margins // and append it to result - intersection(_coverage, this->expolygon, coverage); + return intersection(_coverage, this->expolygon); /* if (0) { @@ -268,22 +261,14 @@ BridgeDetector::coverage(double angle, Polygons* coverage) const */ } -Polygons -BridgeDetector::coverage(double angle) const -{ - Polygons pp; - this->coverage(angle, &pp); - return pp; -} - /* This method returns the bridge edges (as polylines) that are not supported but would allow the entire bridge area to be bridged with detected angle if supported too */ -void -BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const +Polylines +BridgeDetector::unsupported_edges(double angle) const { if (angle == -1) angle = this->angle; - if (angle == -1) return; + if (angle == -1) return Polylines(); // get bridge edges (both contour and holes) Polylines bridge_edges; @@ -293,10 +278,10 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const } // get unsupported edges - Polygons grown_lower; - offset(this->lower_slices, &grown_lower, +this->extrusion_width); - Polylines _unsupported; - diff(bridge_edges, grown_lower, &_unsupported); + Polylines _unsupported = diff_pl( + bridge_edges, + offset(this->lower_slices, +this->extrusion_width) + ); /* 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, @@ -304,13 +289,15 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const extrusions would be anchored within such length (i.e. a slightly non-parallel bridging direction might still benefit from anchors if long enough) double angle_tolerance = PI / 180.0 * 5.0; */ + Polylines unsupported; for (Polylines::const_iterator polyline = _unsupported.begin(); polyline != _unsupported.end(); ++polyline) { Lines lines = polyline->lines(); for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { if (!Slic3r::Geometry::directions_parallel(line->direction(), angle)) - unsupported->push_back(*line); + unsupported.push_back(*line); } } + return unsupported; /* if (0) { @@ -328,12 +315,4 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const */ } -Polylines -BridgeDetector::unsupported_edges(double angle) const -{ - Polylines pp; - this->unsupported_edges(angle, &pp); - return pp; -} - } diff --git a/xs/src/libslic3r/BridgeDetector.hpp b/xs/src/libslic3r/BridgeDetector.hpp index 5b1566b27b..14bfd80afa 100644 --- a/xs/src/libslic3r/BridgeDetector.hpp +++ b/xs/src/libslic3r/BridgeDetector.hpp @@ -18,9 +18,7 @@ class BridgeDetector { BridgeDetector(const ExPolygon &_expolygon, 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; private: diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp index 69c8643f37..37cc4b698f 100644 --- a/xs/src/libslic3r/ClipperUtils.cpp +++ b/xs/src/libslic3r/ClipperUtils.cpp @@ -5,54 +5,53 @@ namespace Slic3r { //----------------------------------------------------------- // legacy code from Clipper documentation -void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPolygons* expolygons) +void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, ExPolygons* expolygons) { size_t cnt = expolygons->size(); expolygons->resize(cnt + 1); - ClipperPath_to_Slic3rMultiPoint(polynode.Contour, &(*expolygons)[cnt].contour); + (*expolygons)[cnt].contour = ClipperPath_to_Slic3rMultiPoint(polynode.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]); + (*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); } } -void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons* expolygons) +ExPolygons +PolyTreeToExPolygons(ClipperLib::PolyTree& polytree) { - expolygons->clear(); - for (int i = 0; i < polytree.ChildCount(); ++i) - AddOuterPolyNodeToExPolygons(*polytree.Childs[i], expolygons); + ExPolygons retval; + for (int i = 0; i < polytree.ChildCount(); ++i) + AddOuterPolyNodeToExPolygons(*polytree.Childs[i], &retval); + return retval; } //----------------------------------------------------------- template -void -ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input, T* output) +T +ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input) { - output->points.clear(); - for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit) { - output->points.push_back(Slic3r::Point( (*pit).X, (*pit).Y )); - } + 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 void ClipperPath_to_Slic3rMultiPoint(const ClipperLib::Path &input, Slic3r::Polygon* output); template -void -ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input, T* output) +T +ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input) { - output->clear(); - 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); - } + T retval; + for (ClipperLib::Paths::const_iterator it = input.begin(); it != input.end(); ++it) + retval.push_back(ClipperPath_to_Slic3rMultiPoint(*it)); + return retval; } -void -ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, Slic3r::ExPolygons* output) +ExPolygons +ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input) { // init Clipper ClipperLib::Clipper clipper; @@ -64,29 +63,26 @@ ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, Slic3r::ExPolyg 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); + return PolyTreeToExPolygons(polytree); } -void -Slic3rMultiPoint_to_ClipperPath(const Slic3r::MultiPoint &input, ClipperLib::Path* output) +ClipperLib::Path +Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input) { - output->clear(); - for (Slic3r::Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) { - output->push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); - } + 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; } template -void -Slic3rMultiPoints_to_ClipperPaths(const T &input, ClipperLib::Paths* output) +ClipperLib::Paths +Slic3rMultiPoints_to_ClipperPaths(const T &input) { - output->clear(); - for (typename T::const_iterator it = input.begin(); it != input.end(); ++it) { - ClipperLib::Path p; - Slic3rMultiPoint_to_ClipperPath(*it, &p); - output->push_back(p); - } + ClipperLib::Paths retval; + for (typename T::const_iterator it = input.begin(); it != input.end(); ++it) + retval.push_back(Slic3rMultiPoint_to_ClipperPath(*it)); + return retval; } void @@ -100,13 +96,12 @@ scaleClipperPolygons(ClipperLib::Paths &polygons, const double scale) } } -void -offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta, +ClipperLib::Paths +_offset(const Polygons &polygons, const float delta, double scale, ClipperLib::JoinType joinType, double miterLimit) { // read input - ClipperLib::Paths input; - Slic3rMultiPoints_to_ClipperPaths(polygons, &input); + ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polygons); // scale input scaleClipperPolygons(input, scale); @@ -119,40 +114,20 @@ offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float co.MiterLimit = miterLimit; } co.AddPaths(input, joinType, ClipperLib::etClosedPolygon); - co.Execute(*retval, (delta*scale)); + ClipperLib::Paths retval; + co.Execute(retval, (delta*scale)); // unscale output - scaleClipperPolygons(*retval, 1/scale); + scaleClipperPolygons(retval, 1/scale); + return retval; } -void -offset(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta, - double scale, ClipperLib::JoinType joinType, double miterLimit) -{ - // perform offset - ClipperLib::Paths output; - offset(polygons, &output, delta, scale, joinType, miterLimit); - - // convert into ExPolygons - ClipperPaths_to_Slic3rMultiPoints(output, retval); -} - -Slic3r::Polygons -offset(const Slic3r::Polygons &polygons, const float delta, - double scale, ClipperLib::JoinType joinType, double miterLimit) -{ - Slic3r::Polygons pp; - offset(polygons, &pp, delta, scale, joinType, miterLimit); - return pp; -} - -void -offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const float delta, +ClipperLib::Paths +_offset(const Polylines &polylines, const float delta, double scale, ClipperLib::JoinType joinType, double miterLimit) { // read input - ClipperLib::Paths input; - Slic3rMultiPoints_to_ClipperPaths(polylines, &input); + ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polylines); // scale input scaleClipperPolygons(input, scale); @@ -165,82 +140,78 @@ offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const floa co.MiterLimit = miterLimit; } co.AddPaths(input, joinType, ClipperLib::etOpenButt); - co.Execute(*retval, (delta*scale)); + ClipperLib::Paths retval; + co.Execute(retval, (delta*scale)); // unscale output - scaleClipperPolygons(*retval, 1/scale); + scaleClipperPolygons(retval, 1/scale); + return retval; } -void -offset(const Slic3r::Polylines &polylines, Slic3r::Polygons* retval, const float delta, +Polygons +offset(const Polygons &polygons, const float delta, double scale, ClipperLib::JoinType joinType, double miterLimit) { // perform offset - ClipperLib::Paths output; - offset(polylines, &output, delta, scale, joinType, miterLimit); + ClipperLib::Paths output = _offset(polygons, delta, scale, joinType, miterLimit); // convert into ExPolygons - ClipperPaths_to_Slic3rMultiPoints(output, retval); + return ClipperPaths_to_Slic3rMultiPoints(output); } -void -offset(const Slic3r::Surface &surface, Slic3r::Surfaces* retval, const float delta, +Polygons +offset(const Polylines &polylines, const float delta, double scale, ClipperLib::JoinType joinType, double miterLimit) { // perform offset - Slic3r::ExPolygons expp; - offset(surface.expolygon, &expp, delta, scale, joinType, miterLimit); + ClipperLib::Paths output = _offset(polylines, delta, scale, joinType, miterLimit); + + // convert into ExPolygons + return ClipperPaths_to_Slic3rMultiPoints(output); +} + +Surfaces +offset(const Surface &surface, const float delta, + double scale, ClipperLib::JoinType joinType, double miterLimit) +{ + // perform offset + ExPolygons expp = offset_ex(surface.expolygon, delta, scale, joinType, miterLimit); // clone the input surface for each expolygon we got - retval->clear(); - retval->reserve(expp.size()); + Surfaces retval; + 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); + retval.push_back(s); } + return retval; } -void -offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta, +ExPolygons +offset_ex(const Polygons &polygons, const float delta, double scale, ClipperLib::JoinType joinType, double miterLimit) { // perform offset - ClipperLib::Paths output; - offset(polygons, &output, delta, scale, joinType, miterLimit); + ClipperLib::Paths output = _offset(polygons, delta, scale, joinType, miterLimit); // convert into ExPolygons - ClipperPaths_to_Slic3rExPolygons(output, retval); + return ClipperPaths_to_Slic3rExPolygons(output); } -Slic3r::ExPolygons -offset_ex(const Slic3r::Polygons &polygons, const float delta, +ExPolygons +offset_ex(const ExPolygons &expolygons, const float delta, double scale, ClipperLib::JoinType joinType, double miterLimit) { - Slic3r::ExPolygons expp; - offset(polygons, &expp, delta, scale, joinType, miterLimit); - return expp; + return offset_ex(to_polygons(expolygons), delta, scale, joinType, miterLimit); } -Slic3r::ExPolygons -offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, - double scale, ClipperLib::JoinType joinType, double miterLimit) -{ - Slic3r::Polygons pp; - for (Slic3r::ExPolygons::const_iterator ex = expolygons.begin(); ex != expolygons.end(); ++ex) { - Slic3r::Polygons pp2 = *ex; - pp.insert(pp.end(), pp2.begin(), pp2.end()); - } - return offset_ex(pp, delta, scale, joinType, miterLimit); -} - -void -offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1, - const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit) +ClipperLib::Paths +_offset2(const Polygons &polygons, const float delta1, const float delta2, + const double scale, const ClipperLib::JoinType joinType, const double miterLimit) { // read input - ClipperLib::Paths input; - Slic3rMultiPoints_to_ClipperPaths(polygons, &input); + ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polygons); // scale input scaleClipperPolygons(input, scale); @@ -261,62 +232,44 @@ offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float // perform second offset co.Clear(); co.AddPaths(output1, joinType, ClipperLib::etClosedPolygon); - co.Execute(*retval, (delta2*scale)); + ClipperLib::Paths retval; + co.Execute(retval, (delta2*scale)); // unscale output - scaleClipperPolygons(*retval, 1/scale); + scaleClipperPolygons(retval, 1/scale); + return retval; } -void -offset2(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta1, - const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit) +Polygons +offset2(const Polygons &polygons, const float delta1, const float delta2, + const double scale, const ClipperLib::JoinType joinType, const double miterLimit) { // perform offset - ClipperLib::Paths output; - offset2(polygons, &output, delta1, delta2, scale, joinType, miterLimit); + ClipperLib::Paths output = _offset2(polygons, delta1, delta2, scale, 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 double scale, const ClipperLib::JoinType joinType, const double miterLimit) -{ - Slic3r::Polygons pp; - offset2(polygons, &pp, delta1, delta2, scale, joinType, miterLimit); - return pp; -} - -void -offset2(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta1, - const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit) +ExPolygons +offset2_ex(const Polygons &polygons, const float delta1, const float delta2, + const double scale, const ClipperLib::JoinType joinType, const double miterLimit) { // perform offset - ClipperLib::Paths output; - offset2(polygons, &output, delta1, delta2, scale, joinType, miterLimit); + ClipperLib::Paths output = _offset2(polygons, delta1, delta2, scale, 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 double scale, const ClipperLib::JoinType joinType, const double miterLimit) -{ - Slic3r::ExPolygons expp; - offset2(polygons, &expp, delta1, delta2, scale, 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_) { // 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_) { @@ -333,20 +286,22 @@ void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polygons &su // add polygons clipper.AddPaths(input_subject, ClipperLib::ptSubject, true); - clipper.AddPaths(input_clip, ClipperLib::ptClip, true); + clipper.AddPaths(input_clip, ClipperLib::ptClip, true); // perform operation - 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_) { // 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); @@ -360,285 +315,133 @@ void _clipper_do(const ClipperLib::ClipType clipType, const Slic3r::Polylines &s clipper.AddPaths(input_clip, ClipperLib::ptClip, true); // perform operation - 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_) { // perform operation - ClipperLib::Paths output; - _clipper_do(clipType, subject, clip, &output, ClipperLib::pftNonZero, safety_offset_); + ClipperLib::Paths output = _clipper_do(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_); // convert into Polygons - ClipperPaths_to_Slic3rMultiPoints(output, retval); + return ClipperPaths_to_Slic3rMultiPoints(output); } -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, - const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_) +ExPolygons +_clipper_ex(ClipperLib::ClipType clipType, const Polygons &subject, + const Polygons &clip, bool safety_offset_) { // perform operation - ClipperLib::PolyTree polytree; - _clipper_do(clipType, subject, clip, &polytree, ClipperLib::pftNonZero, safety_offset_); + ClipperLib::PolyTree polytree = _clipper_do(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_); // convert into ExPolygons - PolyTreeToExPolygons(polytree, retval); + return PolyTreeToExPolygons(polytree); } -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, - const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_) +Polylines +_clipper_pl(ClipperLib::ClipType clipType, const Polylines &subject, + const Polygons &clip, bool safety_offset_) { // perform operation - ClipperLib::PolyTree polytree; - _clipper_do(clipType, subject, clip, &polytree, ClipperLib::pftNonZero, safety_offset_); + ClipperLib::PolyTree polytree = _clipper_do(clipType, subject, clip, ClipperLib::pftNonZero, safety_offset_); // convert into Polylines ClipperLib::Paths output; ClipperLib::PolyTreeToPaths(polytree, output); - ClipperPaths_to_Slic3rMultiPoints(output, retval); + return ClipperPaths_to_Slic3rMultiPoints(output); } -void _clipper(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(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(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 Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); -template void diff(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* 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 void intersection(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); -template void intersection(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* 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_); - 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; +} + +static 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? */ @@ -660,19 +463,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) { // 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); @@ -684,21 +487,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) { 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; @@ -709,7 +509,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) diff --git a/xs/src/libslic3r/ClipperUtils.hpp b/xs/src/libslic3r/ClipperUtils.hpp index 08697652c6..ae1c969fe0 100644 --- a/xs/src/libslic3r/ClipperUtils.hpp +++ b/xs/src/libslic3r/ClipperUtils.hpp @@ -22,22 +22,19 @@ 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); +T ClipperPaths_to_Slic3rMultiPoints(const ClipperLib::Paths &input); +Slic3r::ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input); void scaleClipperPolygons(ClipperLib::Paths &polygons, const double scale); // offset Polygons -void offset(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta, - double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); -void offset(const Slic3r::Polygons &polygons, Slic3r::Polygons* retval, const float delta, +ClipperLib::Paths _offset(const Slic3r::Polygons &polygons, const float delta, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, @@ -45,19 +42,16 @@ Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, double miterLimit = 3); // offset Polylines -void offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const float delta, +ClipperLib::Paths _offset(const Slic3r::Polylines &polylines, const float delta, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3); -void offset(const Slic3r::Polylines &polylines, Slic3r::Polygons* retval, const float delta, +Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3); -void offset(const Slic3r::Surface &surface, Slic3r::Surfaces* retval, const float delta, +Slic3r::Surfaces offset(const Slic3r::Surface &surface, const float delta, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3); -void offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta, - double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); @@ -65,78 +59,159 @@ Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float d double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); -void offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1, - const float delta2, double scale = 100000, 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, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1, const float delta2, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); -void offset2(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta1, - const float delta2, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter, - double miterLimit = 3); Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1, const float delta2, double scale = 100000, 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(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, - const Slic3r::Polygons &clip, Slic3r::Polylines* retval); -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, - const Slic3r::Polygons &clip, Slic3r::Lines* retval); +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); +// diff +inline Slic3r::Polygons +diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper(ClipperLib::ctDifference, subject, clip, safety_offset_); +} -template -Slic3r::ExPolygons diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_ = false); +inline Slic3r::ExPolygons +diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + 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 Slic3r::ExPolygons +diff_ex(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false) +{ + return _clipper_ex(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::Polygons +diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_ = false) +{ + return _clipper(ClipperLib::ctDifference, to_polygons(subject), to_polygons(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::Polygons &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::Polylines +diff_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper_pl(ClipperLib::ctDifference, subject, clip, safety_offset_); +} -void xor_(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, - 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_); +} -template -void union_(const Slic3r::Polygons &subject, T* retval, bool safety_offset_ = false); +// 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_); +} -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::ExPolygons +intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + return _clipper_ex(ClipperLib::ctIntersection, subject, clip, 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 +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_); +} -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); +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) +{ + return _clipper_pl(ClipperLib::ctIntersection, subject, clip, safety_offset_); +} + +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_); +} + +// union +inline Slic3r::Polygons +union_(const Slic3r::Polygons &subject, bool safety_offset_ = false) +{ + return _clipper(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_); +} + +inline Slic3r::Polygons +union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2, bool safety_offset_ = false) +{ + return _clipper(ClipperLib::ctUnion, subject, subject2, safety_offset_); +} + +inline Slic3r::ExPolygons +union_ex(const Slic3r::Polygons &subject, bool safety_offset_ = false) +{ + return _clipper_ex(ClipperLib::ctUnion, subject, Slic3r::Polygons(), safety_offset_); +} + +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_); +} + +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); static void traverse_pt(ClipperLib::PolyNodes &nodes, Slic3r::Polygons* retval); -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); +/* 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); diff --git a/xs/src/libslic3r/ExPolygon.cpp b/xs/src/libslic3r/ExPolygon.cpp index 3640d39188..c9bb080482 100644 --- a/xs/src/libslic3r/ExPolygon.cpp +++ b/xs/src/libslic3r/ExPolygon.cpp @@ -90,9 +90,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 @@ -152,8 +150,7 @@ ExPolygon::simplify_p(double tolerance) const p.points.pop_back(); pp.push_back(p); } - simplify_polygons(pp, &pp); - return pp; + return simplify_polygons(pp); } ExPolygons @@ -346,8 +343,7 @@ ExPolygon::get_trapezoids2(Polygons* polygons) const poly[3].y = bb.max.y; // intersect with this expolygon - Polygons trapezoids; - intersection(poly, *this, &trapezoids); + Polygons trapezoids = intersection(poly, *this); // append results to return value polygons->insert(polygons->end(), trapezoids.begin(), trapezoids.end()); @@ -384,10 +380,7 @@ 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 = simplify_polygons_ex(*this, true); for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) { // contour @@ -440,8 +433,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 @@ -505,4 +497,15 @@ ExPolygon::dump_perl() const return ret.str(); } +Polygons +to_polygons(const ExPolygons &expolygons) +{ + Slic3r::Polygons pp; + for (ExPolygons::const_iterator ex = expolygons.begin(); ex != expolygons.end(); ++ex) { + Slic3r::Polygons ppp = *ex; + pp.insert(pp.end(), ppp.begin(), ppp.end()); + } + return pp; +} + } diff --git a/xs/src/libslic3r/ExPolygon.hpp b/xs/src/libslic3r/ExPolygon.hpp index 69fe9fb0ee..a9c86bf664 100644 --- a/xs/src/libslic3r/ExPolygon.hpp +++ b/xs/src/libslic3r/ExPolygon.hpp @@ -45,6 +45,8 @@ class ExPolygon std::string dump_perl() const; }; +Polygons to_polygons(const ExPolygons &expolygons); + } // start Boost diff --git a/xs/src/libslic3r/ExtrusionEntity.cpp b/xs/src/libslic3r/ExtrusionEntity.cpp index 5d0e5502af..a844cdd774 100644 --- a/xs/src/libslic3r/ExtrusionEntity.cpp +++ b/xs/src/libslic3r/ExtrusionEntity.cpp @@ -36,8 +36,7 @@ void ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const { // perform clipping - Polylines clipped; - intersection(this->polyline, collection, &clipped); + Polylines clipped = intersection_pl(this->polyline, collection); return this->_inflate_collection(clipped, retval); } @@ -45,8 +44,7 @@ void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const { // perform clipping - Polylines clipped; - diff(this->polyline, collection, &clipped); + Polylines clipped = diff_pl(this->polyline, collection); return this->_inflate_collection(clipped, retval); } @@ -113,9 +111,7 @@ ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCo Polygons ExtrusionPath::grow() const { - Polygons pp; - offset(this->polyline, &pp, +scale_(this->width/2)); - return pp; + return offset(this->polyline, +scale_(this->width/2)); } ExtrusionLoop* diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 41a8671a6b..7a935b3640 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -283,11 +283,8 @@ GCode::change_layer(const Layer &layer) this->first_layer = (layer.id() == 0); // avoid computing islands and overhangs if they're not needed - if (this->config.avoid_crossing_perimeters) { - ExPolygons islands; - union_(layer.slices, &islands, true); - this->avoid_crossing_perimeters.init_layer_mp(islands); - } + if (this->config.avoid_crossing_perimeters) + this->avoid_crossing_perimeters.init_layer_mp(union_ex(layer.slices, true)); std::string gcode; if (this->layer_count > 0) { diff --git a/xs/src/libslic3r/Geometry.cpp b/xs/src/libslic3r/Geometry.cpp index 6d864f6313..fcf39f7057 100644 --- a/xs/src/libslic3r/Geometry.cpp +++ b/xs/src/libslic3r/Geometry.cpp @@ -149,20 +149,6 @@ deg2rad(double angle) return PI * angle / 180.0; } -void -simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval) -{ - Polygons pp; - for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++it) { - Polygon p = *it; - p.points.push_back(p.points.front()); - p.points = MultiPoint::_douglas_peucker(p.points, tolerance); - p.points.pop_back(); - pp.push_back(p); - } - Slic3r::simplify_polygons(pp, retval); -} - double linint(double value, double oldmin, double oldmax, double newmin, double newmax) { diff --git a/xs/src/libslic3r/Geometry.hpp b/xs/src/libslic3r/Geometry.hpp index 14bc3f0ca8..724279f4b7 100644 --- a/xs/src/libslic3r/Geometry.hpp +++ b/xs/src/libslic3r/Geometry.hpp @@ -23,7 +23,6 @@ template bool contains(const std::vector &vector, const Point &point double rad2deg(double angle); double rad2deg_dir(double angle); double deg2rad(double angle); -void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval); class ArrangeItem { public: diff --git a/xs/src/libslic3r/Layer.cpp b/xs/src/libslic3r/Layer.cpp index dc931923c3..4d12a76f70 100644 --- a/xs/src/libslic3r/Layer.cpp +++ b/xs/src/libslic3r/Layer.cpp @@ -110,7 +110,7 @@ Layer::make_slices() Polygons region_slices_p = (*layerm)->slices; slices_p.insert(slices_p.end(), region_slices_p.begin(), region_slices_p.end()); } - union_(slices_p, &slices); + slices = union_ex(slices_p); } this->slices.expolygons.clear(); @@ -229,8 +229,8 @@ Layer::make_perimeters() if (!fill_surfaces.surfaces.empty()) { for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) { ExPolygons expp = intersection_ex( - fill_surfaces, - (*l)->slices + (Polygons) fill_surfaces, + (Polygons) (*l)->slices ); (*l)->fill_surfaces.surfaces.clear(); diff --git a/xs/src/libslic3r/LayerRegion.cpp b/xs/src/libslic3r/LayerRegion.cpp index f459c58788..64e5a3dec1 100644 --- a/xs/src/libslic3r/LayerRegion.cpp +++ b/xs/src/libslic3r/LayerRegion.cpp @@ -45,9 +45,8 @@ LayerRegion::flow(FlowRole role, bool bridge, double width) const void LayerRegion::merge_slices() { - ExPolygons expp; // without safety offset, artifacts are generated (GH #2494) - union_(this->slices, &expp, true); + ExPolygons expp = union_ex((Polygons)this->slices, true); this->slices.surfaces.clear(); this->slices.surfaces.reserve(expp.size()); diff --git a/xs/src/libslic3r/MotionPlanner.cpp b/xs/src/libslic3r/MotionPlanner.cpp index a1df679cfd..6c6d7336dc 100644 --- a/xs/src/libslic3r/MotionPlanner.cpp +++ b/xs/src/libslic3r/MotionPlanner.cpp @@ -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(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(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(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 f9e6a8c6e6..842801d4e4 100644 --- a/xs/src/libslic3r/PerimeterGenerator.cpp +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -343,8 +343,7 @@ PerimeterGenerator::_traverse_loops(const PerimeterGeneratorLoops &loops, && !(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); + Polylines polylines = intersection_pl(loop->polygon, this->_lower_slices_p); for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) { ExtrusionPath path(role); @@ -360,8 +359,7 @@ PerimeterGenerator::_traverse_loops(const PerimeterGeneratorLoops &loops, // 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); + Polylines polylines = diff_pl(loop->polygon, this->_lower_slices_p); for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) { ExtrusionPath path(erOverhangPerimeter); diff --git a/xs/src/libslic3r/Polygon.cpp b/xs/src/libslic3r/Polygon.cpp index 102838809b..0fbfda3704 100644 --- a/xs/src/libslic3r/Polygon.cpp +++ b/xs/src/libslic3r/Polygon.cpp @@ -86,17 +86,13 @@ Polygon::equally_spaced_points(double distance) const double Polygon::area() const { - ClipperLib::Path p; - Slic3rMultiPoint_to_ClipperPath(*this, &p); - return ClipperLib::Area(p); + return ClipperLib::Area(Slic3rMultiPoint_to_ClipperPath(*this)); } 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 @@ -157,10 +153,7 @@ Polygon::simplify(double tolerance) const Polygon p(MultiPoint::_douglas_peucker(points, tolerance)); p.points.pop_back(); - Polygons pp; - pp.push_back(p); - simplify_polygons(pp, &pp); - return pp; + return simplify_polygons(p); } void diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 8d114f6e2f..393677343c 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -607,20 +607,16 @@ 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, 1, jtRound, scale_(0.1)); - convex_hull = grown_hull.front(); - } + convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, 1, 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()) throw PrintValidationException("Some objects are too close; your extruder will collide with them."); - union_(a, p, &a); + a = union_(a, p); } } } diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 23d9e74e1d..13ba53da15 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -429,7 +429,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); // build the new collection of fill_surfaces { diff --git a/xs/src/libslic3r/Surface.cpp b/xs/src/libslic3r/Surface.cpp index 4d2234e4db..ba32ecd10c 100644 --- a/xs/src/libslic3r/Surface.cpp +++ b/xs/src/libslic3r/Surface.cpp @@ -54,4 +54,15 @@ Surface::is_bridge() const || this->surface_type == stInternalBridge; } +Polygons +to_polygons(const Surfaces &surfaces) +{ + Slic3r::Polygons pp; + for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) { + Slic3r::Polygons ppp = *s; + pp.insert(pp.end(), ppp.begin(), ppp.end()); + } + return pp; +} + } diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp index 21395bdc64..d445db208e 100644 --- a/xs/src/libslic3r/Surface.hpp +++ b/xs/src/libslic3r/Surface.hpp @@ -34,6 +34,8 @@ class Surface typedef std::vector Surfaces; typedef std::vector SurfacesPtr; +Polygons to_polygons(const Surfaces &surfaces); + } #endif diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index 4286d5aa30..437bea44c7 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -390,10 +390,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 @@ -848,14 +845,13 @@ TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) if (area[*loop_idx] > +EPSILON) { p_slices.push_back(*loop); } else if (area[*loop_idx] < -EPSILON) { - diff(p_slices, *loop, &p_slices); + 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_DEBUG size_t holes_count = 0; diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index d8621ac915..5bba8fcb6d 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -531,8 +531,7 @@ SV* polynode2perl(const ClipperLib::PolyNode& node) { HV* hv = newHV(); - Slic3r::Polygon p; - ClipperPath_to_Slic3rMultiPoint(node.Contour, &p); + 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/xsp/Clipper.xsp b/xs/xsp/Clipper.xsp index 7a33ea0c4d..7bbbdb8d64 100644 --- a/xs/xsp/Clipper.xsp +++ b/xs/xsp/Clipper.xsp @@ -8,6 +8,40 @@ %package{Slic3r::Geometry::Clipper}; +Polygons offset(Polygons polygons, float delta, double scale = CLIPPER_OFFSET_SCALE, + ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); + +ExPolygons offset_ex(Polygons polygons, float delta, double scale = CLIPPER_OFFSET_SCALE, + ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); + +Polygons offset2(Polygons polygons, float delta1, float delta2, double scale = CLIPPER_OFFSET_SCALE, + ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); + +ExPolygons offset2_ex(Polygons polygons, float delta1, float delta2, double scale = CLIPPER_OFFSET_SCALE, + ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); + +Polygons diff(Polygons subject, Polygons clip, bool safety_offset = false); + +ExPolygons diff_ex(Polygons subject, Polygons clip, bool safety_offset = false); + +Polylines diff_pl(Polylines subject, Polygons clip); + +Polygons intersection(Polygons subject, Polygons clip, bool safety_offset = false); + +ExPolygons intersection_ex(Polygons subject, Polygons clip, bool safety_offset = false); + +Polylines intersection_pl(Polylines subject, Polygons clip); + +%name{intersection_ppl} Polylines intersection_pl(Polygons subject, Polygons clip); + +%name{union} Polygons union_(Polygons subject, bool safety_offset = false); + +ExPolygons union_ex(Polygons subject, bool safety_offset = false); + +Polygons union_pt_chained(Polygons subject, bool safety_offset = false); + +Polygons simplify_polygons(Polygons subject); + %{ IV @@ -21,188 +55,15 @@ _constant() RETVAL = ix; OUTPUT: RETVAL -Polygons -offset(polygons, delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMiter, miterLimit = 3) - Polygons polygons - const float delta - double scale - ClipperLib::JoinType joinType - double miterLimit - CODE: - offset(polygons, &RETVAL, delta, scale, joinType, miterLimit); - OUTPUT: - RETVAL - -ExPolygons -offset_ex(polygons, delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMiter, miterLimit = 3) - Polygons polygons - const float delta - double scale - ClipperLib::JoinType joinType - double miterLimit - CODE: - offset(polygons, &RETVAL, delta, scale, joinType, miterLimit); - OUTPUT: - RETVAL - -Polygons -offset2(polygons, delta1, delta2, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMiter, miterLimit = 3) - Polygons polygons - const float delta1 - const float delta2 - double scale - ClipperLib::JoinType joinType - double miterLimit - CODE: - offset2(polygons, &RETVAL, delta1, delta2, scale, joinType, miterLimit); - OUTPUT: - RETVAL - -ExPolygons -offset2_ex(polygons, delta1, delta2, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMiter, miterLimit = 3) - Polygons polygons - const float delta1 - const float delta2 - double scale - ClipperLib::JoinType joinType - double miterLimit - CODE: - offset2(polygons, &RETVAL, delta1, delta2, scale, joinType, miterLimit); - OUTPUT: - RETVAL - -Polygons -diff(subject, clip, safety_offset = false) - Polygons subject - Polygons clip - bool safety_offset - CODE: - diff(subject, clip, &RETVAL, safety_offset); - OUTPUT: - RETVAL - -ExPolygons -diff_ex(subject, clip, safety_offset = false) - Polygons subject - Polygons clip - bool safety_offset - CODE: - diff(subject, clip, &RETVAL, safety_offset); - OUTPUT: - RETVAL - -Polylines -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); - OUTPUT: - RETVAL - -Polygons -intersection(subject, clip, safety_offset = false) - Polygons subject - Polygons clip - bool safety_offset - CODE: - intersection(subject, clip, &RETVAL, safety_offset); - OUTPUT: - RETVAL - -ExPolygons -intersection_ex(subject, clip, safety_offset = false) - Polygons subject - Polygons clip - bool safety_offset - CODE: - intersection(subject, clip, &RETVAL, safety_offset); - OUTPUT: - RETVAL - -Polylines -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); - OUTPUT: - RETVAL - -Polygons -union(subject, safety_offset = false) - Polygons subject - bool safety_offset - CODE: - union_(subject, &RETVAL, safety_offset); - OUTPUT: - RETVAL - -ExPolygons -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); - + ClipperLib::PolyTree polytree = union_pt(subject, safety_offset); RETVAL = polynode_children_2_perl(polytree); OUTPUT: RETVAL -Polygons -union_pt_chained(subject, safety_offset = false) - Polygons subject - bool safety_offset - CODE: - union_pt_chained(subject, &RETVAL, safety_offset); - OUTPUT: - RETVAL - -Polygons -simplify_polygons(subject) - Polygons subject - CODE: - simplify_polygons(subject, &RETVAL); - OUTPUT: - RETVAL - %} diff --git a/xs/xsp/Geometry.xsp b/xs/xsp/Geometry.xsp index 718ce5bdfc..de911ccb09 100644 --- a/xs/xsp/Geometry.xsp +++ b/xs/xsp/Geometry.xsp @@ -81,15 +81,6 @@ deg2rad(angle) OUTPUT: RETVAL -Polygons -simplify_polygons(polygons, tolerance) - Polygons polygons - double tolerance - CODE: - Slic3r::Geometry::simplify_polygons(polygons, tolerance, &RETVAL); - OUTPUT: - RETVAL - IV _constant() diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp index 31bd4045ea..41cf4f359b 100644 --- a/xs/xsp/Polyline.xsp +++ b/xs/xsp/Polyline.xsp @@ -86,7 +86,7 @@ Polyline::grow(delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtSqu ClipperLib::JoinType joinType double miterLimit CODE: - offset(*THIS, &RETVAL, delta, scale, joinType, miterLimit); + RETVAL = offset(*THIS, delta, scale, joinType, miterLimit); OUTPUT: RETVAL diff --git a/xs/xsp/Surface.xsp b/xs/xsp/Surface.xsp index ebacd17957..021a8b7e45 100644 --- a/xs/xsp/Surface.xsp +++ b/xs/xsp/Surface.xsp @@ -89,7 +89,7 @@ Surface::offset(delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtMi ClipperLib::JoinType joinType double miterLimit CODE: - offset(*THIS, &RETVAL, delta, scale, joinType, miterLimit); + RETVAL = offset(*THIS, delta, scale, joinType, miterLimit); OUTPUT: RETVAL diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 37d7a9620c..89975c949a 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -198,7 +198,8 @@ %typemap{LayerPtrs*}; %typemap{SupportLayerPtrs*}; - +%typemap{ClipperLib::JoinType}{simple}; +%typemap{ClipperLib::PolyFillType}{simple}; %typemap{Axis}{parsed}{ %cpp_type{Axis}; %precall_code{%