Revert "Some optimization of memory allocation, some reduction / inlining of short functions."
This reverts commit bc19e97d45
.
This commit is contained in:
parent
473624fcd7
commit
062a6628e5
2 changed files with 176 additions and 114 deletions
xs/src
|
@ -47,7 +47,6 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
namespace ClipperLib {
|
namespace ClipperLib {
|
||||||
|
|
||||||
|
@ -65,28 +64,19 @@ static int const Skip = -2; //edge that would otherwise close a path
|
||||||
#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE))
|
#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE))
|
||||||
|
|
||||||
struct TEdge {
|
struct TEdge {
|
||||||
// Bottom point of this edge (with minimum Y).
|
|
||||||
IntPoint Bot;
|
IntPoint Bot;
|
||||||
// Current position.
|
|
||||||
IntPoint Curr;
|
IntPoint Curr;
|
||||||
// Top point of this edge (with maximum Y).
|
|
||||||
IntPoint Top;
|
IntPoint Top;
|
||||||
// Vector from Bot to Top.
|
|
||||||
IntPoint Delta;
|
IntPoint Delta;
|
||||||
// Slope (dx/dy). For horiontal edges, the slope is set to HORIZONTAL (-1.0E+40).
|
|
||||||
double Dx;
|
double Dx;
|
||||||
PolyType PolyTyp;
|
PolyType PolyTyp;
|
||||||
EdgeSide Side;
|
EdgeSide Side;
|
||||||
// Winding number delta. 1 or -1 depending on winding direction, 0 for open paths and flat closed paths.
|
int WindDelta; //1 or -1 depending on winding direction
|
||||||
int WindDelta;
|
|
||||||
int WindCnt;
|
int WindCnt;
|
||||||
int WindCnt2; //winding count of the opposite polytype
|
int WindCnt2; //winding count of the opposite polytype
|
||||||
int OutIdx;
|
int OutIdx;
|
||||||
// Next edge in the input path.
|
|
||||||
TEdge *Next;
|
TEdge *Next;
|
||||||
// Previous edge in the input path.
|
|
||||||
TEdge *Prev;
|
TEdge *Prev;
|
||||||
// Next edge in the Local Minima List chain.
|
|
||||||
TEdge *NextInLML;
|
TEdge *NextInLML;
|
||||||
TEdge *NextInAEL;
|
TEdge *NextInAEL;
|
||||||
TEdge *PrevInAEL;
|
TEdge *PrevInAEL;
|
||||||
|
@ -125,6 +115,20 @@ struct OutPt {
|
||||||
OutPt *Prev;
|
OutPt *Prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Join {
|
||||||
|
OutPt *OutPt1;
|
||||||
|
OutPt *OutPt2;
|
||||||
|
IntPoint OffPt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LocMinSorter
|
||||||
|
{
|
||||||
|
inline bool operator()(const LocalMinimum& locMin1, const LocalMinimum& locMin2)
|
||||||
|
{
|
||||||
|
return locMin2.Y < locMin1.Y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -214,7 +218,6 @@ PolyNode* PolyNode::GetNextSiblingUp() const
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Edge delimits a hole if it has an odd number of parent loops.
|
|
||||||
bool PolyNode::IsHole() const
|
bool PolyNode::IsHole() const
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
@ -347,7 +350,7 @@ class Int128
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline Int128 Int128Mul (long64 lhs, long64 rhs)
|
Int128 Int128Mul (long64 lhs, long64 rhs)
|
||||||
{
|
{
|
||||||
bool negate = (lhs < 0) != (rhs < 0);
|
bool negate = (lhs < 0) != (rhs < 0);
|
||||||
|
|
||||||
|
@ -378,7 +381,7 @@ inline Int128 Int128Mul (long64 lhs, long64 rhs)
|
||||||
// Miscellaneous global functions
|
// Miscellaneous global functions
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline bool Orientation(const Path &poly)
|
bool Orientation(const Path &poly)
|
||||||
{
|
{
|
||||||
return Area(poly) >= 0;
|
return Area(poly) >= 0;
|
||||||
}
|
}
|
||||||
|
@ -528,7 +531,7 @@ bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2)
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
inline bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range)
|
bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range)
|
||||||
{
|
{
|
||||||
#ifndef use_int32
|
#ifndef use_int32
|
||||||
if (UseFullInt64Range)
|
if (UseFullInt64Range)
|
||||||
|
@ -539,7 +542,7 @@ inline bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2,
|
bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2,
|
||||||
const IntPoint &pt3, bool UseFullInt64Range)
|
const IntPoint &pt3, bool UseFullInt64Range)
|
||||||
{
|
{
|
||||||
#ifndef use_int32
|
#ifndef use_int32
|
||||||
|
@ -551,7 +554,7 @@ inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2,
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2,
|
bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2,
|
||||||
const IntPoint &pt3, const IntPoint &pt4, bool UseFullInt64Range)
|
const IntPoint &pt3, const IntPoint &pt4, bool UseFullInt64Range)
|
||||||
{
|
{
|
||||||
#ifndef use_int32
|
#ifndef use_int32
|
||||||
|
@ -576,6 +579,16 @@ inline double GetDx(const IntPoint &pt1, const IntPoint &pt2)
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline void SetDx(TEdge &e)
|
||||||
|
{
|
||||||
|
e.Delta.X = (e.Top.X - e.Bot.X);
|
||||||
|
e.Delta.Y = (e.Top.Y - e.Bot.Y);
|
||||||
|
|
||||||
|
if (e.Delta.Y == 0) e.Dx = HORIZONTAL;
|
||||||
|
else e.Dx = (double)(e.Delta.X) / e.Delta.Y;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
inline void SwapSides(TEdge &Edge1, TEdge &Edge2)
|
inline void SwapSides(TEdge &Edge1, TEdge &Edge2)
|
||||||
{
|
{
|
||||||
EdgeSide Side = Edge1.Side;
|
EdgeSide Side = Edge1.Side;
|
||||||
|
@ -717,13 +730,7 @@ void InitEdge2(TEdge& e, PolyType Pt)
|
||||||
e.Top = e.Curr;
|
e.Top = e.Curr;
|
||||||
e.Bot = e.Next->Curr;
|
e.Bot = e.Next->Curr;
|
||||||
}
|
}
|
||||||
|
SetDx(e);
|
||||||
e.Delta.X = (e.Top.X - e.Bot.X);
|
|
||||||
e.Delta.Y = (e.Top.Y - e.Bot.Y);
|
|
||||||
|
|
||||||
if (e.Delta.Y == 0) e.Dx = HORIZONTAL;
|
|
||||||
else e.Dx = (double)(e.Delta.X) / e.Delta.Y;
|
|
||||||
|
|
||||||
e.PolyTyp = Pt;
|
e.PolyTyp = Pt;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -863,6 +870,7 @@ bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b)
|
||||||
|
|
||||||
ClipperBase::ClipperBase() //constructor
|
ClipperBase::ClipperBase() //constructor
|
||||||
{
|
{
|
||||||
|
m_CurrentLM = m_MinimaList.begin(); //begin() == end() here
|
||||||
m_UseFullRange = false;
|
m_UseFullRange = false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -873,8 +881,7 @@ ClipperBase::~ClipperBase() //destructor
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Called from ClipperBase::AddPath() to verify the scale of the input polygon coordinates.
|
void RangeTest(const IntPoint& Pt, bool& useFullRange)
|
||||||
inline void RangeTest(const IntPoint& Pt, bool& useFullRange)
|
|
||||||
{
|
{
|
||||||
if (useFullRange)
|
if (useFullRange)
|
||||||
{
|
{
|
||||||
|
@ -889,9 +896,7 @@ inline void RangeTest(const IntPoint& Pt, bool& useFullRange)
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Called from ClipperBase::AddPath() to construct the Local Minima List.
|
TEdge* FindNextLocMin(TEdge* E)
|
||||||
// Find a local minimum edge on the path starting with E.
|
|
||||||
inline TEdge* FindNextLocMin(TEdge* E)
|
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -908,7 +913,6 @@ inline TEdge* FindNextLocMin(TEdge* E)
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Called from ClipperBase::AddPath().
|
|
||||||
TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
|
TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
|
||||||
{
|
{
|
||||||
TEdge *Result = E;
|
TEdge *Result = E;
|
||||||
|
@ -943,7 +947,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
|
||||||
E = Result->Next;
|
E = Result->Next;
|
||||||
else
|
else
|
||||||
E = Result->Prev;
|
E = Result->Prev;
|
||||||
LocalMinimum locMin;
|
MinimaList::value_type locMin;
|
||||||
locMin.Y = E->Bot.Y;
|
locMin.Y = E->Bot.Y;
|
||||||
locMin.LeftBound = 0;
|
locMin.LeftBound = 0;
|
||||||
locMin.RightBound = E;
|
locMin.RightBound = E;
|
||||||
|
@ -1036,8 +1040,6 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||||
throw clipperException("AddPath: Open paths have been disabled.");
|
throw clipperException("AddPath: Open paths have been disabled.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Remove duplicate end point from a closed input path.
|
|
||||||
// Remove duplicate points from the end of the input path.
|
|
||||||
int highI = (int)pg.size() -1;
|
int highI = (int)pg.size() -1;
|
||||||
if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI;
|
if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI;
|
||||||
while (highI > 0 && (pg[highI] == pg[highI -1])) --highI;
|
while (highI > 0 && (pg[highI] == pg[highI -1])) --highI;
|
||||||
|
@ -1046,6 +1048,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||||
//create a new edge array ...
|
//create a new edge array ...
|
||||||
TEdge *edges = new TEdge [highI +1];
|
TEdge *edges = new TEdge [highI +1];
|
||||||
|
|
||||||
|
bool IsFlat = true;
|
||||||
//1. Basic (first) edge initialization ...
|
//1. Basic (first) edge initialization ...
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -1114,8 +1117,6 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||||
}
|
}
|
||||||
|
|
||||||
//3. Do second stage of edge initialization ...
|
//3. Do second stage of edge initialization ...
|
||||||
// IsFlat means all vertices have the same Y coordinate.
|
|
||||||
bool IsFlat = true;
|
|
||||||
E = eStart;
|
E = eStart;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -1137,7 +1138,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
E->Prev->OutIdx = Skip;
|
E->Prev->OutIdx = Skip;
|
||||||
LocalMinimum locMin;
|
MinimaList::value_type locMin;
|
||||||
locMin.Y = E->Bot.Y;
|
locMin.Y = E->Bot.Y;
|
||||||
locMin.LeftBound = 0;
|
locMin.LeftBound = 0;
|
||||||
locMin.RightBound = E;
|
locMin.RightBound = E;
|
||||||
|
@ -1163,8 +1164,6 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||||
//open paths have matching start and end points ...
|
//open paths have matching start and end points ...
|
||||||
if (E->Prev->Bot == E->Prev->Top) E = E->Next;
|
if (E->Prev->Bot == E->Prev->Top) E = E->Next;
|
||||||
|
|
||||||
// Find local minima and store them into a Local Minima List.
|
|
||||||
// Multiple Local Minima could be created for a single path.
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
E = FindNextLocMin(E);
|
E = FindNextLocMin(E);
|
||||||
|
@ -1173,7 +1172,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||||
|
|
||||||
//E and E.Prev now share a local minima (left aligned if horizontal).
|
//E and E.Prev now share a local minima (left aligned if horizontal).
|
||||||
//Compare their slopes to find which starts which bound ...
|
//Compare their slopes to find which starts which bound ...
|
||||||
LocalMinimum locMin;
|
MinimaList::value_type locMin;
|
||||||
locMin.Y = E->Bot.Y;
|
locMin.Y = E->Bot.Y;
|
||||||
if (E->Dx < E->Prev->Dx)
|
if (E->Dx < E->Prev->Dx)
|
||||||
{
|
{
|
||||||
|
@ -1223,7 +1222,7 @@ bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed)
|
||||||
|
|
||||||
void ClipperBase::Clear()
|
void ClipperBase::Clear()
|
||||||
{
|
{
|
||||||
m_MinimaList.clear();
|
DisposeLocalMinimaList();
|
||||||
for (EdgeList::size_type i = 0; i < m_edges.size(); ++i)
|
for (EdgeList::size_type i = 0; i < m_edges.size(); ++i)
|
||||||
{
|
{
|
||||||
//for each edge array in turn, find the first used edge and
|
//for each edge array in turn, find the first used edge and
|
||||||
|
@ -1237,16 +1236,16 @@ void ClipperBase::Clear()
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initialize the Local Minima List:
|
|
||||||
// Sort the LML entries, initialize the left / right bound edges of each Local Minima.
|
|
||||||
void ClipperBase::Reset()
|
void ClipperBase::Reset()
|
||||||
{
|
{
|
||||||
if (m_MinimaList.empty()) return; //ie nothing to process
|
m_CurrentLM = m_MinimaList.begin();
|
||||||
std::sort(m_MinimaList.begin(), m_MinimaList.end(), [](const LocalMinimum& lm1, const LocalMinimum& lm2){ return lm1.Y < lm2.Y; });
|
if (m_CurrentLM == m_MinimaList.end()) return; //ie nothing to process
|
||||||
|
std::sort(m_MinimaList.begin(), m_MinimaList.end(), LocMinSorter());
|
||||||
|
|
||||||
//reset all edges ...
|
//reset all edges ...
|
||||||
for (LocalMinimum &lm : m_MinimaList) {
|
for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm)
|
||||||
TEdge* e = lm.LeftBound;
|
{
|
||||||
|
TEdge* e = lm->LeftBound;
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
e->Curr = e->Bot;
|
e->Curr = e->Bot;
|
||||||
|
@ -1254,7 +1253,7 @@ void ClipperBase::Reset()
|
||||||
e->OutIdx = Unassigned;
|
e->OutIdx = Unassigned;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = lm.RightBound;
|
e = lm->RightBound;
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
e->Curr = e->Bot;
|
e->Curr = e->Bot;
|
||||||
|
@ -1265,12 +1264,24 @@ void ClipperBase::Reset()
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get bounds of the edges referenced by the Local Minima List.
|
void ClipperBase::DisposeLocalMinimaList()
|
||||||
// Returns (0,0,0,0) for an empty rectangle.
|
{
|
||||||
|
m_MinimaList.clear();
|
||||||
|
m_CurrentLM = m_MinimaList.begin();
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ClipperBase::PopLocalMinima()
|
||||||
|
{
|
||||||
|
if (m_CurrentLM == m_MinimaList.end()) return;
|
||||||
|
++m_CurrentLM;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
IntRect ClipperBase::GetBounds()
|
IntRect ClipperBase::GetBounds()
|
||||||
{
|
{
|
||||||
IntRect result;
|
IntRect result;
|
||||||
auto lm = m_MinimaList.begin();
|
MinimaList::iterator lm = m_MinimaList.begin();
|
||||||
if (lm == m_MinimaList.end())
|
if (lm == m_MinimaList.end())
|
||||||
{
|
{
|
||||||
result.left = result.top = result.right = result.bottom = 0;
|
result.left = result.top = result.right = result.bottom = 0;
|
||||||
|
@ -1313,6 +1324,7 @@ Clipper::Clipper(int initOptions) : ClipperBase() //constructor
|
||||||
{
|
{
|
||||||
m_ActiveEdges = 0;
|
m_ActiveEdges = 0;
|
||||||
m_SortedEdges = 0;
|
m_SortedEdges = 0;
|
||||||
|
m_ExecuteLocked = false;
|
||||||
m_UseFullRange = false;
|
m_UseFullRange = false;
|
||||||
m_ReverseOutput = ((initOptions & ioReverseSolution) != 0);
|
m_ReverseOutput = ((initOptions & ioReverseSolution) != 0);
|
||||||
m_StrictSimple = ((initOptions & ioStrictlySimple) != 0);
|
m_StrictSimple = ((initOptions & ioStrictlySimple) != 0);
|
||||||
|
@ -1341,12 +1353,12 @@ void Clipper::ZFillFunction(ZFillCallback zFillFunc)
|
||||||
void Clipper::Reset()
|
void Clipper::Reset()
|
||||||
{
|
{
|
||||||
ClipperBase::Reset();
|
ClipperBase::Reset();
|
||||||
m_Scanbeam = std::priority_queue<cInt>();
|
m_Scanbeam = ScanbeamList();
|
||||||
m_Maxima.clear();
|
m_Maxima = MaximaList();
|
||||||
m_ActiveEdges = 0;
|
m_ActiveEdges = 0;
|
||||||
m_SortedEdges = 0;
|
m_SortedEdges = 0;
|
||||||
for (auto lm = m_MinimaList.rbegin(); lm != m_MinimaList.rend(); ++lm)
|
for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm)
|
||||||
m_Scanbeam.push(lm->Y);
|
InsertScanbeam(lm->Y);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1365,8 +1377,10 @@ bool Clipper::Execute(ClipType clipType, PolyTree &polytree, PolyFillType fillTy
|
||||||
bool Clipper::Execute(ClipType clipType, Paths &solution,
|
bool Clipper::Execute(ClipType clipType, Paths &solution,
|
||||||
PolyFillType subjFillType, PolyFillType clipFillType)
|
PolyFillType subjFillType, PolyFillType clipFillType)
|
||||||
{
|
{
|
||||||
|
if( m_ExecuteLocked ) return false;
|
||||||
if (m_HasOpenPaths)
|
if (m_HasOpenPaths)
|
||||||
throw clipperException("Error: PolyTree struct is needed for open path clipping.");
|
throw clipperException("Error: PolyTree struct is needed for open path clipping.");
|
||||||
|
m_ExecuteLocked = true;
|
||||||
solution.resize(0);
|
solution.resize(0);
|
||||||
m_SubjFillType = subjFillType;
|
m_SubjFillType = subjFillType;
|
||||||
m_ClipFillType = clipFillType;
|
m_ClipFillType = clipFillType;
|
||||||
|
@ -1375,6 +1389,7 @@ bool Clipper::Execute(ClipType clipType, Paths &solution,
|
||||||
bool succeeded = ExecuteInternal();
|
bool succeeded = ExecuteInternal();
|
||||||
if (succeeded) BuildResult(solution);
|
if (succeeded) BuildResult(solution);
|
||||||
DisposeAllOutRecs();
|
DisposeAllOutRecs();
|
||||||
|
m_ExecuteLocked = false;
|
||||||
return succeeded;
|
return succeeded;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -1382,6 +1397,8 @@ bool Clipper::Execute(ClipType clipType, Paths &solution,
|
||||||
bool Clipper::Execute(ClipType clipType, PolyTree& polytree,
|
bool Clipper::Execute(ClipType clipType, PolyTree& polytree,
|
||||||
PolyFillType subjFillType, PolyFillType clipFillType)
|
PolyFillType subjFillType, PolyFillType clipFillType)
|
||||||
{
|
{
|
||||||
|
if( m_ExecuteLocked ) return false;
|
||||||
|
m_ExecuteLocked = true;
|
||||||
m_SubjFillType = subjFillType;
|
m_SubjFillType = subjFillType;
|
||||||
m_ClipFillType = clipFillType;
|
m_ClipFillType = clipFillType;
|
||||||
m_ClipType = clipType;
|
m_ClipType = clipType;
|
||||||
|
@ -1389,6 +1406,7 @@ bool Clipper::Execute(ClipType clipType, PolyTree& polytree,
|
||||||
bool succeeded = ExecuteInternal();
|
bool succeeded = ExecuteInternal();
|
||||||
if (succeeded) BuildResult2(polytree);
|
if (succeeded) BuildResult2(polytree);
|
||||||
DisposeAllOutRecs();
|
DisposeAllOutRecs();
|
||||||
|
m_ExecuteLocked = false;
|
||||||
return succeeded;
|
return succeeded;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -1413,19 +1431,19 @@ bool Clipper::ExecuteInternal()
|
||||||
bool succeeded = true;
|
bool succeeded = true;
|
||||||
try {
|
try {
|
||||||
Reset();
|
Reset();
|
||||||
if (m_MinimaList.empty()) return true;
|
if (m_CurrentLM == m_MinimaList.end()) return true;
|
||||||
cInt botY = PopScanbeam();
|
cInt botY = PopScanbeam();
|
||||||
do {
|
do {
|
||||||
InsertLocalMinimaIntoAEL(botY);
|
InsertLocalMinimaIntoAEL(botY);
|
||||||
ProcessHorizontals();
|
ProcessHorizontals();
|
||||||
m_GhostJoins.clear();
|
ClearGhostJoins();
|
||||||
if (m_Scanbeam.empty()) break;
|
if (m_Scanbeam.empty()) break;
|
||||||
cInt topY = PopScanbeam();
|
cInt topY = PopScanbeam();
|
||||||
succeeded = ProcessIntersections(topY);
|
succeeded = ProcessIntersections(topY);
|
||||||
if (!succeeded) break;
|
if (!succeeded) break;
|
||||||
ProcessEdgesAtTopOfScanbeam(topY);
|
ProcessEdgesAtTopOfScanbeam(topY);
|
||||||
botY = topY;
|
botY = topY;
|
||||||
} while (!m_Scanbeam.empty() || !m_MinimaList.empty());
|
} while (!m_Scanbeam.empty() || m_CurrentLM != m_MinimaList.end());
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -1459,12 +1477,18 @@ bool Clipper::ExecuteInternal()
|
||||||
if (m_StrictSimple) DoSimplePolygons();
|
if (m_StrictSimple) DoSimplePolygons();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Joins.clear();
|
ClearJoins();
|
||||||
m_GhostJoins.clear();
|
ClearGhostJoins();
|
||||||
return succeeded;
|
return succeeded;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Clipper::InsertScanbeam(const cInt Y)
|
||||||
|
{
|
||||||
|
m_Scanbeam.push(Y);
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
cInt Clipper::PopScanbeam()
|
cInt Clipper::PopScanbeam()
|
||||||
{
|
{
|
||||||
const cInt Y = m_Scanbeam.top();
|
const cInt Y = m_Scanbeam.top();
|
||||||
|
@ -1735,7 +1759,7 @@ OutPt* Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt)
|
||||||
(e->WindDelta != 0) && (prevE->WindDelta != 0))
|
(e->WindDelta != 0) && (prevE->WindDelta != 0))
|
||||||
{
|
{
|
||||||
OutPt* outPt = AddOutPt(prevE, Pt);
|
OutPt* outPt = AddOutPt(prevE, Pt);
|
||||||
m_Joins.emplace_back(Join(result, outPt, e->Top));
|
AddJoin(result, outPt, e->Top);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1788,17 +1812,51 @@ void Clipper::CopyAELToSEL()
|
||||||
e = e->NextInAEL;
|
e = e->NextInAEL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Clipper::AddJoin(OutPt *op1, OutPt *op2, const IntPoint &OffPt)
|
||||||
|
{
|
||||||
|
Join* j = new Join;
|
||||||
|
j->OutPt1 = op1;
|
||||||
|
j->OutPt2 = op2;
|
||||||
|
j->OffPt = OffPt;
|
||||||
|
m_Joins.push_back(j);
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Clipper::ClearJoins()
|
||||||
|
{
|
||||||
|
for (JoinList::size_type i = 0; i < m_Joins.size(); i++)
|
||||||
|
delete m_Joins[i];
|
||||||
|
m_Joins.resize(0);
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Clipper::ClearGhostJoins()
|
||||||
|
{
|
||||||
|
for (JoinList::size_type i = 0; i < m_GhostJoins.size(); i++)
|
||||||
|
delete m_GhostJoins[i];
|
||||||
|
m_GhostJoins.resize(0);
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Clipper::AddGhostJoin(OutPt *op, const IntPoint &OffPt)
|
||||||
|
{
|
||||||
|
Join* j = new Join;
|
||||||
|
j->OutPt1 = op;
|
||||||
|
j->OutPt2 = 0;
|
||||||
|
j->OffPt = OffPt;
|
||||||
|
m_GhostJoins.push_back(j);
|
||||||
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
|
void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
|
||||||
{
|
{
|
||||||
while (!m_MinimaList.empty() && m_MinimaList.back().Y == botY)
|
while (m_CurrentLM != m_MinimaList.end() && (m_CurrentLM->Y == botY))
|
||||||
{
|
{
|
||||||
TEdge* lb = m_MinimaList.back().LeftBound;
|
TEdge* lb = m_CurrentLM->LeftBound;
|
||||||
TEdge* rb = m_MinimaList.back().RightBound;
|
TEdge* rb = m_CurrentLM->RightBound;
|
||||||
m_MinimaList.pop_back();
|
PopLocalMinima();
|
||||||
|
|
||||||
OutPt *Op1 = 0;
|
OutPt *Op1 = 0;
|
||||||
if (!lb)
|
if (!lb)
|
||||||
{
|
{
|
||||||
|
@ -1814,7 +1872,7 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
|
||||||
SetWindingCount(*lb);
|
SetWindingCount(*lb);
|
||||||
if (IsContributing(*lb))
|
if (IsContributing(*lb))
|
||||||
Op1 = AddOutPt(lb, lb->Bot);
|
Op1 = AddOutPt(lb, lb->Bot);
|
||||||
m_Scanbeam.push(lb->Top.Y);
|
InsertScanbeam(lb->Top.Y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1825,13 +1883,13 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
|
||||||
rb->WindCnt2 = lb->WindCnt2;
|
rb->WindCnt2 = lb->WindCnt2;
|
||||||
if (IsContributing(*lb))
|
if (IsContributing(*lb))
|
||||||
Op1 = AddLocalMinPoly(lb, rb, lb->Bot);
|
Op1 = AddLocalMinPoly(lb, rb, lb->Bot);
|
||||||
m_Scanbeam.push(lb->Top.Y);
|
InsertScanbeam(lb->Top.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rb)
|
if (rb)
|
||||||
{
|
{
|
||||||
if(IsHorizontal(*rb)) AddEdgeToSEL(rb);
|
if(IsHorizontal(*rb)) AddEdgeToSEL(rb);
|
||||||
else m_Scanbeam.push(rb->Top.Y);
|
else InsertScanbeam( rb->Top.Y );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lb || !rb) continue;
|
if (!lb || !rb) continue;
|
||||||
|
@ -1840,11 +1898,14 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
|
||||||
if (Op1 && IsHorizontal(*rb) &&
|
if (Op1 && IsHorizontal(*rb) &&
|
||||||
m_GhostJoins.size() > 0 && (rb->WindDelta != 0))
|
m_GhostJoins.size() > 0 && (rb->WindDelta != 0))
|
||||||
{
|
{
|
||||||
for (Join &jr : m_GhostJoins)
|
for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i)
|
||||||
|
{
|
||||||
|
Join* jr = m_GhostJoins[i];
|
||||||
//if the horizontal Rb and a 'ghost' horizontal overlap, then convert
|
//if the horizontal Rb and a 'ghost' horizontal overlap, then convert
|
||||||
//the 'ghost' join to a real join ready for later ...
|
//the 'ghost' join to a real join ready for later ...
|
||||||
if (HorzSegmentsOverlap(jr.OutPt1->Pt.X, jr.OffPt.X, rb->Bot.X, rb->Top.X))
|
if (HorzSegmentsOverlap(jr->OutPt1->Pt.X, jr->OffPt.X, rb->Bot.X, rb->Top.X))
|
||||||
m_Joins.emplace_back(Join(jr.OutPt1, Op1, jr.OffPt));
|
AddJoin(jr->OutPt1, Op1, jr->OffPt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lb->OutIdx >= 0 && lb->PrevInAEL &&
|
if (lb->OutIdx >= 0 && lb->PrevInAEL &&
|
||||||
|
@ -1854,7 +1915,7 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
|
||||||
(lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0))
|
(lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0))
|
||||||
{
|
{
|
||||||
OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot);
|
OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot);
|
||||||
m_Joins.emplace_back(Join(Op1, Op2, lb->Top));
|
AddJoin(Op1, Op2, lb->Top);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lb->NextInAEL != rb)
|
if(lb->NextInAEL != rb)
|
||||||
|
@ -1865,7 +1926,7 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
|
||||||
(rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0))
|
(rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0))
|
||||||
{
|
{
|
||||||
OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot);
|
OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot);
|
||||||
m_Joins.emplace_back(Join(Op1, Op2, rb->Top));
|
AddJoin(Op1, Op2, rb->Top);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEdge* e = lb->NextInAEL;
|
TEdge* e = lb->NextInAEL;
|
||||||
|
@ -2600,11 +2661,11 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
|
||||||
horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
|
horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
|
||||||
{
|
{
|
||||||
OutPt* op2 = GetLastOutPt(eNextHorz);
|
OutPt* op2 = GetLastOutPt(eNextHorz);
|
||||||
m_Joins.emplace_back(Join(op2, op1, eNextHorz->Top));
|
AddJoin(op2, op1, eNextHorz->Top);
|
||||||
}
|
}
|
||||||
eNextHorz = eNextHorz->NextInSEL;
|
eNextHorz = eNextHorz->NextInSEL;
|
||||||
}
|
}
|
||||||
m_GhostJoins.emplace_back(Join(op1, 0, horzEdge->Bot));
|
AddGhostJoin(op1, horzEdge->Bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
//OK, so far we're still in range of the horizontal Edge but make sure
|
//OK, so far we're still in range of the horizontal Edge but make sure
|
||||||
|
@ -2653,11 +2714,11 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
|
||||||
horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
|
horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
|
||||||
{
|
{
|
||||||
OutPt* op2 = GetLastOutPt(eNextHorz);
|
OutPt* op2 = GetLastOutPt(eNextHorz);
|
||||||
m_Joins.emplace_back(Join(op2, op1, eNextHorz->Top));
|
AddJoin(op2, op1, eNextHorz->Top);
|
||||||
}
|
}
|
||||||
eNextHorz = eNextHorz->NextInSEL;
|
eNextHorz = eNextHorz->NextInSEL;
|
||||||
}
|
}
|
||||||
m_GhostJoins.emplace_back(Join(op1, 0, horzEdge->Top));
|
AddGhostJoin(op1, horzEdge->Top);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (horzEdge->NextInLML)
|
if (horzEdge->NextInLML)
|
||||||
|
@ -2676,7 +2737,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
|
||||||
SlopesEqual(*horzEdge, *ePrev, m_UseFullRange)))
|
SlopesEqual(*horzEdge, *ePrev, m_UseFullRange)))
|
||||||
{
|
{
|
||||||
OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot);
|
OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot);
|
||||||
m_Joins.emplace_back(Join(op1, op2, horzEdge->Top));
|
AddJoin(op1, op2, horzEdge->Top);
|
||||||
}
|
}
|
||||||
else if (eNext && eNext->Curr.X == horzEdge->Bot.X &&
|
else if (eNext && eNext->Curr.X == horzEdge->Bot.X &&
|
||||||
eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 &&
|
eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 &&
|
||||||
|
@ -2684,7 +2745,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
|
||||||
SlopesEqual(*horzEdge, *eNext, m_UseFullRange))
|
SlopesEqual(*horzEdge, *eNext, m_UseFullRange))
|
||||||
{
|
{
|
||||||
OutPt* op2 = AddOutPt(eNext, horzEdge->Bot);
|
OutPt* op2 = AddOutPt(eNext, horzEdge->Bot);
|
||||||
m_Joins.emplace_back(Join(op1, op2, horzEdge->Top));
|
AddJoin(op1, op2, horzEdge->Top);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2717,8 +2778,7 @@ void Clipper::UpdateEdgeIntoAEL(TEdge *&e)
|
||||||
e->Curr = e->Bot;
|
e->Curr = e->Bot;
|
||||||
e->PrevInAEL = AelPrev;
|
e->PrevInAEL = AelPrev;
|
||||||
e->NextInAEL = AelNext;
|
e->NextInAEL = AelNext;
|
||||||
if (!IsHorizontal(*e))
|
if (!IsHorizontal(*e)) InsertScanbeam(e->Top.Y);
|
||||||
m_Scanbeam.push(e->Top.Y);
|
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -2815,6 +2875,12 @@ void Clipper::ProcessIntersectList()
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool IntersectListSort(IntersectNode* node1, IntersectNode* node2)
|
||||||
|
{
|
||||||
|
return node2->Pt.Y < node1->Pt.Y;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline bool EdgesAdjacent(const IntersectNode &inode)
|
inline bool EdgesAdjacent(const IntersectNode &inode)
|
||||||
{
|
{
|
||||||
return (inode.Edge1->NextInSEL == inode.Edge2) ||
|
return (inode.Edge1->NextInSEL == inode.Edge2) ||
|
||||||
|
@ -2828,8 +2894,7 @@ bool Clipper::FixupIntersectionOrder()
|
||||||
//Now it's crucial that intersections are made only between adjacent edges,
|
//Now it's crucial that intersections are made only between adjacent edges,
|
||||||
//so to ensure this the order of intersections may need adjusting ...
|
//so to ensure this the order of intersections may need adjusting ...
|
||||||
CopyAELToSEL();
|
CopyAELToSEL();
|
||||||
std::sort(m_IntersectList.begin(), m_IntersectList.end(), [](IntersectNode* node1, IntersectNode* node2) { return node2->Pt.Y < node1->Pt.Y; });
|
std::sort(m_IntersectList.begin(), m_IntersectList.end(), IntersectListSort);
|
||||||
|
|
||||||
size_t cnt = m_IntersectList.size();
|
size_t cnt = m_IntersectList.size();
|
||||||
for (size_t i = 0; i < cnt; ++i)
|
for (size_t i = 0; i < cnt; ++i)
|
||||||
{
|
{
|
||||||
|
@ -2951,7 +3016,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
|
||||||
#endif
|
#endif
|
||||||
OutPt* op = AddOutPt(ePrev, pt);
|
OutPt* op = AddOutPt(ePrev, pt);
|
||||||
OutPt* op2 = AddOutPt(e, pt);
|
OutPt* op2 = AddOutPt(e, pt);
|
||||||
m_Joins.emplace_back(Join(op, op2, pt)); //StrictlySimple (type-3) join
|
AddJoin(op, op2, pt); //StrictlySimple (type-3) join
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2985,7 +3050,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
|
||||||
(e->WindDelta != 0) && (ePrev->WindDelta != 0))
|
(e->WindDelta != 0) && (ePrev->WindDelta != 0))
|
||||||
{
|
{
|
||||||
OutPt* op2 = AddOutPt(ePrev, e->Bot);
|
OutPt* op2 = AddOutPt(ePrev, e->Bot);
|
||||||
m_Joins.emplace_back(Join(op, op2, e->Top));
|
AddJoin(op, op2, e->Top);
|
||||||
}
|
}
|
||||||
else if (eNext && eNext->Curr.X == e->Bot.X &&
|
else if (eNext && eNext->Curr.X == e->Bot.X &&
|
||||||
eNext->Curr.Y == e->Bot.Y && op &&
|
eNext->Curr.Y == e->Bot.Y && op &&
|
||||||
|
@ -2994,7 +3059,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
|
||||||
(e->WindDelta != 0) && (eNext->WindDelta != 0))
|
(e->WindDelta != 0) && (eNext->WindDelta != 0))
|
||||||
{
|
{
|
||||||
OutPt* op2 = AddOutPt(eNext, e->Bot);
|
OutPt* op2 = AddOutPt(eNext, e->Bot);
|
||||||
m_Joins.emplace_back(Join(op, op2, e->Top));
|
AddJoin(op, op2, e->Top);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e = e->NextInAEL;
|
e = e->NextInAEL;
|
||||||
|
@ -3541,10 +3606,12 @@ void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) const
|
||||||
|
|
||||||
void Clipper::JoinCommonEdges()
|
void Clipper::JoinCommonEdges()
|
||||||
{
|
{
|
||||||
for (Join &join : m_Joins)
|
for (JoinList::size_type i = 0; i < m_Joins.size(); i++)
|
||||||
{
|
{
|
||||||
OutRec *outRec1 = GetOutRec(join.OutPt1->Idx);
|
Join* join = m_Joins[i];
|
||||||
OutRec *outRec2 = GetOutRec(join.OutPt2->Idx);
|
|
||||||
|
OutRec *outRec1 = GetOutRec(join->OutPt1->Idx);
|
||||||
|
OutRec *outRec2 = GetOutRec(join->OutPt2->Idx);
|
||||||
|
|
||||||
if (!outRec1->Pts || !outRec2->Pts) continue;
|
if (!outRec1->Pts || !outRec2->Pts) continue;
|
||||||
if (outRec1->IsOpen || outRec2->IsOpen) continue;
|
if (outRec1->IsOpen || outRec2->IsOpen) continue;
|
||||||
|
@ -3557,16 +3624,16 @@ void Clipper::JoinCommonEdges()
|
||||||
else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1;
|
else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1;
|
||||||
else holeStateRec = GetLowermostRec(outRec1, outRec2);
|
else holeStateRec = GetLowermostRec(outRec1, outRec2);
|
||||||
|
|
||||||
if (!JoinPoints(&join, outRec1, outRec2)) continue;
|
if (!JoinPoints(join, outRec1, outRec2)) continue;
|
||||||
|
|
||||||
if (outRec1 == outRec2)
|
if (outRec1 == outRec2)
|
||||||
{
|
{
|
||||||
//instead of joining two polygons, we've just created a new one by
|
//instead of joining two polygons, we've just created a new one by
|
||||||
//splitting one polygon into two.
|
//splitting one polygon into two.
|
||||||
outRec1->Pts = join.OutPt1;
|
outRec1->Pts = join->OutPt1;
|
||||||
outRec1->BottomPt = 0;
|
outRec1->BottomPt = 0;
|
||||||
outRec2 = CreateOutRec();
|
outRec2 = CreateOutRec();
|
||||||
outRec2->Pts = join.OutPt2;
|
outRec2->Pts = join->OutPt2;
|
||||||
|
|
||||||
//update all OutRec2.Pts Idx's ...
|
//update all OutRec2.Pts Idx's ...
|
||||||
UpdateOutPtIdxs(*outRec2);
|
UpdateOutPtIdxs(*outRec2);
|
||||||
|
@ -3579,7 +3646,7 @@ void Clipper::JoinCommonEdges()
|
||||||
OutRec* oRec = m_PolyOuts[j];
|
OutRec* oRec = m_PolyOuts[j];
|
||||||
if (!oRec->Pts || ParseFirstLeft(oRec->FirstLeft) != outRec1 ||
|
if (!oRec->Pts || ParseFirstLeft(oRec->FirstLeft) != outRec1 ||
|
||||||
oRec->IsHole == outRec1->IsHole) continue;
|
oRec->IsHole == outRec1->IsHole) continue;
|
||||||
if (Poly2ContainsPoly1(oRec->Pts, join.OutPt2))
|
if (Poly2ContainsPoly1(oRec->Pts, join->OutPt2))
|
||||||
oRec->FirstLeft = outRec2;
|
oRec->FirstLeft = outRec2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,17 +221,11 @@ struct IntersectNode;
|
||||||
struct LocalMinimum;
|
struct LocalMinimum;
|
||||||
struct OutPt;
|
struct OutPt;
|
||||||
struct OutRec;
|
struct OutRec;
|
||||||
struct Join {
|
struct Join;
|
||||||
Join(OutPt *OutPt1, OutPt *OutPt2, IntPoint OffPt) :
|
|
||||||
OutPt1(OutPt1), OutPt2(OutPt2), OffPt(OffPt) {}
|
|
||||||
OutPt *OutPt1;
|
|
||||||
OutPt *OutPt2;
|
|
||||||
IntPoint OffPt;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector < OutRec* > PolyOutList;
|
typedef std::vector < OutRec* > PolyOutList;
|
||||||
typedef std::vector < TEdge* > EdgeList;
|
typedef std::vector < TEdge* > EdgeList;
|
||||||
typedef std::vector < Join > JoinList;
|
typedef std::vector < Join* > JoinList;
|
||||||
typedef std::vector < IntersectNode* > IntersectList;
|
typedef std::vector < IntersectNode* > IntersectList;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -248,11 +242,10 @@ public:
|
||||||
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
|
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
|
||||||
virtual void Clear();
|
virtual void Clear();
|
||||||
IntRect GetBounds();
|
IntRect GetBounds();
|
||||||
// By default, when three or more vertices are collinear in input polygons (subject or clip), the Clipper object removes the 'inner' vertices before clipping.
|
|
||||||
// When enabled the PreserveCollinear property prevents this default behavior to allow these inner vertices to appear in the solution.
|
|
||||||
bool PreserveCollinear() const {return m_PreserveCollinear;};
|
bool PreserveCollinear() const {return m_PreserveCollinear;};
|
||||||
void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
|
void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
|
||||||
protected:
|
protected:
|
||||||
|
void DisposeLocalMinimaList();
|
||||||
TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
|
TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
|
||||||
void PopLocalMinima();
|
void PopLocalMinima();
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
@ -260,17 +253,13 @@ protected:
|
||||||
TEdge* DescendToMin(TEdge *&E);
|
TEdge* DescendToMin(TEdge *&E);
|
||||||
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
|
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
|
||||||
|
|
||||||
// Local minima (Y, left edge, right edge) sorted by ascending Y.
|
typedef std::vector<LocalMinimum> MinimaList;
|
||||||
std::vector<LocalMinimum> m_MinimaList;
|
MinimaList::iterator m_CurrentLM;
|
||||||
|
MinimaList m_MinimaList;
|
||||||
|
|
||||||
// True if the input polygons have abs values higher than loRange, but lower than hiRange.
|
|
||||||
// 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.
|
|
||||||
EdgeList m_edges;
|
EdgeList m_edges;
|
||||||
// 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?
|
|
||||||
bool m_HasOpenPaths;
|
bool m_HasOpenPaths;
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -311,16 +300,16 @@ private:
|
||||||
JoinList m_GhostJoins;
|
JoinList m_GhostJoins;
|
||||||
IntersectList m_IntersectList;
|
IntersectList m_IntersectList;
|
||||||
ClipType m_ClipType;
|
ClipType m_ClipType;
|
||||||
// A priority queue (a binary heap) of Y coordinates.
|
typedef std::priority_queue<cInt> ScanbeamList;
|
||||||
std::priority_queue<cInt> m_Scanbeam;
|
ScanbeamList m_Scanbeam;
|
||||||
typedef std::list<cInt> MaximaList;
|
typedef std::list<cInt> MaximaList;
|
||||||
MaximaList m_Maxima;
|
MaximaList m_Maxima;
|
||||||
TEdge *m_ActiveEdges;
|
TEdge *m_ActiveEdges;
|
||||||
TEdge *m_SortedEdges;
|
TEdge *m_SortedEdges;
|
||||||
|
bool m_ExecuteLocked;
|
||||||
PolyFillType m_ClipFillType;
|
PolyFillType m_ClipFillType;
|
||||||
PolyFillType m_SubjFillType;
|
PolyFillType m_SubjFillType;
|
||||||
bool m_ReverseOutput;
|
bool m_ReverseOutput;
|
||||||
// Does the result go to a PolyTree or Paths?
|
|
||||||
bool m_UsingPolyTree;
|
bool m_UsingPolyTree;
|
||||||
bool m_StrictSimple;
|
bool m_StrictSimple;
|
||||||
#ifdef use_xyz
|
#ifdef use_xyz
|
||||||
|
@ -329,6 +318,7 @@ private:
|
||||||
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;
|
bool IsEvenOddAltFillType(const TEdge& edge) const;
|
||||||
|
void InsertScanbeam(const cInt Y);
|
||||||
cInt PopScanbeam();
|
cInt PopScanbeam();
|
||||||
void InsertLocalMinimaIntoAEL(const cInt botY);
|
void InsertLocalMinimaIntoAEL(const cInt botY);
|
||||||
void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
|
void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
|
||||||
|
@ -365,8 +355,13 @@ private:
|
||||||
bool FixupIntersectionOrder();
|
bool FixupIntersectionOrder();
|
||||||
void FixupOutPolygon(OutRec &outrec);
|
void FixupOutPolygon(OutRec &outrec);
|
||||||
void FixupOutPolyline(OutRec &outrec);
|
void FixupOutPolyline(OutRec &outrec);
|
||||||
|
bool IsHole(TEdge *e);
|
||||||
bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
|
bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
|
||||||
void FixHoleLinkage(OutRec &outrec);
|
void FixHoleLinkage(OutRec &outrec);
|
||||||
|
void AddJoin(OutPt *op1, OutPt *op2, const IntPoint &offPt);
|
||||||
|
void ClearJoins();
|
||||||
|
void ClearGhostJoins();
|
||||||
|
void AddGhostJoin(OutPt *op, const IntPoint &offPt);
|
||||||
bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
|
bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
|
||||||
void JoinCommonEdges();
|
void JoinCommonEdges();
|
||||||
void DoSimplePolygons();
|
void DoSimplePolygons();
|
||||||
|
|
Loading…
Add table
Reference in a new issue