BambuSrc/libslic3r/Clipper2Utils.cpp

211 lines
7.4 KiB
C++

#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 <typename T>
Clipper2Lib::Paths64 Slic3rPoints_to_Paths64(const std::vector<T>& 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