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:
parent
fddd7c620f
commit
5580fd64b3
File diff suppressed because it is too large
Load Diff
@ -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,10 +215,52 @@ 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};
|
||||||
|
|
||||||
|
// namespace Internal {
|
||||||
//forward declarations (for stuff used internally) ...
|
//forward declarations (for stuff used internally) ...
|
||||||
struct TEdge;
|
struct TEdge {
|
||||||
struct IntersectNode;
|
// Bottom point of this edge (with minimum Y).
|
||||||
struct LocalMinimum;
|
IntPoint Bot;
|
||||||
|
// Current position.
|
||||||
|
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 OutPt;
|
||||||
struct OutRec;
|
struct OutRec;
|
||||||
struct Join {
|
struct Join {
|
||||||
@ -228,11 +270,7 @@ struct Join {
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user