From 5a8173157727495a3ef849a338c7b26a5e618f35 Mon Sep 17 00:00:00 2001 From: bubnikv <bubnikv@gmail.com> Date: Mon, 7 Nov 2016 22:49:11 +0100 Subject: [PATCH] Implemented utility functions to operate over lines, polylines, polygons, surfaces. --- xs/src/libslic3r/BoundingBox.hpp | 2 + xs/src/libslic3r/ClipperUtils.cpp | 107 +++++++++++++ xs/src/libslic3r/ClipperUtils.hpp | 10 ++ xs/src/libslic3r/ExPolygon.cpp | 32 ++-- xs/src/libslic3r/ExPolygon.hpp | 209 +++++++++++++++++++++---- xs/src/libslic3r/MultiPoint.cpp | 41 ++++- xs/src/libslic3r/MultiPoint.hpp | 2 + xs/src/libslic3r/Polygon.cpp | 31 ++-- xs/src/libslic3r/Polygon.hpp | 65 ++++++++ xs/src/libslic3r/Polyline.hpp | 27 ++++ xs/src/libslic3r/Surface.hpp | 21 +++ xs/src/libslic3r/SurfaceCollection.cpp | 11 +- xs/src/libslic3r/libslic3r.h | 3 + 13 files changed, 495 insertions(+), 66 deletions(-) diff --git a/xs/src/libslic3r/BoundingBox.hpp b/xs/src/libslic3r/BoundingBox.hpp index ac52129e1..5f676151c 100644 --- a/xs/src/libslic3r/BoundingBox.hpp +++ b/xs/src/libslic3r/BoundingBox.hpp @@ -70,6 +70,8 @@ class BoundingBox : public BoundingBoxBase<Point> BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {}; BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {}; BoundingBox(const Lines &lines); + + friend BoundingBox get_extents_rotated(const Points &points, double angle); }; /* diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp index f68610849..04357b15a 100644 --- a/xs/src/libslic3r/ClipperUtils.cpp +++ b/xs/src/libslic3r/ClipperUtils.cpp @@ -314,6 +314,113 @@ Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, return retval; } +Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, + double scale, ClipperLib::JoinType joinType, double miterLimit) +{ + // perform offset + ClipperLib::Paths output; + offset(expolygon, &output, delta, scale, joinType, miterLimit); + + // convert into ExPolygons + Slic3r::ExPolygons retval; + ClipperPaths_to_Slic3rExPolygons(output, &retval); + return retval; +} + +// 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, + double scale, ClipperLib::JoinType joinType, double miterLimit) +{ +// printf("new ExPolygon offset\n"); + const float delta_scaled = float(delta * scale); + ClipperLib::Paths contours; + ClipperLib::Paths holes; + contours.reserve(expolygons.size()); + { + size_t n_holes = 0; + for (size_t i = 0; i < expolygons.size(); ++ i) + n_holes += expolygons[i].holes.size(); + holes.reserve(n_holes); + } + + 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); + scaleClipperPolygon(input, scale); + ClipperLib::ClipperOffset co; + if (joinType == jtRound) + co.ArcTolerance = miterLimit; + else + co.MiterLimit = miterLimit; + co.AddPath(input, joinType, ClipperLib::etClosedPolygon); + ClipperLib::Paths out; + co.Execute(out, delta_scaled); + contours.insert(contours.end(), out.begin(), out.end()); + } + + // 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); + scaleClipperPolygon(input, scale); + ClipperLib::ClipperOffset co; + if (joinType == jtRound) + co.ArcTolerance = miterLimit; + else + co.MiterLimit = miterLimit; + co.AddPath(input, joinType, ClipperLib::etClosedPolygon); + ClipperLib::Paths out; + co.Execute(out, - delta_scaled); + holes.insert(holes.end(), out.begin(), out.end()); + } + } + } + + // 3) Subtract holes from the contours. + ClipperLib::Paths output; + { + ClipperLib::Clipper clipper; + clipper.Clear(); + clipper.AddPaths(contours, ClipperLib::ptSubject, true); + clipper.AddPaths(holes, ClipperLib::ptClip, true); + clipper.Execute(ClipperLib::ctDifference, *retval, ClipperLib::pftNonZero, ClipperLib::pftNonZero); + } + + // 4) Unscale the output. + scaleClipperPolygons(*retval, 1/scale); +} + +Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, + double scale, ClipperLib::JoinType joinType, double miterLimit) +{ + // perform offset + ClipperLib::Paths output; + offset(expolygons, &output, delta, scale, 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, + double scale, ClipperLib::JoinType joinType, double miterLimit) +{ + // perform offset + ClipperLib::Paths output; + offset(expolygons, &output, delta, scale, 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, double scale, ClipperLib::JoinType joinType, double miterLimit) diff --git a/xs/src/libslic3r/ClipperUtils.hpp b/xs/src/libslic3r/ClipperUtils.hpp index 00b7a56a7..2bb58bdf6 100644 --- a/xs/src/libslic3r/ClipperUtils.hpp +++ b/xs/src/libslic3r/ClipperUtils.hpp @@ -55,9 +55,19 @@ Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, void offset(const Slic3r::ExPolygon &expolygon, ClipperLib::Paths* retval, const float delta, double scale = CLIPPER_OFFSET_SCALE, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); +void offset(const Slic3r::ExPolygons &expolygons, ClipperLib::Paths* retval, const float delta, + double scale = CLIPPER_OFFSET_SCALE, ClipperLib::JoinType joinType = ClipperLib::jtMiter, + double miterLimit = 3); Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, double scale = CLIPPER_OFFSET_SCALE, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3); +Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float delta, + double scale = CLIPPER_OFFSET_SCALE, 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); // offset Polylines void offset(const Slic3r::Polylines &polylines, ClipperLib::Paths* retval, const float delta, diff --git a/xs/src/libslic3r/ExPolygon.cpp b/xs/src/libslic3r/ExPolygon.cpp index 71f90179a..f37e2e701 100644 --- a/xs/src/libslic3r/ExPolygon.cpp +++ b/xs/src/libslic3r/ExPolygon.cpp @@ -26,24 +26,12 @@ ExPolygon::operator Points() const ExPolygon::operator Polygons() const { - Polygons polygons; - polygons.reserve(this->holes.size() + 1); - polygons.push_back(this->contour); - for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { - polygons.push_back(*it); - } - return polygons; + return to_polygons(*this); } ExPolygon::operator Polylines() const { - Polylines polylines; - polylines.reserve(this->holes.size() + 1); - polylines.push_back((Polyline)this->contour); - for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { - polylines.push_back((Polyline)*it); - } - return polylines; + return to_polylines(*this); } void @@ -583,6 +571,22 @@ BoundingBox get_extents(const ExPolygons &expolygons) return bbox; } +BoundingBox get_extents_rotated(const ExPolygon &expolygon, double angle) +{ + return get_extents_rotated(expolygon.contour, angle); +} + +BoundingBox get_extents_rotated(const ExPolygons &expolygons, double angle) +{ + BoundingBox bbox; + if (! expolygons.empty()) { + bbox = get_extents_rotated(expolygons.front().contour, angle); + for (size_t i = 1; i < expolygons.size(); ++ i) + bbox.merge(get_extents_rotated(expolygons[i].contour, angle)); + } + return bbox; +} + bool remove_sticks(ExPolygon &poly) { return remove_sticks(poly.contour) || remove_sticks(poly.holes); diff --git a/xs/src/libslic3r/ExPolygon.hpp b/xs/src/libslic3r/ExPolygon.hpp index f3a6a99eb..c1204a953 100644 --- a/xs/src/libslic3r/ExPolygon.hpp +++ b/xs/src/libslic3r/ExPolygon.hpp @@ -25,6 +25,7 @@ class ExPolygon void rotate(double angle); void rotate(double angle, const Point ¢er); double area() const; + bool empty() const { return contour.points.empty(); } bool is_valid() const; // Contains the line / polyline / polylines etc COMPLETELY. @@ -57,32 +58,6 @@ class ExPolygon std::string dump_perl() const; }; -inline Polygons to_polygons(const ExPolygons &src) -{ - Polygons polygons; - for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++it) { - polygons.push_back(it->contour); - for (Polygons::const_iterator ith = it->holes.begin(); ith != it->holes.end(); ++ith) { - polygons.push_back(*ith); - } - } - return polygons; -} - -#if SLIC3R_CPPVER >= 11 -inline Polygons to_polygons(ExPolygons &&src) -{ - Polygons polygons; - for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++it) { - polygons.push_back(std::move(it->contour)); - for (Polygons::const_iterator ith = it->holes.begin(); ith != it->holes.end(); ++ith) { - polygons.push_back(std::move(*ith)); - } - } - return polygons; -} -#endif - // Count a nuber of polygons stored inside the vector of expolygons. // Useful for allocating space for polygons when converting expolygons to polygons. inline size_t number_polygons(const ExPolygons &expolys) @@ -93,7 +68,164 @@ inline size_t number_polygons(const ExPolygons &expolys) return n_polygons; } -// Append a vector of ExPolygons at the end of another vector of polygons. +inline Lines to_lines(const ExPolygon &src) +{ + size_t n_lines = src.contour.points.size(); + for (size_t i = 0; i < src.holes.size(); ++ i) + n_lines += src.holes[i].points.size(); + Lines lines; + lines.reserve(n_lines); + for (size_t i = 0; i <= src.holes.size(); ++ i) { + const Polygon &poly = (i == 0) ? src.contour : src.holes[i - 1]; + for (Points::const_iterator it = poly.points.begin(); it != poly.points.end()-1; ++it) + lines.push_back(Line(*it, *(it + 1))); + lines.push_back(Line(poly.points.back(), poly.points.front())); + } + return lines; +} + +inline Lines to_lines(const ExPolygons &src) +{ + size_t n_lines = 0; + for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) { + n_lines += it_expoly->contour.points.size(); + for (size_t i = 0; i < it_expoly->holes.size(); ++ i) + n_lines += it_expoly->holes[i].points.size(); + } + Lines lines; + lines.reserve(n_lines); + for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) { + for (size_t i = 0; i <= it_expoly->holes.size(); ++ i) { + const Points &points = ((i == 0) ? it_expoly->contour : it_expoly->holes[i - 1]).points; + for (Points::const_iterator it = points.begin(); it != points.end()-1; ++it) + lines.push_back(Line(*it, *(it + 1))); + lines.push_back(Line(points.back(), points.front())); + } + } + return lines; +} + +inline Polylines to_polylines(const ExPolygon &src) +{ + Polylines polylines; + polylines.assign(src.holes.size() + 1, Polyline()); + size_t idx = 0; + Polyline &pl = polylines[idx ++]; + pl.points = src.contour.points; + pl.points.push_back(pl.points.front()); + for (Polygons::const_iterator ith = src.holes.begin(); ith != src.holes.end(); ++ith) { + Polyline &pl = polylines[idx ++]; + pl.points = ith->points; + pl.points.push_back(ith->points.front()); + } + assert(idx == polylines.size()); + return polylines; +} + +inline Polylines to_polylines(const ExPolygons &src) +{ + Polylines polylines; + polylines.assign(number_polygons(src), Polyline()); + size_t idx = 0; + for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++it) { + Polyline &pl = polylines[idx ++]; + pl.points = it->contour.points; + pl.points.push_back(pl.points.front()); + for (Polygons::const_iterator ith = it->holes.begin(); ith != it->holes.end(); ++ith) { + Polyline &pl = polylines[idx ++]; + pl.points = ith->points; + pl.points.push_back(ith->points.front()); + } + } + assert(idx == polylines.size()); + return polylines; +} + +#if SLIC3R_CPPVER >= 11 +inline Polylines to_polylines(ExPolygon &&src) +{ + Polylines polylines; + polylines.assign(src.holes.size() + 1, Polyline()); + size_t idx = 0; + Polyline &pl = polylines[idx ++]; + pl.points = std::move(src.contour.points); + pl.points.push_back(pl.points.front()); + for (Polygons::const_iterator ith = src.holes.begin(); ith != src.holes.end(); ++ith) { + Polyline &pl = polylines[idx ++]; + pl.points = std::move(ith->points); + pl.points.push_back(ith->points.front()); + } + assert(idx == polylines.size()); + return polylines; +} +inline Polylines to_polylines(ExPolygons &&src) +{ + Polylines polylines; + polylines.assign(number_polygons(src), Polyline()); + size_t idx = 0; + for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++it) { + Polyline &pl = polylines[idx ++]; + pl.points = std::move(it->contour.points); + pl.points.push_back(pl.points.front()); + for (Polygons::const_iterator ith = it->holes.begin(); ith != it->holes.end(); ++ith) { + Polyline &pl = polylines[idx ++]; + pl.points = std::move(ith->points); + pl.points.push_back(ith->points.front()); + } + } + assert(idx == polylines.size()); + return polylines; +} +#endif + +inline Polygons to_polygons(const ExPolygon &src) +{ + Polygons polygons; + polygons.reserve(src.holes.size() + 1); + polygons.push_back(src.contour); + polygons.insert(polygons.end(), src.holes.begin(), src.holes.end()); + return polygons; +} + +inline Polygons to_polygons(const ExPolygons &src) +{ + Polygons polygons; + polygons.reserve(number_polygons(src)); + for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++it) { + polygons.push_back(it->contour); + polygons.insert(polygons.end(), it->holes.begin(), it->holes.end()); + } + return polygons; +} + +#if SLIC3R_CPPVER >= 11 +inline Polygons to_polygons(ExPolygon &&src) +{ + Polygons polygons; + polygons.reserve(src.holes.size() + 1); + polygons.push_back(std::move(src.contour)); + std::move(std::begin(src.holes), std::end(src.holes), std::back_inserter(polygons)); + return polygons; +} +inline Polygons to_polygons(ExPolygons &&src) +{ + Polygons polygons; + polygons.reserve(number_polygons(src)); + for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++it) { + polygons.push_back(std::move(it->contour)); + std::move(std::begin(it->holes), std::end(it->holes), std::back_inserter(polygons)); + } + return polygons; +} +#endif + +inline void polygons_append(Polygons &dst, const ExPolygon &src) +{ + dst.reserve(dst.size() + src.holes.size() + 1); + dst.push_back(src.contour); + dst.insert(dst.end(), src.holes.begin(), src.holes.end()); +} + inline void polygons_append(Polygons &dst, const ExPolygons &src) { dst.reserve(dst.size() + number_polygons(src)); @@ -104,6 +236,13 @@ inline void polygons_append(Polygons &dst, const ExPolygons &src) } #if SLIC3R_CPPVER >= 11 +inline void polygons_append(Polygons &dst, ExPolygon &&src) +{ + dst.reserve(dst.size() + src.holes.size() + 1); + dst.push_back(std::move(src.contour)); + std::move(std::begin(src.holes), std::end(src.holes), std::back_inserter(dst)); +} + inline void polygons_append(Polygons &dst, ExPolygons &&src) { dst.reserve(dst.size() + number_polygons(src)); @@ -114,8 +253,24 @@ inline void polygons_append(Polygons &dst, ExPolygons &&src) } #endif +inline void expolygons_rotate(ExPolygons &expolys, double angle) +{ + for (ExPolygons::iterator p = expolys.begin(); p != expolys.end(); ++p) + p->rotate(angle); +} + +inline bool expolygons_contain(ExPolygons &expolys, const Point &pt) +{ + for (ExPolygons::iterator p = expolys.begin(); p != expolys.end(); ++p) + if (p->contains(pt)) + return true; + return false; +} + extern BoundingBox get_extents(const ExPolygon &expolygon); extern BoundingBox get_extents(const ExPolygons &expolygons); +extern BoundingBox get_extents_rotated(const ExPolygon &poly, double angle); +extern BoundingBox get_extents_rotated(const ExPolygons &polygons, double angle); extern bool remove_sticks(ExPolygon &poly); diff --git a/xs/src/libslic3r/MultiPoint.cpp b/xs/src/libslic3r/MultiPoint.cpp index b771833ed..639eb6bb7 100644 --- a/xs/src/libslic3r/MultiPoint.cpp +++ b/xs/src/libslic3r/MultiPoint.cpp @@ -36,10 +36,10 @@ MultiPoint::rotate(double angle) double s = sin(angle); double c = cos(angle); for (Points::iterator it = points.begin(); it != points.end(); ++it) { - double cur_x = (double)it->x; - double cur_y = (double)it->y; - it->x = (coord_t)round(c * cur_x - s * cur_y); - it->y = (coord_t)round(c * cur_y + s * cur_x); + double cur_x = (double)it->x; + double cur_y = (double)it->y; + it->x = (coord_t)round(c * cur_x - s * cur_y); + it->y = (coord_t)round(c * cur_y + s * cur_x); } } @@ -214,7 +214,38 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance) BoundingBox get_extents(const MultiPoint &mp) { - return mp.bounding_box(); + return BoundingBox(mp.points); +} + +BoundingBox get_extents_rotated(const Points &points, double angle) +{ + BoundingBox bbox; + if (! points.empty()) { + double s = sin(angle); + double c = cos(angle); + Points::const_iterator it = points.begin(); + double cur_x = (double)it->x; + double cur_y = (double)it->y; + bbox.min.x = bbox.max.x = (coord_t)round(c * cur_x - s * cur_y); + bbox.min.y = bbox.max.y = (coord_t)round(c * cur_y + s * cur_x); + for (++it; it != points.end(); ++it) { + double cur_x = (double)it->x; + double cur_y = (double)it->y; + coord_t x = (coord_t)round(c * cur_x - s * cur_y); + coord_t y = (coord_t)round(c * cur_y + s * cur_x); + bbox.min.x = std::min(x, bbox.min.x); + bbox.min.y = std::min(y, bbox.min.y); + bbox.max.x = std::max(x, bbox.max.x); + bbox.max.y = std::max(y, bbox.max.y); + } + bbox.defined = true; + } + return bbox; +} + +BoundingBox get_extents_rotated(const MultiPoint &mp, double angle) +{ + return get_extents_rotated(mp.points, angle); } } diff --git a/xs/src/libslic3r/MultiPoint.hpp b/xs/src/libslic3r/MultiPoint.hpp index 66b36d720..60e24e17e 100644 --- a/xs/src/libslic3r/MultiPoint.hpp +++ b/xs/src/libslic3r/MultiPoint.hpp @@ -48,6 +48,8 @@ class MultiPoint }; extern BoundingBox get_extents(const MultiPoint &mp); +extern BoundingBox get_extents_rotated(const std::vector<Point> &points, double angle); +extern BoundingBox get_extents_rotated(const MultiPoint &mp, double angle); } // namespace Slic3r diff --git a/xs/src/libslic3r/Polygon.cpp b/xs/src/libslic3r/Polygon.cpp index 5fe0537fb..9338f2ec7 100644 --- a/xs/src/libslic3r/Polygon.cpp +++ b/xs/src/libslic3r/Polygon.cpp @@ -35,16 +35,9 @@ Polygon::last_point() const return this->points.front(); // last point == first point for polygons } -Lines -Polygon::lines() const +Lines Polygon::lines() const { - Lines lines; - lines.reserve(this->points.size()); - for (Points::const_iterator it = this->points.begin(); it != this->points.end()-1; ++it) { - lines.push_back(Line(*it, *(it + 1))); - } - lines.push_back(Line(this->points.back(), this->points.front())); - return lines; + return to_lines(*this); } Polyline @@ -312,9 +305,25 @@ BoundingBox get_extents(const Polygons &polygons) { BoundingBox bb; if (! polygons.empty()) { - bb = polygons.front().bounding_box(); + bb = get_extents(polygons.front()); for (size_t i = 1; i < polygons.size(); ++ i) - bb.merge(polygons[i]); + bb.merge(get_extents(polygons[i])); + } + return bb; +} + +BoundingBox get_extents_rotated(const Polygon &poly, double angle) +{ + return get_extents_rotated(poly.points, angle); +} + +BoundingBox get_extents_rotated(const Polygons &polygons, double angle) +{ + BoundingBox bb; + if (! polygons.empty()) { + bb = get_extents_rotated(polygons.front().points, angle); + for (size_t i = 1; i < polygons.size(); ++ i) + bb.merge(get_extents_rotated(polygons[i].points, angle)); } return bb; } diff --git a/xs/src/libslic3r/Polygon.hpp b/xs/src/libslic3r/Polygon.hpp index 21f46117d..3ccd7154b 100644 --- a/xs/src/libslic3r/Polygon.hpp +++ b/xs/src/libslic3r/Polygon.hpp @@ -50,6 +50,8 @@ class Polygon : public MultiPoint { extern BoundingBox get_extents(const Polygon &poly); extern BoundingBox get_extents(const Polygons &polygons); +extern BoundingBox get_extents_rotated(const Polygon &poly, double angle); +extern BoundingBox get_extents_rotated(const Polygons &polygons, double angle); // Remove sticks (tentacles with zero area) from the polygon. extern bool remove_sticks(Polygon &poly); @@ -70,8 +72,71 @@ inline void polygons_append(Polygons &dst, Polygons &&src) std::move(std::begin(src), std::end(src), std::back_inserter(dst)); } #endif + +inline void polygons_rotate(Polygons &polys, double angle) +{ + for (Polygons::iterator p = polys.begin(); p != polys.end(); ++p) + p->rotate(angle); } +inline Lines to_lines(const Polygon &poly) +{ + Lines lines; + lines.reserve(poly.points.size()); + for (Points::const_iterator it = poly.points.begin(); it != poly.points.end()-1; ++it) + lines.push_back(Line(*it, *(it + 1))); + lines.push_back(Line(poly.points.back(), poly.points.front())); + return lines; +} + +inline Lines to_lines(const Polygons &polys) +{ + size_t n_lines = 0; + for (size_t i = 0; i < polys.size(); ++ i) + n_lines += polys[i].points.size(); + Lines lines; + lines.reserve(n_lines); + for (size_t i = 0; i < polys.size(); ++ i) { + const Polygon &poly = polys[i]; + for (Points::const_iterator it = poly.points.begin(); it != poly.points.end()-1; ++it) + lines.push_back(Line(*it, *(it + 1))); + lines.push_back(Line(poly.points.back(), poly.points.front())); + } + return lines; +} + +inline Polylines to_polylines(const Polygons &polys) +{ + Polylines polylines; + polylines.assign(polys.size(), Polyline()); + size_t idx = 0; + for (Polygons::const_iterator it = polys.begin(); it != polys.end(); ++ it) { + Polyline &pl = polylines[idx ++]; + pl.points = it->points; + pl.points.push_back(it->points.front()); + } + assert(idx == polylines.size()); + return polylines; +} + +#if SLIC3R_CPPVER >= 11 +inline Polylines to_polylines(Polygons &&polys) +{ + Polylines polylines; + polylines.assign(polys.size(), Polyline()); + size_t idx = 0; + for (Polygons::const_iterator it = polys.begin(); it != polys.end(); ++ it) { + Polyline &pl = polylines[idx ++]; + pl.points = std::move(it->points); + pl.points.push_back(it->points.front()); + } + assert(idx == polylines.size()); + return polylines; +} +#endif + +} // Slic3r + // start Boost #include <boost/polygon/polygon.hpp> namespace boost { namespace polygon { diff --git a/xs/src/libslic3r/Polyline.hpp b/xs/src/libslic3r/Polyline.hpp index dd2818199..b8c04a12a 100644 --- a/xs/src/libslic3r/Polyline.hpp +++ b/xs/src/libslic3r/Polyline.hpp @@ -36,6 +36,33 @@ class Polyline : public MultiPoint { extern BoundingBox get_extents(const Polyline &polyline); extern BoundingBox get_extents(const Polylines &polylines); +inline Lines to_lines(const Polyline &poly) +{ + Lines lines; + if (poly.points.size() >= 2) { + lines.reserve(poly.points.size() - 1); + for (Points::const_iterator it = poly.points.begin(); it != poly.points.end()-1; ++it) + lines.push_back(Line(*it, *(it + 1))); + } + return lines; +} + +inline Lines to_lines(const Polylines &polys) +{ + size_t n_lines = 0; + for (size_t i = 0; i < polys.size(); ++ i) + if (polys[i].points.size() > 1) + n_lines += polys[i].points.size() - 1; + Lines lines; + lines.reserve(n_lines); + for (size_t i = 0; i < polys.size(); ++ i) { + const Polyline &poly = polys[i]; + for (Points::const_iterator it = poly.points.begin(); it != poly.points.end()-1; ++it) + lines.push_back(Line(*it, *(it + 1))); + } + return lines; +} + class ThickPolyline : public Polyline { public: std::vector<coordf_t> width; diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp index d48b59557..9ef710741 100644 --- a/xs/src/libslic3r/Surface.hpp +++ b/xs/src/libslic3r/Surface.hpp @@ -56,6 +56,7 @@ public: #endif operator Polygons() const; double area() const; + bool empty() const { return expolygon.empty(); } bool is_solid() const; bool is_external() const; bool is_internal() const; @@ -168,6 +169,10 @@ inline void surfaces_append(Surfaces &dst, const ExPolygons &src, const Surface for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++ it) dst.push_back(Surface(surfaceTempl, *it)); } +inline void surfaces_append(Surfaces &dst, const Surfaces &src) +{ + dst.insert(dst.end(), src.begin(), src.end()); +} #if SLIC3R_CPPVER >= 11 inline void surfaces_append(Surfaces &dst, ExPolygons &&src, SurfaceType surfaceType) @@ -182,12 +187,28 @@ inline void surfaces_append(Surfaces &dst, ExPolygons &&src, const Surface &surf for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++ it) dst.push_back(Surface(surfaceTempl, std::move(*it))); } +inline void surfaces_append(Surfaces &dst, Surfaces &&src) +{ + if (dst.empty()) + dst = std::move(src); + else + std::move(std::begin(src), std::end(src), std::back_inserter(dst)); +} #endif extern BoundingBox get_extents(const Surface &surface); extern BoundingBox get_extents(const Surfaces &surfaces); extern BoundingBox get_extents(const SurfacesPtr &surfaces); +inline bool surfaces_could_merge(const Surface &s1, const Surface &s2) +{ + return + s1.surface_type == s2.surface_type && + s1.thickness == s2.thickness && + s1.thickness_layers == s2.thickness_layers && + s1.bridge_angle == s2.bridge_angle; +} + class SVG; extern const char* surface_type_to_color_name(const SurfaceType surface_type); diff --git a/xs/src/libslic3r/SurfaceCollection.cpp b/xs/src/libslic3r/SurfaceCollection.cpp index c31d603c0..804190548 100644 --- a/xs/src/libslic3r/SurfaceCollection.cpp +++ b/xs/src/libslic3r/SurfaceCollection.cpp @@ -49,23 +49,16 @@ SurfaceCollection::group(std::vector<SurfacesPtr> *retval) for (Surfaces::iterator it = this->surfaces.begin(); it != this->surfaces.end(); ++it) { // find a group with the same properties SurfacesPtr* group = NULL; - for (std::vector<SurfacesPtr>::iterator git = retval->begin(); git != retval->end(); ++git) { - Surface* gkey = git->front(); - if ( gkey->surface_type == it->surface_type - && gkey->thickness == it->thickness - && gkey->thickness_layers == it->thickness_layers - && gkey->bridge_angle == it->bridge_angle) { + for (std::vector<SurfacesPtr>::iterator git = retval->begin(); git != retval->end(); ++git) + if (! git->empty() && surfaces_could_merge(*git->front(), *it)) { group = &*git; break; } - } - // if no group with these properties exists, add one if (group == NULL) { retval->resize(retval->size() + 1); group = &retval->back(); } - // append surface to group group->push_back(&*it); } diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h index 431482cba..78853f145 100644 --- a/xs/src/libslic3r/libslic3r.h +++ b/xs/src/libslic3r/libslic3r.h @@ -60,10 +60,13 @@ void confess_at(const char *file, int line, const char *func, const char *pat, . // For example, could optimized functions with move semantics be used? #if __cplusplus==201402L #define SLIC3R_CPPVER 14 + #define STDMOVE(WHAT) std::move(WHAT) #elif __cplusplus==201103L #define SLIC3R_CPPVER 11 + #define STDMOVE(WHAT) std::move(WHAT) #else #define SLIC3R_CPPVER 0 + #define STDMOVE(WHAT) (WHAT) #endif #define SLIC3R_DEBUG_OUT_PATH_PREFIX "out/"