Clipper library:

Added some comments,
some methods were made inline, tiny methods moved to the header as inline,
dynamic allocation replaced with std:: containers,
changed some loops to the condensed C++11 syntax.
This commit is contained in:
bubnikv 2017-03-02 17:11:46 +01:00
parent fddd7c620f
commit 5580fd64b3
2 changed files with 290 additions and 466 deletions

File diff suppressed because it is too large Load Diff

View File

@ -50,8 +50,7 @@
//#define use_deprecated //#define use_deprecated
#include <vector> #include <vector>
#include <list> #include <deque>
#include <set>
#include <stdexcept> #include <stdexcept>
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
@ -136,21 +135,22 @@ typedef std::vector< PolyNode* > PolyNodes;
class PolyNode class PolyNode
{ {
public: public:
PolyNode(); PolyNode() : Childs(), Parent(0), Index(0), m_IsOpen(false) {}
virtual ~PolyNode(){}; virtual ~PolyNode(){};
Path Contour; Path Contour;
PolyNodes Childs; PolyNodes Childs;
PolyNode* Parent; PolyNode* Parent;
PolyNode* GetNext() const; // Traversal of the polygon tree in a depth first fashion.
PolyNode* GetNext() const { return Childs.empty() ? GetNextSiblingUp() : Childs.front(); }
bool IsHole() const; bool IsHole() const;
bool IsOpen() const; bool IsOpen() const { return m_IsOpen; }
int ChildCount() const; int ChildCount() const { return (int)Childs.size(); }
private: private:
unsigned Index; //node index in Parent.Childs unsigned Index; //node index in Parent.Childs
bool m_IsOpen; bool m_IsOpen;
JoinType m_jointype; JoinType m_jointype;
EndType m_endtype; EndType m_endtype;
PolyNode* GetNextSiblingUp() const; PolyNode* GetNextSiblingUp() const { return Parent ? ((Index == Parent->Childs.size() - 1) ? Parent->GetNextSiblingUp() : Parent->Childs[Index + 1]) : nullptr; }
void AddChild(PolyNode& child); void AddChild(PolyNode& child);
friend class Clipper; //to access Index friend class Clipper; //to access Index
friend class ClipperOffset; friend class ClipperOffset;
@ -176,13 +176,13 @@ public:
Childs[i]->Parent = this; Childs[i]->Parent = this;
return *this; return *this;
} }
PolyNode* GetFirst() const; PolyNode* GetFirst() const { return Childs.empty() ? nullptr : Childs.front(); }
void Clear(); void Clear() { AllNodes.clear(); Childs.clear(); }
int Total() const; int Total() const;
private: private:
PolyTree(const PolyTree &src) = delete; PolyTree(const PolyTree &src) = delete;
PolyTree& operator=(const PolyTree &src) = delete; PolyTree& operator=(const PolyTree &src) = delete;
PolyNodes AllNodes; std::vector<PolyNode> AllNodes;
friend class Clipper; //to access AllNodes friend class Clipper; //to access AllNodes
}; };
@ -215,24 +215,62 @@ struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
//enums that are used internally ... //enums that are used internally ...
enum EdgeSide { esLeft = 1, esRight = 2}; enum EdgeSide { esLeft = 1, esRight = 2};
//forward declarations (for stuff used internally) ... // namespace Internal {
struct TEdge; //forward declarations (for stuff used internally) ...
struct IntersectNode; struct TEdge {
struct LocalMinimum; // Bottom point of this edge (with minimum Y).
struct OutPt; IntPoint Bot;
struct OutRec; // Current position.
struct Join { 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;
EdgeSide Side;
// Winding number delta. 1 or -1 depending on winding direction, 0 for open paths and flat closed paths.
int WindDelta;
int WindCnt;
int WindCnt2; //winding count of the opposite polytype
int OutIdx;
// Next edge in the input path.
TEdge *Next;
// Previous edge in the input path.
TEdge *Prev;
// Next edge in the Local Minima List chain.
TEdge *NextInLML;
TEdge *NextInAEL;
TEdge *PrevInAEL;
TEdge *NextInSEL;
TEdge *PrevInSEL;
};
struct IntersectNode {
IntersectNode(TEdge *Edge1, TEdge *Edge2, IntPoint Pt) :
Edge1(Edge1), Edge2(Edge2), Pt(Pt) {}
TEdge *Edge1;
TEdge *Edge2;
IntPoint Pt;
};
struct LocalMinimum {
cInt Y;
TEdge *LeftBound;
TEdge *RightBound;
};
struct OutPt;
struct OutRec;
struct Join {
Join(OutPt *OutPt1, OutPt *OutPt2, IntPoint OffPt) : Join(OutPt *OutPt1, OutPt *OutPt2, IntPoint OffPt) :
OutPt1(OutPt1), OutPt2(OutPt2), OffPt(OffPt) {} OutPt1(OutPt1), OutPt2(OutPt2), OffPt(OffPt) {}
OutPt *OutPt1; OutPt *OutPt1;
OutPt *OutPt2; OutPt *OutPt2;
IntPoint OffPt; IntPoint OffPt;
}; };
// }; // namespace Internal
typedef std::vector < OutRec* > PolyOutList;
typedef std::vector < TEdge* > EdgeList;
typedef std::vector < Join > JoinList;
typedef std::vector < IntersectNode* > IntersectList;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -242,8 +280,8 @@ typedef std::vector < IntersectNode* > IntersectList;
class ClipperBase class ClipperBase
{ {
public: public:
ClipperBase(); ClipperBase() : m_UseFullRange(false), m_HasOpenPaths(false) {}
virtual ~ClipperBase(); virtual ~ClipperBase() { Clear(); }
bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
virtual void Clear(); virtual void Clear();
@ -254,7 +292,6 @@ public:
void PreserveCollinear(bool value) {m_PreserveCollinear = value;}; void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
protected: protected:
TEdge* AddBoundsToLML(TEdge *e, bool IsClosed); TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
void PopLocalMinima();
virtual void Reset(); virtual void Reset();
TEdge* ProcessBound(TEdge* E, bool IsClockwise); TEdge* ProcessBound(TEdge* E, bool IsClockwise);
TEdge* DescendToMin(TEdge *&E); TEdge* DescendToMin(TEdge *&E);
@ -267,7 +304,7 @@ protected:
// False if the input polygons have abs values lower or equal to loRange. // False if the input polygons have abs values lower or equal to loRange.
bool m_UseFullRange; bool m_UseFullRange;
// A vector of edges per each input path. // A vector of edges per each input path.
EdgeList m_edges; std::vector<std::vector<TEdge>> m_edges;
// Don't remove intermediate vertices of a collinear sequence of points. // Don't remove intermediate vertices of a collinear sequence of points.
bool m_PreserveCollinear; bool m_PreserveCollinear;
// Is any of the paths inserted by AddPath() or AddPaths() open? // Is any of the paths inserted by AddPath() or AddPaths() open?
@ -279,17 +316,19 @@ class Clipper : public virtual ClipperBase
{ {
public: public:
Clipper(int initOptions = 0); Clipper(int initOptions = 0);
~Clipper(); ~Clipper() { Clear(); }
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
Paths &solution, Paths &solution,
PolyFillType fillType = pftEvenOdd); PolyFillType fillType = pftEvenOdd)
{ return Execute(clipType, solution, fillType, fillType); }
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
Paths &solution, Paths &solution,
PolyFillType subjFillType, PolyFillType subjFillType,
PolyFillType clipFillType); PolyFillType clipFillType);
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
PolyTree &polytree, PolyTree &polytree,
PolyFillType fillType = pftEvenOdd); PolyFillType fillType = pftEvenOdd)
{ return Execute(clipType, polytree, fillType, fillType); }
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
PolyTree &polytree, PolyTree &polytree,
PolyFillType subjFillType, PolyFillType subjFillType,
@ -300,21 +339,21 @@ public:
void StrictlySimple(bool value) {m_StrictSimple = value;}; void StrictlySimple(bool value) {m_StrictSimple = value;};
//set the callback function for z value filling on intersections (otherwise Z is 0) //set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz #ifdef use_xyz
void ZFillFunction(ZFillCallback zFillFunc); void ZFillFunction(ZFillCallback zFillFunc) { m_ZFill = zFillFunc; }
#endif #endif
protected: protected:
void Reset(); void Reset();
virtual bool ExecuteInternal(); virtual bool ExecuteInternal();
private: private:
PolyOutList m_PolyOuts; std::vector<OutRec*> m_PolyOuts;
JoinList m_Joins; std::vector<Join> m_Joins;
JoinList m_GhostJoins; std::vector<Join> m_GhostJoins;
IntersectList m_IntersectList; std::vector<IntersectNode> m_IntersectList;
ClipType m_ClipType; ClipType m_ClipType;
// A priority queue (a binary heap) of Y coordinates. // A priority queue (a binary heap) of Y coordinates.
std::priority_queue<cInt> m_Scanbeam; std::priority_queue<cInt> m_Scanbeam;
typedef std::list<cInt> MaximaList; // Maxima are collected by ProcessEdgesAtTopOfScanbeam(), consumed by ProcessHorizontal().
MaximaList m_Maxima; std::vector<cInt> m_Maxima;
TEdge *m_ActiveEdges; TEdge *m_ActiveEdges;
TEdge *m_SortedEdges; TEdge *m_SortedEdges;
PolyFillType m_ClipFillType; PolyFillType m_ClipFillType;
@ -327,9 +366,10 @@ private:
ZFillCallback m_ZFill; //custom callback ZFillCallback m_ZFill; //custom callback
#endif #endif
void SetWindingCount(TEdge& edge) const; void SetWindingCount(TEdge& edge) const;
bool IsEvenOddFillType(const TEdge& edge) const; bool IsEvenOddFillType(const TEdge& edge) const
bool IsEvenOddAltFillType(const TEdge& edge) const; { return (edge.PolyTyp == ptSubject) ? m_SubjFillType == pftEvenOdd : m_ClipFillType == pftEvenOdd; }
cInt PopScanbeam(); bool IsEvenOddAltFillType(const TEdge& edge) const
{ return (edge.PolyTyp == ptSubject) ? m_ClipFillType == pftEvenOdd : m_SubjFillType == pftEvenOdd; }
void InsertLocalMinimaIntoAEL(const cInt botY); void InsertLocalMinimaIntoAEL(const cInt botY);
void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge); void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
void AddEdgeToSEL(TEdge *edge); void AddEdgeToSEL(TEdge *edge);
@ -353,15 +393,12 @@ private:
OutPt* AddOutPt(TEdge *e, const IntPoint &pt); OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
OutPt* GetLastOutPt(TEdge *e); OutPt* GetLastOutPt(TEdge *e);
void DisposeAllOutRecs(); void DisposeAllOutRecs();
void DisposeOutRec(PolyOutList::size_type index);
bool ProcessIntersections(const cInt topY); bool ProcessIntersections(const cInt topY);
void BuildIntersectList(const cInt topY); void BuildIntersectList(const cInt topY);
void ProcessIntersectList();
void ProcessEdgesAtTopOfScanbeam(const cInt topY); void ProcessEdgesAtTopOfScanbeam(const cInt topY);
void BuildResult(Paths& polys); void BuildResult(Paths& polys);
void BuildResult2(PolyTree& polytree); void BuildResult2(PolyTree& polytree);
void SetHoleState(TEdge *e, OutRec *outrec) const; void SetHoleState(TEdge *e, OutRec *outrec) const;
void DisposeIntersectNodes();
bool FixupIntersectionOrder(); bool FixupIntersectionOrder();
void FixupOutPolygon(OutRec &outrec); void FixupOutPolygon(OutRec &outrec);
void FixupOutPolyline(OutRec &outrec); void FixupOutPolyline(OutRec &outrec);
@ -382,7 +419,7 @@ class ClipperOffset
{ {
public: public:
ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25); ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
~ClipperOffset(); ~ClipperOffset() { Clear(); }
void AddPath(const Path& path, JoinType joinType, EndType endType); void AddPath(const Path& path, JoinType joinType, EndType endType);
void AddPaths(const Paths& paths, JoinType joinType, EndType endType); void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
void Execute(Paths& solution, double delta); void Execute(Paths& solution, double delta);