CuraEngine
CuraEngine copied to clipboard
Consider updating to clipper2
libclipper is one of the workhorses for CuraEngine, seeing that there is a newer version which has better performance: http://www.angusj.com/clipper2/Docs/Changes.htm
You might get overall beter performance in Cura if this is used instead.
With love,
Me.
if it isn't the man himself, the O.G.
I wasn't aware that clipper2 existed, so I will definitely look into that. Thank you for the heads up and I will bring it up with our next Cura & Cookies
Sweet! ❤️ Might be a while 'till we get to it, but definitely interested.
if it isn't the man himself, the O.G.
I wasn't aware that clipper2 existed, so I will definitely look into that. Thank you for the heads up and I will bring it up with our next Cura & Cookies
I noticed it, and directly went to check if you guys where already using it. Glad to hear Cura&Cookies is still a thing.
I expect good quality from clipper2. I only once had a bug with clipper1 and that was quickly fixed after creating a reproducible case and sending it.
you got all (of the developers) very excited atleast.
I was planning on creating a Conan recipe for clipper2 in the weekend, because currently only clipper1 is in the Conan Center Index https://github.com/conan-io/conan-center-index/blob/master/recipes/clipper/all/conanfile.py). which we use to setup our development environment https://github.com/Ultimaker/Cura/wiki/Running-Cura-from-Source. Once I made a PR for the new clipper2 it would be very easy to integrate build system wise so that we can experiment with the fun stuff.
Hi, I have done the experiment and now have a version of my Cura variant that uses Clipper2. Haven't extensively tested it so I don't have performance figures yet.
@smartavionics was it a drop-in replacement or did you change some fundamental types?
Unfortunately, it's not a drop-in replacement, I had to make a zillion small edits. To give you an idea, here's the diffs I made for IntPoint.h and polygon.h...
diff --git a/src/utils/IntPoint.h b/src/utils/IntPoint.h
index f0e4421e9..8db3336ef 100644
--- a/src/utils/IntPoint.h
+++ b/src/utils/IntPoint.h
@@ -11,7 +11,7 @@ Integer points are used to avoid floating point rounding errors, and because Cli
#define INLINE static inline
//Include Clipper to get the ClipperLib::IntPoint definition, which we reuse as Point definition.
-#include "clipper.hpp"
+#include "clipper2/clipper.h"
#include <cmath>
#include <functional> // for hash function object
#include <iostream> // auto-serialization / auto-toString()
@@ -37,27 +37,29 @@ namespace cura
{
/* 64bit Points are used mostly throughout the code, these are the 2D points from ClipperLib */
-typedef ClipperLib::IntPoint Point;
+typedef Clipper2Lib::Point64 Point;
-#define POINT_MIN std::numeric_limits<ClipperLib::cInt>::min()
-#define POINT_MAX std::numeric_limits<ClipperLib::cInt>::max()
+#define POINT_MIN std::numeric_limits<int64_t>::min()
+#define POINT_MAX std::numeric_limits<int64_t>::max()
-static Point no_point(std::numeric_limits<ClipperLib::cInt>::min(), std::numeric_limits<ClipperLib::cInt>::min());
+static Point no_point(std::numeric_limits<int64_t>::min(), std::numeric_limits<int64_t>::min());
/* Extra operators to make it easier to do math with the 64bit Point objects */
-INLINE Point operator-(const Point& p0) { return Point(-p0.X, -p0.Y); }
-INLINE Point operator+(const Point& p0, const Point& p1) { return Point(p0.X+p1.X, p0.Y+p1.Y); }
-INLINE Point operator-(const Point& p0, const Point& p1) { return Point(p0.X-p1.X, p0.Y-p1.Y); }
-INLINE Point operator*(const Point& p0, const coord_t i) { return Point(p0.X * i, p0.Y * i); }
+/*
+INLINE Point operator-(const Point& p0) { return Point(-p0.x, -p0.x); }
+INLINE Point operator+(const Point& p0, const Point& p1) { return Point(p0.x+p1.x, p0.y+p1.y); }
+INLINE Point operator-(const Point& p0, const Point& p1) { return Point(p0.x-p1.x, p0.y-p1.y); }
+*/
+INLINE Point operator*(const Point& p0, const coord_t i) { return Point(p0.x * i, p0.y * i); }
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type> //Use only for numeric types.
-INLINE Point operator*(const Point& p0, const T i) { return Point(p0.X * i, p0.Y * i); }
+INLINE Point operator*(const Point& p0, const T i) { return Point(p0.x * i, p0.y * i); }
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type> //Use only for numeric types.
INLINE Point operator*(const T i, const Point& p0) { return p0 * i; }
-INLINE Point operator/(const Point& p0, const coord_t i) { return Point(p0.X/i, p0.Y/i); }
-INLINE Point operator/(const Point& p0, const Point& p1) { return Point(p0.X/p1.X, p0.Y/p1.Y); }
+INLINE Point operator/(const Point& p0, const coord_t i) { return Point(p0.x/i, p0.y/i); }
+INLINE Point operator/(const Point& p0, const Point& p1) { return Point(p0.x/p1.x, p0.y/p1.y); }
-INLINE Point& operator += (Point& p0, const Point& p1) { p0.X += p1.X; p0.Y += p1.Y; return p0; }
-INLINE Point& operator -= (Point& p0, const Point& p1) { p0.X -= p1.X; p0.Y -= p1.Y; return p0; }
+INLINE Point& operator += (Point& p0, const Point& p1) { p0.x += p1.x; p0.y += p1.y; return p0; }
+INLINE Point& operator -= (Point& p0, const Point& p1) { p0.x -= p1.x; p0.y -= p1.y; return p0; }
/* ***** NOTE *****
TL;DR: DO NOT implement operators *= and /= because of the default values in ClipperLib::IntPoint's constructor.
@@ -73,21 +75,21 @@ INLINE Point& operator -= (Point& p0, const Point& p1) { p0.X -= p1.X; p0.Y -= p
INLINE coord_t vSize2(const Point& p0)
{
- return p0.X*p0.X+p0.Y*p0.Y;
+ return p0.x*p0.x+p0.y*p0.y;
}
INLINE float vSize2f(const Point& p0)
{
- return static_cast<float>(p0.X)*static_cast<float>(p0.X)+static_cast<float>(p0.Y)*static_cast<float>(p0.Y);
+ return static_cast<float>(p0.x)*static_cast<float>(p0.x)+static_cast<float>(p0.y)*static_cast<float>(p0.y);
}
INLINE bool shorterThen(const Point& p0, const coord_t len)
{
- if (p0.X > len || p0.X < -len)
+ if (p0.x > len || p0.x < -len)
{
return false;
}
- if (p0.Y > len || p0.Y < -len)
+ if (p0.y > len || p0.y < -len)
{
return false;
}
@@ -101,8 +103,8 @@ INLINE coord_t vSize(const Point& p0)
INLINE double vSizeMM(const Point& p0)
{
- double fx = INT2MM(p0.X);
- double fy = INT2MM(p0.Y);
+ double fx = INT2MM(p0.x);
+ double fy = INT2MM(p0.y);
return sqrt(fx*fx+fy*fy);
}
@@ -110,30 +112,30 @@ INLINE Point normal(const Point& p0, coord_t len)
{
coord_t _len = vSize(p0);
if (_len < 1)
- return Point(len, 0);
+ return Point(len, (coord_t)0);
return p0 * len / _len;
}
INLINE Point turn90CCW(const Point& p0)
{
- return Point(-p0.Y, p0.X);
+ return Point(-p0.y, p0.x);
}
INLINE Point rotate(const Point& p0, double angle)
{
const double cos_component = std::cos(angle);
const double sin_component = std::sin(angle);
- return Point(cos_component * p0.X - sin_component * p0.Y, sin_component * p0.X + cos_component * p0.Y);
+ return Point(cos_component * p0.x - sin_component * p0.y, sin_component * p0.x + cos_component * p0.y);
}
INLINE coord_t dot(const Point& p0, const Point& p1)
{
- return p0.X * p1.X + p0.Y * p1.Y;
+ return p0.x * p1.x + p0.y * p1.y;
}
INLINE double angle(const Point& p)
{
- double angle = std::atan2(p.X, p.Y) / M_PI * 180.0;
+ double angle = std::atan2(p.x, p.y) / M_PI * 180.0;
if (angle < 0.0) angle += 360.0;
return angle;
}
@@ -147,8 +149,8 @@ struct hash<cura::Point> {
{
static int prime = 31;
int result = 89;
- result = result * prime + pp.X;
- result = result * prime + pp.Y;
+ result = result * prime + pp.x;
+ result = result * prime + pp.y;
return result;
}
};
@@ -181,8 +183,8 @@ public:
PointMatrix(const Point p)
{
- matrix[0] = p.X;
- matrix[1] = p.Y;
+ matrix[0] = p.x;
+ matrix[1] = p.y;
double f = sqrt((matrix[0] * matrix[0]) + (matrix[1] * matrix[1]));
matrix[0] /= f;
matrix[1] /= f;
@@ -192,12 +194,12 @@ public:
Point apply(const Point p) const
{
- return Point(p.X * matrix[0] + p.Y * matrix[1], p.X * matrix[2] + p.Y * matrix[3]);
+ return Point(p.x * matrix[0] + p.y * matrix[1], p.x * matrix[2] + p.y * matrix[3]);
}
Point unapply(const Point p) const
{
- return Point(p.X * matrix[0] + p.Y * matrix[2], p.X * matrix[1] + p.Y * matrix[3]);
+ return Point(p.x * matrix[0] + p.y * matrix[2], p.x * matrix[1] + p.y * matrix[3]);
}
};
@@ -248,15 +250,15 @@ public:
*/
Point apply(const Point p) const
{
- Point3 result = apply(Point3(p.X, p.Y, 1));
+ Point3 result = apply(Point3(p.x, p.y, 1));
return Point(result.x / result.z, result.y / result.z);
}
static Point3Matrix translate(const Point p)
{
Point3Matrix ret; // uniform matrix
- ret.matrix[2] = p.X;
- ret.matrix[5] = p.Y;
+ ret.matrix[2] = p.x;
+ ret.matrix[5] = p.y;
return ret;
}
@@ -280,30 +282,30 @@ public:
inline Point3 operator+(const Point3& p3, const Point& p2) {
- return Point3(p3.x + p2.X, p3.y + p2.Y, p3.z);
+ return Point3(p3.x + p2.x, p3.y + p2.y, p3.z);
}
inline Point3& operator+=(Point3& p3, const Point& p2) {
- p3.x += p2.X;
- p3.y += p2.Y;
+ p3.x += p2.x;
+ p3.y += p2.y;
return p3;
}
inline Point operator+(const Point& p2, const Point3& p3) {
- return Point(p3.x + p2.X, p3.y + p2.Y);
+ return Point(p3.x + p2.x, p3.y + p2.y);
}
inline Point3 operator-(const Point3& p3, const Point& p2) {
- return Point3(p3.x - p2.X, p3.y - p2.Y, p3.z);
+ return Point3(p3.x - p2.x, p3.y - p2.y, p3.z);
}
inline Point3& operator-=(Point3& p3, const Point& p2) {
- p3.x -= p2.X;
- p3.y -= p2.Y;
+ p3.x -= p2.x;
+ p3.y -= p2.y;
return p3;
}
inline Point operator-(const Point& p2, const Point3& p3) {
- return Point(p2.X - p3.x, p2.Y - p3.y);
+ return Point(p2.x - p3.x, p2.y - p3.y);
}
}//namespace cura
diff --git a/src/utils/polygon.h b/src/utils/polygon.h
index 02dc50bee..a701c65fb 100644
--- a/src/utils/polygon.h
+++ b/src/utils/polygon.h
@@ -7,7 +7,7 @@
#include <vector>
#include <assert.h>
#include <float.h>
-#include "clipper.hpp"
+#include "clipper2/clipper.h"
#include <algorithm> // std::reverse, fill_n array
#include <cmath> // fabs
@@ -39,7 +39,6 @@ class ListPolyIt;
typedef std::list<Point> ListPolygon; //!< A polygon represented by a linked list instead of a vector
typedef std::vector<ListPolygon> ListPolygons; //!< Polygons represented by a vector of linked lists instead of a vector of vectors
-const static int clipper_init = (0);
#define NO_INDEX (std::numeric_limits<unsigned int>::max())
class ConstPolygonPointer;
@@ -56,10 +55,10 @@ class ConstPolygonRef
friend class PolygonRef;
friend class ConstPolygonPointer;
protected:
- ClipperLib::Path* path;
+ Clipper2Lib::Path64* path;
public:
- ConstPolygonRef(const ClipperLib::Path& polygon)
- : path(const_cast<ClipperLib::Path*>(&polygon))
+ ConstPolygonRef(const Clipper2Lib::Path64& polygon)
+ : path(const_cast<Clipper2Lib::Path64*>(&polygon))
{}
virtual ~ConstPolygonRef()
@@ -89,22 +88,22 @@ public:
return (*path)[index];
}
- const ClipperLib::Path& operator*() const
+ const Clipper2Lib::Path64& operator*() const
{
return *path;
}
- ClipperLib::Path::const_iterator begin() const
+ Clipper2Lib::Path64::const_iterator begin() const
{
return path->begin();
}
- ClipperLib::Path::const_iterator end() const
+ Clipper2Lib::Path64::const_iterator end() const
{
return path->end();
}
- ClipperLib::Path::const_reference back() const
+ Clipper2Lib::Path64::const_reference back() const
{
return path->back();
}
@@ -122,10 +121,10 @@ public:
*/
bool orientation() const
{
- return ClipperLib::Orientation(*path);
+ return Clipper2Lib::IsPositive(*path);
}
- Polygons offset(int distance, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miter_limit = 1.2) const;
+ Polygons offset(int distance, Clipper2Lib::JoinType joinType = Clipper2Lib::JoinType::Miter, double miter_limit = 1.2) const;
int64_t polygonLength() const
{
@@ -147,8 +146,8 @@ public:
Point ret = Point(POINT_MAX, POINT_MAX);
for(Point p : *path)
{
- ret.X = std::min(ret.X, p.X);
- ret.Y = std::min(ret.Y, p.Y);
+ ret.x = std::min(ret.x, p.x);
+ ret.y = std::min(ret.y, p.y);
}
return ret;
}
@@ -158,15 +157,15 @@ public:
Point ret = Point(POINT_MIN, POINT_MIN);
for(Point p : *path)
{
- ret.X = std::max(ret.X, p.X);
- ret.Y = std::max(ret.Y, p.Y);
+ ret.x = std::max(ret.x, p.x);
+ ret.y = std::max(ret.y, p.y);
}
return ret;
}
double area() const
{
- return ClipperLib::Area(*path);
+ return Clipper2Lib::Area(*path);
}
Point centerOfMass() const
@@ -176,10 +175,10 @@ public:
for(unsigned int n=0; n<path->size(); n++)
{
Point p1 = (*path)[n];
- double second_factor = (p0.X * p1.Y) - (p1.X * p0.Y);
+ double second_factor = (p0.x * p1.y) - (p1.x * p0.y);
- x += double(p0.X + p1.X) * second_factor;
- y += double(p0.Y + p1.Y) * second_factor;
+ x += double(p0.x + p1.x) * second_factor;
+ y += double(p0.y + p1.y) * second_factor;
p0 = p1;
}
@@ -235,12 +234,12 @@ public:
*/
bool inside(Point p, bool border_result = false) const
{
- int res = ClipperLib::PointInPolygon(p, *path);
- if (res == -1)
+ Clipper2Lib::PointInPolygonResult res = Clipper2Lib::PointInPolygon(p, *path);
+ if (res == Clipper2Lib::PointInPolygonResult::IsOn)
{
return border_result;
}
- return res == 1;
+ return res == Clipper2Lib::PointInPolygonResult::IsInside;
}
/*!
@@ -347,7 +346,7 @@ class PolygonRef : public ConstPolygonRef
{
friend class PolygonPointer;
public:
- PolygonRef(ClipperLib::Path& polygon)
+ PolygonRef(Clipper2Lib::Path64& polygon)
: ConstPolygonRef(polygon)
{}
@@ -386,17 +385,17 @@ public:
return path->at(index);
}
- ClipperLib::Path::iterator begin()
+ Clipper2Lib::Path64::iterator begin()
{
return path->begin();
}
- ClipperLib::Path::iterator end()
+ Clipper2Lib::Path64::iterator end()
{
return path->end();
}
- ClipperLib::Path::reference back()
+ Clipper2Lib::Path64::reference back()
{
return path->back();
}
@@ -411,7 +410,7 @@ public:
path->push_back(p);
}
- ClipperLib::Path& operator*()
+ Clipper2Lib::Path64& operator*()
{
return *path;
}
@@ -435,7 +434,7 @@ public:
void reverse()
{
- ClipperLib::ReversePath(*path);
+ std::reverse(path->begin(), path->end());
}
/*!
@@ -484,7 +483,7 @@ public:
class ConstPolygonPointer
{
protected:
- const ClipperLib::Path* path;
+ const Clipper2Lib::Path64* path;
public:
ConstPolygonPointer()
: path(nullptr)
@@ -501,7 +500,7 @@ public:
assert(path);
return ConstPolygonRef(*path);
}
- const ClipperLib::Path* operator->() const
+ const Clipper2Lib::Path64* operator->() const
{
assert(path);
return path;
@@ -521,7 +520,7 @@ public:
class PolygonPointer
{
protected:
- ClipperLib::Path* path;
+ Clipper2Lib::Path64* path;
public:
PolygonPointer()
: path(nullptr)
@@ -539,7 +538,7 @@ public:
assert(path);
return PolygonRef(*path);
}
- ClipperLib::Path* operator->()
+ Clipper2Lib::Path64* operator->()
{
assert(path);
return path;
@@ -553,7 +552,7 @@ public:
class Polygon : public PolygonRef
{
- ClipperLib::Path poly;
+ Clipper2Lib::Path64 poly;
public:
Polygon()
: PolygonRef(poly)
@@ -604,7 +603,7 @@ class Polygons
friend class PolygonRef;
friend class ConstPolygonRef;
protected:
- ClipperLib::Paths paths;
+ Clipper2Lib::Paths64 paths;
public:
unsigned int size() const
{
@@ -630,19 +629,19 @@ public:
POLY_ASSERT(index < size() && index <= static_cast<unsigned int>(std::numeric_limits<int>::max()));
return paths[index];
}
- ClipperLib::Paths::iterator begin()
+ Clipper2Lib::Paths64::iterator begin()
{
return paths.begin();
}
- ClipperLib::Paths::const_iterator begin() const
+ Clipper2Lib::Paths64::const_iterator begin() const
{
return paths.begin();
}
- ClipperLib::Paths::iterator end()
+ Clipper2Lib::Paths64::iterator end()
{
return paths.end();
}
- ClipperLib::Paths::const_iterator end() const
+ Clipper2Lib::Paths64::const_iterator end() const
{
return paths.end();
}
@@ -669,7 +668,7 @@ public:
/*!
* Remove a range of polygons
*/
- void erase(ClipperLib::Paths::iterator start, ClipperLib::Paths::iterator end)
+ void erase(Clipper2Lib::Paths64::iterator start, Clipper2Lib::Paths64::iterator end)
{
paths.erase(start, end);
}
@@ -698,7 +697,7 @@ public:
*/
void addLine(const Point from, const Point to)
{
- paths.emplace_back(ClipperLib::Path{from, to});
+ paths.emplace_back(Clipper2Lib::Path64{from, to});
}
template<typename... Args>
@@ -734,24 +733,18 @@ public:
* Convert ClipperLib::PolyTree to a Polygons object,
* which uses ClipperLib::Paths instead of ClipperLib::PolyTree
*/
- static Polygons toPolygons(ClipperLib::PolyTree& poly_tree);
+ static Polygons toPolygons(Clipper2Lib::PolyTree64& poly_tree);
Polygons difference(const Polygons& other) const
{
Polygons ret;
- ClipperLib::Clipper clipper(clipper_init);
- clipper.AddPaths(paths, ClipperLib::ptSubject, true);
- clipper.AddPaths(other.paths, ClipperLib::ptClip, true);
- clipper.Execute(ClipperLib::ctDifference, ret.paths);
+ ret.paths = Clipper2Lib::Difference(paths, other.paths, Clipper2Lib::FillRule::NonZero);
return ret;
}
- Polygons unionPolygons(const Polygons& other, ClipperLib::PolyFillType fill_type = ClipperLib::pftNonZero) const
+ Polygons unionPolygons(const Polygons& other, Clipper2Lib::FillRule fill_type = Clipper2Lib::FillRule::NonZero) const
{
Polygons ret;
- ClipperLib::Clipper clipper(clipper_init);
- clipper.AddPaths(paths, ClipperLib::ptSubject, true);
- clipper.AddPaths(other.paths, ClipperLib::ptSubject, true);
- clipper.Execute(ClipperLib::ctUnion, ret.paths, fill_type, fill_type);
+ ret.paths = Clipper2Lib::Union(paths, other.paths, fill_type);
return ret;
}
/*!
@@ -764,10 +757,7 @@ public:
Polygons intersection(const Polygons& other) const
{
Polygons ret;
- ClipperLib::Clipper clipper(clipper_init);
- clipper.AddPaths(paths, ClipperLib::ptSubject, true);
- clipper.AddPaths(other.paths, ClipperLib::ptClip, true);
- clipper.Execute(ClipperLib::ctIntersection, ret.paths);
+ ret.paths = Clipper2Lib::Intersect(paths, other.paths, Clipper2Lib::FillRule::NonZero);
return ret;
}
@@ -781,12 +771,14 @@ public:
* \param other Input line segments to be cropped
* \param segment_tree the resulting interior line segments
*/
- void lineSegmentIntersection(const Polygons& other, ClipperLib::PolyTree& segment_tree) const
+ void lineSegmentIntersection(const Polygons& other, Clipper2Lib::Paths64& open_paths) const
{
- ClipperLib::Clipper clipper(clipper_init);
- clipper.AddPaths(paths, ClipperLib::ptClip, true);
- clipper.AddPaths(other.paths, ClipperLib::ptSubject, false);
- clipper.Execute(ClipperLib::ctIntersection, segment_tree);
+ Clipper2Lib::Clipper64 clipper;
+ Clipper2Lib::PolyTree64 poly_tree;
+ clipper.AddOpenSubject(other.paths);
+ clipper.AddClip(paths);
+ Clipper2Lib::Paths64 closed_paths;
+ clipper.Execute(Clipper2Lib::ClipType::Intersection, Clipper2Lib::FillRule::EvenOdd, closed_paths, open_paths);
}
/*!
@@ -798,24 +790,18 @@ public:
Polygons xorPolygons(const Polygons& other) const
{
Polygons ret;
- ClipperLib::Clipper clipper(clipper_init);
- clipper.AddPaths(paths, ClipperLib::ptSubject, true);
- clipper.AddPaths(other.paths, ClipperLib::ptClip, true);
- clipper.Execute(ClipperLib::ctXor, ret.paths);
+ ret.paths = Clipper2Lib::Xor(paths, other.paths, Clipper2Lib::FillRule::NonZero);
return ret;
}
- Polygons offset(int distance, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miter_limit = 1.2) const;
+ Polygons offset(int distance, Clipper2Lib::JoinType joinType = Clipper2Lib::JoinType::Miter, double miter_limit = 1.2) const;
- Polygons offsetPolyLine(int distance, ClipperLib::JoinType joinType = ClipperLib::jtMiter) const
+ Polygons offsetPolyLine(int distance, Clipper2Lib::JoinType join_type = Clipper2Lib::JoinType::Miter) const
{
+ const Clipper2Lib::EndType end_type = (join_type == Clipper2Lib::JoinType::Miter)? Clipper2Lib::EndType::Square : Clipper2Lib::EndType::Round;
+ const double miter_limit = 1.2;
Polygons ret;
- double miterLimit = 1.2;
- ClipperLib::EndType end_type = (joinType == ClipperLib::jtMiter)? ClipperLib::etOpenSquare : ClipperLib::etOpenRound;
- ClipperLib::ClipperOffset clipper(miterLimit, 10.0);
- clipper.AddPaths(paths, joinType, end_type);
- clipper.MiterLimit = miterLimit;
- clipper.Execute(ret.paths, distance);
+ ret.paths = Clipper2Lib::InflatePaths(paths, distance, join_type, end_type, miter_limit);
return ret;
}
@@ -987,14 +973,14 @@ private:
* \param remove_holes Whether to remove empty holes or everything but the empty holes
* \param ret Where to store polygons which are not empty holes
*/
- void removeEmptyHoles_processPolyTreeNode(const ClipperLib::PolyNode& node, const bool remove_holes, Polygons& ret) const;
- void splitIntoParts_processPolyTreeNode(ClipperLib::PolyNode* node, std::vector<PolygonsPart>& ret) const;
+ void removeEmptyHoles_processPolyTreeNode(const Clipper2Lib::PolyTree64& node, const bool remove_holes, Polygons& ret) const;
+ void splitIntoParts_processPolyTreeNode(Clipper2Lib::PolyTree64* node, std::vector<PolygonsPart>& ret) const;
/*!
* Convert a node from a ClipperLib::PolyTree and add it to a Polygons object,
* which uses ClipperLib::Paths instead of ClipperLib::PolyTree
*/
- void addPolyTreeNodeRecursive(const ClipperLib::PolyNode& node);
+ void addPolyTreeNodeRecursive(const Clipper2Lib::PolyTree64& node);
public:
/*!
* Split up the polygons into groups according to the even-odd rule.
@@ -1004,7 +990,7 @@ public:
*/
PartsView splitIntoPartsView(bool unionAll = false);
private:
- void splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Polygons& reordered, ClipperLib::PolyNode* node) const;
+ void splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Polygons& reordered, Clipper2Lib::PolyTree64* node) const;
public:
/*!
* Removes polygons with area smaller than \p min_area_size (note that min_area_size is in mm^2, not in micron^2).
@@ -1105,9 +1091,7 @@ public:
Polygons processEvenOdd() const
{
Polygons ret;
- ClipperLib::Clipper clipper(clipper_init);
- clipper.AddPaths(paths, ClipperLib::ptSubject, true);
- clipper.Execute(ClipperLib::ctUnion, ret.paths);
+ ret.paths = Clipper2Lib::Union(paths, ret.paths, Clipper2Lib::FillRule::NonZero);
return ret;
}
@@ -1132,12 +1116,12 @@ public:
Point min() const
{
Point ret = Point(POINT_MAX, POINT_MAX);
- for(const ClipperLib::Path& polygon : paths)
+ for(const Clipper2Lib::Path64& polygon : paths)
{
for(Point p : polygon)
{
- ret.X = std::min(ret.X, p.X);
- ret.Y = std::min(ret.Y, p.Y);
+ ret.x = std::min(ret.x, p.x);
+ ret.y = std::min(ret.y, p.y);
}
}
return ret;
@@ -1146,12 +1130,12 @@ public:
Point max() const
{
Point ret = Point(POINT_MIN, POINT_MIN);
- for(const ClipperLib::Path& polygon : paths)
+ for(const Clipper2Lib::Path64& polygon : paths)
{
for(Point p : polygon)
{
- ret.X = std::max(ret.X, p.X);
- ret.Y = std::max(ret.Y, p.Y);
+ ret.x = std::max(ret.x, p.x);
+ ret.y = std::max(ret.y, p.y);
}
}
return ret;
I just tried slicing a reasonably complex model and the times reported by the engine were 80 seconds for Clipper2 and 78 seconds for Clipper1. Hardly encouraging. This was using a Cura 4 based slicer, i.e. no Arachne. I'll try some different models and see if I can detect any speed benefit.
Just sliced another complex model and, again, Clipper2 is very slightly slower than Clipper1. So perhaps it's not worth going to the effort of upgrading?
@smartavionics I made a PR today for setting up an automatic benchmark check, might be of interest to you as well. https://github.com/Ultimaker/CuraEngine/pull/1775