Upgrade clipper & improve multi-thread performance (#7177)
* Clipper: Verify range of int32 coordinates on input. Cherry-picked from prusa3d/PrusaSlicer@fa7debf49d Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * ClipperLib: Optimized PointInPolygon() to calculate cross products with int64s instead of doubles. Cherry-picked from prusa3d/PrusaSlicer@9dca8403fe Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Reworked the ClipperLib / Polygon types to use the tbb::scallable_allocator to better scale on multiple threads. Cherry-picked from prusa3d/PrusaSlicer@9cde96993e Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * use tbb::scallable_allocator for Polygons and ExPolygon::holes to better scale on multiple threads Cherry-picked from prusa3d/PrusaSlicer@b67ad6434d Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Fixed compilation on GCC and CLang Cherry-picked from prusa3d/PrusaSlicer@b3b44681a9 Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Remove clipper2 which is not used * Removed shiny profiler from clipperlib Cherry-picked from prusa3d/PrusaSlicer@7e77048593 Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * ClipperLib: Further optimization of memory allocation using scalable_allocator. ClipperLib: SimplifyPolygon() - changed default winding number to positive, added strictly_simple parameter. ClipperUtlis simplify_polygons() - removed "remove_collinear" parameter Cherry-picked from prusa3d/PrusaSlicer@a7e17df25f Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * ClipperLib: emplace_back() instead of push_back(). Cherry-picked from prusa3d/PrusaSlicer@2e150795b1 Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Fixed issue in a 32bit clipper, where IntersectPoint() checked for the Y coordinate of the calculated intersection point for validity, but the Y coordinate was already rounded to 32bits, thus an overflow may have in rare cases masked invalidity of the result. Cherry-picked from prusa3d/PrusaSlicer@b39c33414f Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Fixed Vojtech's out of boundary assert in Clipper library. Cherry-picked from prusa3d/PrusaSlicer@0a202dcff3 Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Update clipper to 6.4.2. Cherry-picked from prusa3d/PrusaSlicer@b8b3cccb40 Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com> * Try fix cmake opencv --------- Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com>
This commit is contained in:
@@ -9,6 +9,4 @@ add_library(clipper STATIC
|
||||
clipper_z.hpp
|
||||
)
|
||||
|
||||
if(SLIC3R_PROFILE)
|
||||
target_link_libraries(clipper Shiny)
|
||||
endif()
|
||||
target_link_libraries(clipper TBB::tbb TBB::tbbmalloc)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Author : Angus Johnson *
|
||||
* Version : 6.2.9 *
|
||||
* Date : 16 February 2015 *
|
||||
* Version : 6.4.2 *
|
||||
* Date : 27 February 2017 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2015 *
|
||||
* Copyright : Angus Johnson 2010-2017 *
|
||||
* *
|
||||
* License: *
|
||||
* Use, modification & distribution is subject to Boost Software License Ver 1. *
|
||||
@@ -39,6 +39,8 @@
|
||||
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include <oneapi/tbb/scalable_allocator.h>
|
||||
|
||||
#define CLIPPER_VERSION "6.2.6"
|
||||
|
||||
//CLIPPERLIB_USE_XYZ: adds a Z member to IntPoint. Adds a minor cost to perfomance.
|
||||
@@ -50,6 +52,7 @@
|
||||
//use_deprecated: Enables temporary support for the obsolete functions
|
||||
//#define use_deprecated
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <stdexcept>
|
||||
@@ -85,9 +88,11 @@ enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
|
||||
// Point coordinate type
|
||||
#ifdef CLIPPERLIB_INT32
|
||||
// Coordinates and their differences (vectors of the coordinates) have to fit int32_t.
|
||||
typedef int32_t cInt;
|
||||
using cInt = int32_t;
|
||||
using CrossProductType = int64_t;
|
||||
#else
|
||||
typedef int64_t cInt;
|
||||
using cInt = int64_t;
|
||||
using CrossProductType = double;
|
||||
// Maximum cInt value to allow a cross product calculation using 32bit expressions.
|
||||
static constexpr cInt const loRange = 0x3FFFFFFF; // 0x3FFFFFFF = 1 073 741 823
|
||||
// Maximum allowed cInt value.
|
||||
@@ -110,8 +115,11 @@ using DoublePoint = Eigen::Matrix<double, 2, 1, Eigen::DontAlign>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
typedef std::vector<IntPoint> Path;
|
||||
typedef std::vector<Path> Paths;
|
||||
template<typename BaseType>
|
||||
using Allocator = tbb::scalable_allocator<BaseType>;
|
||||
//using Allocator = std::allocator<BaseType>;
|
||||
using Path = std::vector<IntPoint, Allocator<IntPoint>>;
|
||||
using Paths = std::vector<Path, Allocator<Path>>;
|
||||
|
||||
inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
|
||||
inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
|
||||
@@ -131,12 +139,12 @@ enum JoinType {jtSquare, jtRound, jtMiter};
|
||||
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
|
||||
|
||||
class PolyNode;
|
||||
typedef std::vector< PolyNode* > PolyNodes;
|
||||
typedef std::vector<PolyNode*, Allocator<PolyNode*>> PolyNodes;
|
||||
|
||||
class PolyNode
|
||||
{
|
||||
public:
|
||||
PolyNode() : Childs(), Parent(0), Index(0), m_IsOpen(false) {}
|
||||
PolyNode() : Parent(0), Index(0), m_IsOpen(false) {}
|
||||
virtual ~PolyNode(){};
|
||||
Path Contour;
|
||||
PolyNodes Childs;
|
||||
@@ -184,7 +192,7 @@ public:
|
||||
private:
|
||||
PolyTree(const PolyTree &src) = delete;
|
||||
PolyTree& operator=(const PolyTree &src) = delete;
|
||||
std::vector<PolyNode> AllNodes;
|
||||
std::vector<PolyNode, Allocator<PolyNode>> AllNodes;
|
||||
friend class Clipper; //to access AllNodes
|
||||
};
|
||||
|
||||
@@ -192,7 +200,8 @@ double Area(const Path &poly);
|
||||
inline bool Orientation(const Path &poly) { return Area(poly) >= 0; }
|
||||
int PointInPolygon(const IntPoint &pt, const Path &path);
|
||||
|
||||
Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType = pftEvenOdd);
|
||||
// Union with "strictly simple" fix enabled.
|
||||
Paths SimplifyPolygon(const Path &in_poly, PolyFillType fillType = pftNonZero, bool strictly_simple = true);
|
||||
|
||||
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
|
||||
void CleanPolygon(Path& poly, double distance = 1.415);
|
||||
@@ -225,8 +234,6 @@ enum EdgeSide { esLeft = 1, esRight = 2};
|
||||
IntPoint Curr;
|
||||
// Top point of this edge (with maximum Y).
|
||||
IntPoint Top;
|
||||
// Vector from Bot to Top.
|
||||
IntPoint Delta;
|
||||
// Slope (dx/dy). For horiontal edges, the slope is set to HORIZONTAL (-1.0E+40).
|
||||
double Dx;
|
||||
PolyType PolyTyp;
|
||||
@@ -275,7 +282,27 @@ enum EdgeSide { esLeft = 1, esRight = 2};
|
||||
OutPt *Prev;
|
||||
};
|
||||
|
||||
struct OutRec;
|
||||
using OutPts = std::vector<OutPt, Allocator<OutPt>>;
|
||||
|
||||
// Output polygon.
|
||||
struct OutRec {
|
||||
int Idx;
|
||||
bool IsHole;
|
||||
bool IsOpen;
|
||||
//The 'FirstLeft' field points to another OutRec that contains or is the
|
||||
//'parent' of OutRec. It is 'first left' because the ActiveEdgeList (AEL) is
|
||||
//parsed left from the current edge (owning OutRec) until the owner OutRec
|
||||
//is found. This field simplifies sorting the polygons into a tree structure
|
||||
//which reflects the parent/child relationships of all polygons.
|
||||
//This field should be renamed Parent, and will be later.
|
||||
OutRec* FirstLeft;
|
||||
// Used only by void Clipper::BuildResult2(PolyTree& polytree)
|
||||
PolyNode* PolyNd;
|
||||
// Linked list of output points, dynamically allocated.
|
||||
OutPt* Pts;
|
||||
OutPt* BottomPt;
|
||||
};
|
||||
|
||||
struct Join {
|
||||
Join(OutPt *OutPt1, OutPt *OutPt2, IntPoint OffPt) :
|
||||
OutPt1(OutPt1), OutPt2(OutPt2), OffPt(OffPt) {}
|
||||
@@ -310,7 +337,7 @@ public:
|
||||
if (num_paths == 1)
|
||||
return AddPath(*paths_provider.begin(), PolyTyp, Closed);
|
||||
|
||||
std::vector<int> num_edges(num_paths, 0);
|
||||
std::vector<int, Allocator<int>> num_edges(num_paths, 0);
|
||||
int num_edges_total = 0;
|
||||
size_t i = 0;
|
||||
for (const Path &pg : paths_provider) {
|
||||
@@ -331,7 +358,7 @@ public:
|
||||
return false;
|
||||
|
||||
// Allocate a new edge array.
|
||||
std::vector<TEdge> edges(num_edges_total);
|
||||
std::vector<TEdge, Allocator<TEdge>> edges(num_edges_total);
|
||||
// Fill in the edge array.
|
||||
bool result = false;
|
||||
TEdge *p_edge = edges.data();
|
||||
@@ -367,7 +394,7 @@ protected:
|
||||
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
|
||||
|
||||
// Local minima (Y, left edge, right edge) sorted by ascending Y.
|
||||
std::vector<LocalMinimum> m_MinimaList;
|
||||
std::vector<LocalMinimum, Allocator<LocalMinimum>> m_MinimaList;
|
||||
|
||||
#ifdef CLIPPERLIB_INT32
|
||||
static constexpr const bool m_UseFullRange = false;
|
||||
@@ -378,7 +405,8 @@ protected:
|
||||
#endif // CLIPPERLIB_INT32
|
||||
|
||||
// A vector of edges per each input path.
|
||||
std::vector<std::vector<TEdge>> m_edges;
|
||||
using Edges = std::vector<TEdge, Allocator<TEdge>>;
|
||||
std::vector<Edges, Allocator<Edges>> m_edges;
|
||||
// Don't remove intermediate vertices of a collinear sequence of points.
|
||||
bool m_PreserveCollinear;
|
||||
// Is any of the paths inserted by AddPath() or AddPaths() open?
|
||||
@@ -422,22 +450,23 @@ protected:
|
||||
private:
|
||||
|
||||
// Output polygons.
|
||||
std::vector<OutRec*> m_PolyOuts;
|
||||
std::deque<OutRec, Allocator<OutRec>> m_PolyOuts;
|
||||
// Output points, allocated by a continuous sets of m_OutPtsChunkSize.
|
||||
std::vector<OutPt*> m_OutPts;
|
||||
static constexpr const size_t m_OutPtsChunkSize = 32;
|
||||
std::deque<std::array<OutPt, m_OutPtsChunkSize>, Allocator<std::array<OutPt, m_OutPtsChunkSize>>> m_OutPts;
|
||||
// List of free output points, to be used before taking a point from m_OutPts or allocating a new chunk.
|
||||
OutPt *m_OutPtsFree;
|
||||
size_t m_OutPtsChunkSize;
|
||||
size_t m_OutPtsChunkLast;
|
||||
|
||||
std::vector<Join> m_Joins;
|
||||
std::vector<Join> m_GhostJoins;
|
||||
std::vector<IntersectNode> m_IntersectList;
|
||||
std::vector<Join, Allocator<Join>> m_Joins;
|
||||
std::vector<Join, Allocator<Join>> m_GhostJoins;
|
||||
std::vector<IntersectNode, Allocator<IntersectNode>> m_IntersectList;
|
||||
ClipType m_ClipType;
|
||||
// A priority queue (a binary heap) of Y coordinates.
|
||||
std::priority_queue<cInt> m_Scanbeam;
|
||||
using cInts = std::vector<cInt, Allocator<cInt>>;
|
||||
std::priority_queue<cInt, cInts> m_Scanbeam;
|
||||
// Maxima are collected by ProcessEdgesAtTopOfScanbeam(), consumed by ProcessHorizontal().
|
||||
std::vector<cInt> m_Maxima;
|
||||
cInts m_Maxima;
|
||||
TEdge *m_ActiveEdges;
|
||||
TEdge *m_SortedEdges;
|
||||
PolyFillType m_ClipFillType;
|
||||
@@ -471,7 +500,7 @@ private:
|
||||
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||
OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||
OutRec* GetOutRec(int idx);
|
||||
void AppendPolygon(TEdge *e1, TEdge *e2) const;
|
||||
void AppendPolygon(TEdge *e1, TEdge *e2);
|
||||
void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
|
||||
OutRec* CreateOutRec();
|
||||
OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
|
||||
@@ -487,7 +516,7 @@ private:
|
||||
void ProcessEdgesAtTopOfScanbeam(const cInt topY);
|
||||
void BuildResult(Paths& polys);
|
||||
void BuildResult2(PolyTree& polytree);
|
||||
void SetHoleState(TEdge *e, OutRec *outrec) const;
|
||||
void SetHoleState(TEdge *e, OutRec *outrec);
|
||||
bool FixupIntersectionOrder();
|
||||
void FixupOutPolygon(OutRec &outrec);
|
||||
void FixupOutPolyline(OutRec &outrec);
|
||||
@@ -497,8 +526,9 @@ private:
|
||||
bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, const IntPoint &Pt, bool DiscardLeft);
|
||||
void JoinCommonEdges();
|
||||
void DoSimplePolygons();
|
||||
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) const;
|
||||
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) const;
|
||||
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
|
||||
void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
#ifdef CLIPPERLIB_USE_XYZ
|
||||
void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
|
||||
#endif
|
||||
@@ -528,7 +558,7 @@ private:
|
||||
Paths m_destPolys;
|
||||
Path m_srcPoly;
|
||||
Path m_destPoly;
|
||||
std::vector<DoublePoint> m_normals;
|
||||
std::vector<DoublePoint, Allocator<DoublePoint>> m_normals;
|
||||
double m_delta, m_sinA, m_sin, m_cos;
|
||||
double m_miterLim, m_StepsPerRad;
|
||||
// x: index of the lowest contour in m_polyNodes
|
||||
@@ -556,8 +586,9 @@ class clipperException : public std::exception
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Union with "strictly simple" fix enabled.
|
||||
template<typename PathsProvider>
|
||||
inline Paths SimplifyPolygons(PathsProvider &&in_polys, PolyFillType fillType = pftEvenOdd, bool strictly_simple = true) {
|
||||
inline Paths SimplifyPolygons(PathsProvider &&in_polys, PolyFillType fillType = pftNonZero, bool strictly_simple = true) {
|
||||
Clipper c;
|
||||
c.StrictlySimple(strictly_simple);
|
||||
c.AddPaths(std::forward<PathsProvider>(in_polys), ptSubject, true);
|
||||
|
||||
Reference in New Issue
Block a user