#include "Clipper2Utils.hpp" #include "libslic3r.h" #include "clipper2/clipper.h" namespace Slic3r { //BBS: FIXME Slic3r::Polylines Paths64_to_polylines(const Clipper2Lib::Paths64& in) { Slic3r::Polylines out; out.reserve(in.size()); for (const Clipper2Lib::Path64& path64 : in) { Slic3r::Points points; points.reserve(path64.size()); for (const Clipper2Lib::Point64& point64 : path64) points.emplace_back(std::move(Slic3r::Point(point64.x, point64.y))); out.emplace_back(std::move(Slic3r::Polyline(points))); } return out; } //BBS: FIXME template Clipper2Lib::Paths64 Slic3rPoints_to_Paths64(const std::vector& in) { Clipper2Lib::Paths64 out; out.reserve(in.size()); for (const T item: in) { Clipper2Lib::Path64 path; path.reserve(item.size()); for (const Slic3r::Point& point : item.points) path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y()))); out.emplace_back(std::move(path)); } return out; } Points Path64ToPoints(const Clipper2Lib::Path64& path64) { Points points; points.reserve(path64.size()); for (const Clipper2Lib::Point64 &point64 : path64) points.emplace_back(std::move(Slic3r::Point(point64.x, point64.y))); return points; } static ExPolygons PolyTreeToExPolygons(Clipper2Lib::PolyTree64 &&polytree) { struct Inner { static void PolyTreeToExPolygonsRecursive(Clipper2Lib::PolyTree64 &&polynode, ExPolygons *expolygons) { size_t cnt = expolygons->size(); expolygons->resize(cnt + 1); (*expolygons)[cnt].contour.points = Path64ToPoints(polynode.Polygon()); (*expolygons)[cnt].holes.resize(polynode.Count()); for (int i = 0; i < polynode.Count(); ++i) { (*expolygons)[cnt].holes[i].points = Path64ToPoints(polynode[i]->Polygon()); // Add outer polygons contained by (nested within) holes. for (int j = 0; j < polynode[i]->Count(); ++j) PolyTreeToExPolygonsRecursive(std::move(*polynode[i]->Child(j)), expolygons); } } static size_t PolyTreeCountExPolygons(const Clipper2Lib::PolyPath64& polynode) { size_t cnt = 1; for (size_t i = 0; i < polynode.Count(); ++i) { for (size_t j = 0; j < polynode.Child(i)->Count(); ++j) cnt += PolyTreeCountExPolygons(*polynode.Child(i)->Child(j)); } return cnt; } }; ExPolygons retval; size_t cnt = 0; for (int i = 0; i < polytree.Count(); ++i) cnt += Inner::PolyTreeCountExPolygons(*polytree[i]); retval.reserve(cnt); for (int i = 0; i < polytree.Count(); ++i) Inner::PolyTreeToExPolygonsRecursive(std::move(*polytree[i]), &retval); return retval; } void SimplifyPolyTree(const Clipper2Lib::PolyPath64 &polytree, double epsilon, Clipper2Lib::PolyPath64 &result) { for (const auto &child : polytree) { Clipper2Lib::PolyPath64 *newchild = result.AddChild(Clipper2Lib::SimplifyPath(child->Polygon(), epsilon)); SimplifyPolyTree(*child, epsilon, *newchild); } } Clipper2Lib::Paths64 Slic3rPolygons_to_Paths64(const Polygons &in) { Clipper2Lib::Paths64 out; out.reserve(in.size()); for (const Polygon &poly : in) { Clipper2Lib::Path64 path; path.reserve(poly.points.size()); for (const Slic3r::Point &point : poly.points) path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y()))); out.emplace_back(std::move(path)); } return out; } Clipper2Lib::Paths64 Slic3rExPolygons_to_Paths64(const ExPolygons& in) { Clipper2Lib::Paths64 out; out.reserve(in.size()); for (const ExPolygon& expolygon : in) { for (size_t i = 0; i < expolygon.num_contours(); i++) { const auto &poly = expolygon.contour_or_hole(i); Clipper2Lib::Path64 path; path.reserve(poly.points.size()); for (const Slic3r::Point &point : poly.points) path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y()))); out.emplace_back(std::move(path)); } } return out; } Polylines _clipper2_pl_open(Clipper2Lib::ClipType clipType, const Slic3r::Polylines& subject, const Slic3r::Polygons& clip) { Clipper2Lib::Clipper64 c; c.AddOpenSubject(Slic3rPoints_to_Paths64(subject)); c.AddClip(Slic3rPoints_to_Paths64(clip)); Clipper2Lib::ClipType ct = clipType; Clipper2Lib::FillRule fr = Clipper2Lib::FillRule::NonZero; Clipper2Lib::Paths64 solution, solution_open; c.Execute(ct, fr, solution, solution_open); Slic3r::Polylines out; out.reserve(solution.size() + solution_open.size()); polylines_append(out, std::move(Paths64_to_polylines(solution))); polylines_append(out, std::move(Paths64_to_polylines(solution_open))); return out; } Slic3r::Polylines intersection_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip) { return _clipper2_pl_open(Clipper2Lib::ClipType::Intersection, subject, clip); } Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip) { return _clipper2_pl_open(Clipper2Lib::ClipType::Difference, subject, clip); } ExPolygons union_ex_2(const Polygons& polygons) { Clipper2Lib::Clipper64 c; c.AddSubject(Slic3rPolygons_to_Paths64(polygons)); Clipper2Lib::ClipType ct = Clipper2Lib::ClipType::Union; Clipper2Lib::FillRule fr = Clipper2Lib::FillRule::NonZero; Clipper2Lib::PolyTree64 solution; c.Execute(ct, fr, solution); ExPolygons results = PolyTreeToExPolygons(std::move(solution)); return results; } ExPolygons union_ex_2(const ExPolygons &expolygons) { Clipper2Lib::Clipper64 c; c.AddSubject(Slic3rExPolygons_to_Paths64(expolygons)); Clipper2Lib::ClipType ct = Clipper2Lib::ClipType::Union; Clipper2Lib::FillRule fr = Clipper2Lib::FillRule::NonZero; Clipper2Lib::PolyTree64 solution; c.Execute(ct, fr, solution); ExPolygons results = PolyTreeToExPolygons(std::move(solution)); return results; } // 对 ExPolygons 进行偏移 ExPolygons offset_ex_2(const ExPolygons &expolygons, double delta) { Clipper2Lib::Paths64 subject = Slic3rExPolygons_to_Paths64(expolygons); Clipper2Lib::ClipperOffset offsetter; offsetter.AddPaths(subject, Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Polygon); Clipper2Lib::PolyPath64 polytree; offsetter.Execute(delta, polytree); ExPolygons results = PolyTreeToExPolygons(std::move(polytree)); return results; } ExPolygons offset2_ex_2(const ExPolygons& expolygons, double delta1, double delta2) { // 1st offset Clipper2Lib::Paths64 subject = Slic3rExPolygons_to_Paths64(expolygons); Clipper2Lib::ClipperOffset offsetter; offsetter.AddPaths(subject, Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Polygon); Clipper2Lib::PolyPath64 polytree; offsetter.Execute(delta1, polytree); // simplify the result Clipper2Lib::PolyPath64 polytree2; SimplifyPolyTree(polytree, SCALED_EPSILON, polytree2); // 2nd offset offsetter.Clear(); offsetter.AddPaths(Clipper2Lib::PolyTreeToPaths64(polytree2), Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Polygon); polytree.Clear(); offsetter.Execute(delta2, polytree); // convert back to expolygons ExPolygons results = PolyTreeToExPolygons(std::move(polytree)); return results; } } // namespace Slic3r