mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-10 03:29:08 +08:00
Upgrade Clipper to 6.2.1
This commit is contained in:
parent
67f1cdf76f
commit
a78be203aa
@ -1,8 +1,8 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* *
|
* *
|
||||||
* Author : Angus Johnson *
|
* Author : Angus Johnson *
|
||||||
* Version : 6.1.5 *
|
* Version : 6.2.1 *
|
||||||
* Date : 22 May 2014 *
|
* Date : 31 October 2014 *
|
||||||
* Website : http://www.angusj.com *
|
* Website : http://www.angusj.com *
|
||||||
* Copyright : Angus Johnson 2010-2014 *
|
* Copyright : Angus Johnson 2010-2014 *
|
||||||
* *
|
* *
|
||||||
@ -90,11 +90,10 @@ struct IntersectNode {
|
|||||||
IntPoint Pt;
|
IntPoint Pt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LocalMinima {
|
struct LocalMinimum {
|
||||||
cInt Y;
|
cInt Y;
|
||||||
TEdge *LeftBound;
|
TEdge *LeftBound;
|
||||||
TEdge *RightBound;
|
TEdge *RightBound;
|
||||||
LocalMinima *Next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OutPt;
|
struct OutPt;
|
||||||
@ -122,6 +121,14 @@ struct Join {
|
|||||||
IntPoint OffPt;
|
IntPoint OffPt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LocMinSorter
|
||||||
|
{
|
||||||
|
inline bool operator()(const LocalMinimum& locMin1, const LocalMinimum& locMin2)
|
||||||
|
{
|
||||||
|
return locMin2.Y < locMin1.Y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -161,7 +168,10 @@ PolyNode* PolyTree::GetFirst() const
|
|||||||
|
|
||||||
int PolyTree::Total() const
|
int PolyTree::Total() const
|
||||||
{
|
{
|
||||||
return (int)AllNodes.size();
|
int result = (int)AllNodes.size();
|
||||||
|
//with negative offsets, ignore the hidden outer polygon ...
|
||||||
|
if (result > 0 && Childs[0] != AllNodes[0]) result--;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -320,9 +330,21 @@ class Int128
|
|||||||
Int128 operator-() const //unary negation
|
Int128 operator-() const //unary negation
|
||||||
{
|
{
|
||||||
if (lo == 0)
|
if (lo == 0)
|
||||||
return Int128(-hi,0);
|
return Int128(-hi, 0);
|
||||||
else
|
else
|
||||||
return Int128(~hi,~lo +1);
|
return Int128(~hi, ~lo + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator double() const
|
||||||
|
{
|
||||||
|
const double shift64 = 18446744073709551616.0; //2^64
|
||||||
|
if (hi < 0)
|
||||||
|
{
|
||||||
|
if (lo == 0) return (double)hi * shift64;
|
||||||
|
else return -(double)(~lo + ~hi * shift64);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (double)(lo + hi * shift64);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -506,8 +528,9 @@ bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2)
|
|||||||
OutPt* op = OutPt1;
|
OutPt* op = OutPt1;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
//nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon
|
||||||
int res = PointInPolygon(op->Pt, OutPt2);
|
int res = PointInPolygon(op->Pt, OutPt2);
|
||||||
if (res >= 0) return res != 0;
|
if (res >= 0) return res > 0;
|
||||||
op = op->Next;
|
op = op->Next;
|
||||||
}
|
}
|
||||||
while (op != OutPt1);
|
while (op != OutPt1);
|
||||||
@ -854,8 +877,7 @@ bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b)
|
|||||||
|
|
||||||
ClipperBase::ClipperBase() //constructor
|
ClipperBase::ClipperBase() //constructor
|
||||||
{
|
{
|
||||||
m_MinimaList = 0;
|
m_CurrentLM = m_MinimaList.begin(); //begin() == end() here
|
||||||
m_CurrentLM = 0;
|
|
||||||
m_UseFullRange = false;
|
m_UseFullRange = false;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -898,124 +920,129 @@ TEdge* FindNextLocMin(TEdge* E)
|
|||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
|
TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
|
||||||
{
|
{
|
||||||
TEdge *EStart = E, *Result = E;
|
TEdge *Result = E;
|
||||||
TEdge *Horz = 0;
|
TEdge *Horz = 0;
|
||||||
cInt StartX;
|
|
||||||
if (IsHorizontal(*E))
|
|
||||||
{
|
|
||||||
//first we need to be careful here with open paths because this
|
|
||||||
//may not be a true local minima (ie may be following a skip edge).
|
|
||||||
//also, watch for adjacent horz edges to start heading left
|
|
||||||
//before finishing right ...
|
|
||||||
if (IsClockwise)
|
|
||||||
{
|
|
||||||
if (E->Prev->Bot.Y == E->Bot.Y) StartX = E->Prev->Bot.X;
|
|
||||||
else StartX = E->Prev->Top.X;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (E->Next->Bot.Y == E->Bot.Y) StartX = E->Next->Bot.X;
|
|
||||||
else StartX = E->Next->Top.X;
|
|
||||||
}
|
|
||||||
if (E->Bot.X != StartX) ReverseHorizontal(*E);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Result->OutIdx != Skip)
|
|
||||||
{
|
|
||||||
if (IsClockwise)
|
|
||||||
{
|
|
||||||
while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip)
|
|
||||||
Result = Result->Next;
|
|
||||||
if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip)
|
|
||||||
{
|
|
||||||
//nb: at the top of a bound, horizontals are added to the bound
|
|
||||||
//only when the preceding edge attaches to the horizontal's left vertex
|
|
||||||
//unless a Skip edge is encountered when that becomes the top divide
|
|
||||||
Horz = Result;
|
|
||||||
while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev;
|
|
||||||
if (Horz->Prev->Top.X == Result->Next->Top.X)
|
|
||||||
{
|
|
||||||
if (!IsClockwise) Result = Horz->Prev;
|
|
||||||
}
|
|
||||||
else if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev;
|
|
||||||
}
|
|
||||||
while (E != Result)
|
|
||||||
{
|
|
||||||
E->NextInLML = E->Next;
|
|
||||||
if (IsHorizontal(*E) && E != EStart &&
|
|
||||||
E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
|
|
||||||
E = E->Next;
|
|
||||||
}
|
|
||||||
if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X)
|
|
||||||
ReverseHorizontal(*E);
|
|
||||||
Result = Result->Next; //move to the edge just beyond current bound
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip)
|
|
||||||
Result = Result->Prev;
|
|
||||||
if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip)
|
|
||||||
{
|
|
||||||
Horz = Result;
|
|
||||||
while (IsHorizontal(*Horz->Next)) Horz = Horz->Next;
|
|
||||||
if (Horz->Next->Top.X == Result->Prev->Top.X)
|
|
||||||
{
|
|
||||||
if (!IsClockwise) Result = Horz->Next;
|
|
||||||
}
|
|
||||||
else if (Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (E != Result)
|
if (E->OutIdx == Skip)
|
||||||
{
|
|
||||||
E->NextInLML = E->Prev;
|
|
||||||
if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X)
|
|
||||||
ReverseHorizontal(*E);
|
|
||||||
E = E->Prev;
|
|
||||||
}
|
|
||||||
if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X)
|
|
||||||
ReverseHorizontal(*E);
|
|
||||||
Result = Result->Prev; //move to the edge just beyond current bound
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Result->OutIdx == Skip)
|
|
||||||
{
|
{
|
||||||
//if edges still remain in the current bound beyond the skip edge then
|
//if edges still remain in the current bound beyond the skip edge then
|
||||||
//create another LocMin and call ProcessBound once more
|
//create another LocMin and call ProcessBound once more
|
||||||
E = Result;
|
if (NextIsForward)
|
||||||
if (IsClockwise)
|
|
||||||
{
|
{
|
||||||
while (E->Top.Y == E->Next->Bot.Y) E = E->Next;
|
while (E->Top.Y == E->Next->Bot.Y) E = E->Next;
|
||||||
//don't include top horizontals when parsing a bound a second time,
|
//don't include top horizontals when parsing a bound a second time,
|
||||||
//they will be contained in the opposite bound ...
|
//they will be contained in the opposite bound ...
|
||||||
while (E != Result && IsHorizontal(*E)) E = E->Prev;
|
while (E != Result && IsHorizontal(*E)) E = E->Prev;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev;
|
while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev;
|
||||||
while (E != Result && IsHorizontal(*E)) E = E->Next;
|
while (E != Result && IsHorizontal(*E)) E = E->Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E == Result)
|
if (E == Result)
|
||||||
{
|
{
|
||||||
if (IsClockwise) Result = E->Next;
|
if (NextIsForward) Result = E->Next;
|
||||||
else Result = E->Prev;
|
else Result = E->Prev;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
//there are more edges in the bound beyond result starting with E
|
//there are more edges in the bound beyond result starting with E
|
||||||
if (IsClockwise)
|
if (NextIsForward)
|
||||||
E = Result->Next;
|
E = Result->Next;
|
||||||
else
|
else
|
||||||
E = Result->Prev;
|
E = Result->Prev;
|
||||||
LocalMinima* locMin = new LocalMinima;
|
MinimaList::value_type locMin;
|
||||||
locMin->Next = 0;
|
locMin.Y = E->Bot.Y;
|
||||||
locMin->Y = E->Bot.Y;
|
locMin.LeftBound = 0;
|
||||||
locMin->LeftBound = 0;
|
locMin.RightBound = E;
|
||||||
locMin->RightBound = E;
|
E->WindDelta = 0;
|
||||||
locMin->RightBound->WindDelta = 0;
|
Result = ProcessBound(E, NextIsForward);
|
||||||
Result = ProcessBound(locMin->RightBound, IsClockwise);
|
m_MinimaList.push_back(locMin);
|
||||||
InsertLocalMinima(locMin);
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEdge *EStart;
|
||||||
|
|
||||||
|
if (IsHorizontal(*E))
|
||||||
|
{
|
||||||
|
//We need to be careful with open paths because this may not be a
|
||||||
|
//true local minima (ie E may be following a skip edge).
|
||||||
|
//Also, consecutive horz. edges may start heading left before going right.
|
||||||
|
if (NextIsForward)
|
||||||
|
EStart = E->Prev;
|
||||||
|
else
|
||||||
|
EStart = E->Next;
|
||||||
|
if (EStart->OutIdx != Skip)
|
||||||
|
{
|
||||||
|
if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge
|
||||||
|
{
|
||||||
|
if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X)
|
||||||
|
ReverseHorizontal(*E);
|
||||||
|
}
|
||||||
|
else if (EStart->Bot.X != E->Bot.X)
|
||||||
|
ReverseHorizontal(*E);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EStart = E;
|
||||||
|
if (NextIsForward)
|
||||||
|
{
|
||||||
|
while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip)
|
||||||
|
Result = Result->Next;
|
||||||
|
if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip)
|
||||||
|
{
|
||||||
|
//nb: at the top of a bound, horizontals are added to the bound
|
||||||
|
//only when the preceding edge attaches to the horizontal's left vertex
|
||||||
|
//unless a Skip edge is encountered when that becomes the top divide
|
||||||
|
Horz = Result;
|
||||||
|
while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev;
|
||||||
|
if (Horz->Prev->Top.X == Result->Next->Top.X)
|
||||||
|
{
|
||||||
|
if (!NextIsForward) Result = Horz->Prev;
|
||||||
|
}
|
||||||
|
else if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev;
|
||||||
|
}
|
||||||
|
while (E != Result)
|
||||||
|
{
|
||||||
|
E->NextInLML = E->Next;
|
||||||
|
if (IsHorizontal(*E) && E != EStart &&
|
||||||
|
E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
|
||||||
|
E = E->Next;
|
||||||
|
}
|
||||||
|
if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X)
|
||||||
|
ReverseHorizontal(*E);
|
||||||
|
Result = Result->Next; //move to the edge just beyond current bound
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip)
|
||||||
|
Result = Result->Prev;
|
||||||
|
if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip)
|
||||||
|
{
|
||||||
|
Horz = Result;
|
||||||
|
while (IsHorizontal(*Horz->Next)) Horz = Horz->Next;
|
||||||
|
if (Horz->Next->Top.X == Result->Prev->Top.X)
|
||||||
|
{
|
||||||
|
if (!NextIsForward) Result = Horz->Next;
|
||||||
|
}
|
||||||
|
else if (Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (E != Result)
|
||||||
|
{
|
||||||
|
E->NextInLML = E->Prev;
|
||||||
|
if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X)
|
||||||
|
ReverseHorizontal(*E);
|
||||||
|
E = E->Prev;
|
||||||
|
}
|
||||||
|
if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X)
|
||||||
|
ReverseHorizontal(*E);
|
||||||
|
Result = Result->Prev; //move to the edge just beyond current bound
|
||||||
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1129,26 +1156,25 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
|||||||
}
|
}
|
||||||
E->Prev->OutIdx = Skip;
|
E->Prev->OutIdx = Skip;
|
||||||
if (E->Prev->Bot.X < E->Prev->Top.X) ReverseHorizontal(*E->Prev);
|
if (E->Prev->Bot.X < E->Prev->Top.X) ReverseHorizontal(*E->Prev);
|
||||||
LocalMinima* locMin = new LocalMinima();
|
MinimaList::value_type locMin;
|
||||||
locMin->Next = 0;
|
locMin.Y = E->Bot.Y;
|
||||||
locMin->Y = E->Bot.Y;
|
locMin.LeftBound = 0;
|
||||||
locMin->LeftBound = 0;
|
locMin.RightBound = E;
|
||||||
locMin->RightBound = E;
|
locMin.RightBound->Side = esRight;
|
||||||
locMin->RightBound->Side = esRight;
|
locMin.RightBound->WindDelta = 0;
|
||||||
locMin->RightBound->WindDelta = 0;
|
|
||||||
while (E->Next->OutIdx != Skip)
|
while (E->Next->OutIdx != Skip)
|
||||||
{
|
{
|
||||||
E->NextInLML = E->Next;
|
E->NextInLML = E->Next;
|
||||||
if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
|
if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
|
||||||
E = E->Next;
|
E = E->Next;
|
||||||
}
|
}
|
||||||
InsertLocalMinima(locMin);
|
m_MinimaList.push_back(locMin);
|
||||||
m_edges.push_back(edges);
|
m_edges.push_back(edges);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_edges.push_back(edges);
|
m_edges.push_back(edges);
|
||||||
bool clockwise;
|
bool leftBoundIsForward;
|
||||||
TEdge* EMin = 0;
|
TEdge* EMin = 0;
|
||||||
|
|
||||||
//workaround to avoid an endless loop in the while loop below when
|
//workaround to avoid an endless loop in the while loop below when
|
||||||
@ -1163,38 +1189,40 @@ 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 ...
|
||||||
LocalMinima* locMin = new LocalMinima;
|
MinimaList::value_type locMin;
|
||||||
locMin->Next = 0;
|
locMin.Y = E->Bot.Y;
|
||||||
locMin->Y = E->Bot.Y;
|
|
||||||
if (E->Dx < E->Prev->Dx)
|
if (E->Dx < E->Prev->Dx)
|
||||||
{
|
{
|
||||||
locMin->LeftBound = E->Prev;
|
locMin.LeftBound = E->Prev;
|
||||||
locMin->RightBound = E;
|
locMin.RightBound = E;
|
||||||
clockwise = false; //Q.nextInLML = Q.prev
|
leftBoundIsForward = false; //Q.nextInLML = Q.prev
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
locMin->LeftBound = E;
|
locMin.LeftBound = E;
|
||||||
locMin->RightBound = E->Prev;
|
locMin.RightBound = E->Prev;
|
||||||
clockwise = true; //Q.nextInLML = Q.next
|
leftBoundIsForward = true; //Q.nextInLML = Q.next
|
||||||
}
|
}
|
||||||
locMin->LeftBound->Side = esLeft;
|
locMin.LeftBound->Side = esLeft;
|
||||||
locMin->RightBound->Side = esRight;
|
locMin.RightBound->Side = esRight;
|
||||||
|
|
||||||
if (!Closed) locMin->LeftBound->WindDelta = 0;
|
if (!Closed) locMin.LeftBound->WindDelta = 0;
|
||||||
else if (locMin->LeftBound->Next == locMin->RightBound)
|
else if (locMin.LeftBound->Next == locMin.RightBound)
|
||||||
locMin->LeftBound->WindDelta = -1;
|
locMin.LeftBound->WindDelta = -1;
|
||||||
else locMin->LeftBound->WindDelta = 1;
|
else locMin.LeftBound->WindDelta = 1;
|
||||||
locMin->RightBound->WindDelta = -locMin->LeftBound->WindDelta;
|
locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta;
|
||||||
|
|
||||||
E = ProcessBound(locMin->LeftBound, clockwise);
|
E = ProcessBound(locMin.LeftBound, leftBoundIsForward);
|
||||||
TEdge* E2 = ProcessBound(locMin->RightBound, !clockwise);
|
if (E->OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward);
|
||||||
|
|
||||||
if (locMin->LeftBound->OutIdx == Skip)
|
TEdge* E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward);
|
||||||
locMin->LeftBound = 0;
|
if (E2->OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward);
|
||||||
else if (locMin->RightBound->OutIdx == Skip)
|
|
||||||
locMin->RightBound = 0;
|
if (locMin.LeftBound->OutIdx == Skip)
|
||||||
InsertLocalMinima(locMin);
|
locMin.LeftBound = 0;
|
||||||
if (!clockwise) E = E2;
|
else if (locMin.RightBound->OutIdx == Skip)
|
||||||
|
locMin.RightBound = 0;
|
||||||
|
m_MinimaList.push_back(locMin);
|
||||||
|
if (!leftBoundIsForward) E = E2;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1209,27 +1237,6 @@ bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed)
|
|||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void ClipperBase::InsertLocalMinima(LocalMinima *newLm)
|
|
||||||
{
|
|
||||||
if( ! m_MinimaList )
|
|
||||||
{
|
|
||||||
m_MinimaList = newLm;
|
|
||||||
}
|
|
||||||
else if( newLm->Y >= m_MinimaList->Y )
|
|
||||||
{
|
|
||||||
newLm->Next = m_MinimaList;
|
|
||||||
m_MinimaList = newLm;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
LocalMinima* tmpLm = m_MinimaList;
|
|
||||||
while( tmpLm->Next && ( newLm->Y < tmpLm->Next->Y ) )
|
|
||||||
tmpLm = tmpLm->Next;
|
|
||||||
newLm->Next = tmpLm->Next;
|
|
||||||
tmpLm->Next = newLm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void ClipperBase::Clear()
|
void ClipperBase::Clear()
|
||||||
{
|
{
|
||||||
DisposeLocalMinimaList();
|
DisposeLocalMinimaList();
|
||||||
@ -1248,12 +1255,12 @@ void ClipperBase::Clear()
|
|||||||
|
|
||||||
void ClipperBase::Reset()
|
void ClipperBase::Reset()
|
||||||
{
|
{
|
||||||
m_CurrentLM = m_MinimaList;
|
m_CurrentLM = m_MinimaList.begin();
|
||||||
if( !m_CurrentLM ) return; //ie nothing to process
|
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 ...
|
||||||
LocalMinima* lm = m_MinimaList;
|
for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm)
|
||||||
while( lm )
|
|
||||||
{
|
{
|
||||||
TEdge* e = lm->LeftBound;
|
TEdge* e = lm->LeftBound;
|
||||||
if (e)
|
if (e)
|
||||||
@ -1270,35 +1277,29 @@ void ClipperBase::Reset()
|
|||||||
e->Side = esRight;
|
e->Side = esRight;
|
||||||
e->OutIdx = Unassigned;
|
e->OutIdx = Unassigned;
|
||||||
}
|
}
|
||||||
lm = lm->Next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void ClipperBase::DisposeLocalMinimaList()
|
void ClipperBase::DisposeLocalMinimaList()
|
||||||
{
|
{
|
||||||
while( m_MinimaList )
|
m_MinimaList.clear();
|
||||||
{
|
m_CurrentLM = m_MinimaList.begin();
|
||||||
LocalMinima* tmpLm = m_MinimaList->Next;
|
|
||||||
delete m_MinimaList;
|
|
||||||
m_MinimaList = tmpLm;
|
|
||||||
}
|
|
||||||
m_CurrentLM = 0;
|
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void ClipperBase::PopLocalMinima()
|
void ClipperBase::PopLocalMinima()
|
||||||
{
|
{
|
||||||
if( ! m_CurrentLM ) return;
|
if (m_CurrentLM == m_MinimaList.end()) return;
|
||||||
m_CurrentLM = m_CurrentLM->Next;
|
++m_CurrentLM;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
IntRect ClipperBase::GetBounds()
|
IntRect ClipperBase::GetBounds()
|
||||||
{
|
{
|
||||||
IntRect result;
|
IntRect result;
|
||||||
LocalMinima* lm = m_MinimaList;
|
MinimaList::iterator lm = m_MinimaList.begin();
|
||||||
if (!lm)
|
if (lm == m_MinimaList.end())
|
||||||
{
|
{
|
||||||
result.left = result.top = result.right = result.bottom = 0;
|
result.left = result.top = result.right = result.bottom = 0;
|
||||||
return result;
|
return result;
|
||||||
@ -1307,10 +1308,9 @@ IntRect ClipperBase::GetBounds()
|
|||||||
result.top = lm->LeftBound->Bot.Y;
|
result.top = lm->LeftBound->Bot.Y;
|
||||||
result.right = lm->LeftBound->Bot.X;
|
result.right = lm->LeftBound->Bot.X;
|
||||||
result.bottom = lm->LeftBound->Bot.Y;
|
result.bottom = lm->LeftBound->Bot.Y;
|
||||||
while (lm)
|
while (lm != m_MinimaList.end())
|
||||||
{
|
{
|
||||||
if (lm->LeftBound->Bot.Y > result.bottom)
|
result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y);
|
||||||
result.bottom = lm->LeftBound->Bot.Y;
|
|
||||||
TEdge* e = lm->LeftBound;
|
TEdge* e = lm->LeftBound;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
TEdge* bottomE = e;
|
TEdge* bottomE = e;
|
||||||
@ -1320,16 +1320,15 @@ IntRect ClipperBase::GetBounds()
|
|||||||
if (e->Bot.X > result.right) result.right = e->Bot.X;
|
if (e->Bot.X > result.right) result.right = e->Bot.X;
|
||||||
e = e->NextInLML;
|
e = e->NextInLML;
|
||||||
}
|
}
|
||||||
if (e->Bot.X < result.left) result.left = e->Bot.X;
|
result.left = std::min(result.left, e->Bot.X);
|
||||||
if (e->Bot.X > result.right) result.right = e->Bot.X;
|
result.right = std::max(result.right, e->Bot.X);
|
||||||
if (e->Top.X < result.left) result.left = e->Top.X;
|
result.left = std::min(result.left, e->Top.X);
|
||||||
if (e->Top.X > result.right) result.right = e->Top.X;
|
result.right = std::max(result.right, e->Top.X);
|
||||||
if (e->Top.Y < result.top) result.top = e->Top.Y;
|
result.top = std::min(result.top, e->Top.Y);
|
||||||
|
|
||||||
if (bottomE == lm->LeftBound) e = lm->RightBound;
|
if (bottomE == lm->LeftBound) e = lm->RightBound;
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
lm = lm->Next;
|
++lm;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1357,12 +1356,11 @@ Clipper::Clipper(int initOptions) : ClipperBase() //constructor
|
|||||||
Clipper::~Clipper() //destructor
|
Clipper::~Clipper() //destructor
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
m_Scanbeam.clear();
|
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifdef use_xyz
|
#ifdef use_xyz
|
||||||
void Clipper::ZFillFunction(TZFillCallback zFillFunc)
|
void Clipper::ZFillFunction(ZFillCallback zFillFunc)
|
||||||
{
|
{
|
||||||
m_ZFill = zFillFunc;
|
m_ZFill = zFillFunc;
|
||||||
}
|
}
|
||||||
@ -1372,15 +1370,11 @@ void Clipper::ZFillFunction(TZFillCallback zFillFunc)
|
|||||||
void Clipper::Reset()
|
void Clipper::Reset()
|
||||||
{
|
{
|
||||||
ClipperBase::Reset();
|
ClipperBase::Reset();
|
||||||
m_Scanbeam.clear();
|
m_Scanbeam = ScanbeamList();
|
||||||
m_ActiveEdges = 0;
|
m_ActiveEdges = 0;
|
||||||
m_SortedEdges = 0;
|
m_SortedEdges = 0;
|
||||||
LocalMinima* lm = m_MinimaList;
|
for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm)
|
||||||
while (lm)
|
|
||||||
{
|
|
||||||
InsertScanbeam(lm->Y);
|
InsertScanbeam(lm->Y);
|
||||||
lm = lm->Next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -1441,7 +1435,7 @@ bool Clipper::ExecuteInternal()
|
|||||||
bool succeeded = true;
|
bool succeeded = true;
|
||||||
try {
|
try {
|
||||||
Reset();
|
Reset();
|
||||||
if (!m_CurrentLM) return false;
|
if (m_CurrentLM == m_MinimaList.end()) return true;
|
||||||
cInt botY = PopScanbeam();
|
cInt botY = PopScanbeam();
|
||||||
do {
|
do {
|
||||||
InsertLocalMinimaIntoAEL(botY);
|
InsertLocalMinimaIntoAEL(botY);
|
||||||
@ -1449,11 +1443,11 @@ bool Clipper::ExecuteInternal()
|
|||||||
ProcessHorizontals(false);
|
ProcessHorizontals(false);
|
||||||
if (m_Scanbeam.empty()) break;
|
if (m_Scanbeam.empty()) break;
|
||||||
cInt topY = PopScanbeam();
|
cInt topY = PopScanbeam();
|
||||||
succeeded = ProcessIntersections(botY, topY);
|
succeeded = ProcessIntersections(topY);
|
||||||
if (!succeeded) break;
|
if (!succeeded) break;
|
||||||
ProcessEdgesAtTopOfScanbeam(topY);
|
ProcessEdgesAtTopOfScanbeam(topY);
|
||||||
botY = topY;
|
botY = topY;
|
||||||
} while (!m_Scanbeam.empty() || m_CurrentLM);
|
} while (!m_Scanbeam.empty() || m_CurrentLM != m_MinimaList.end());
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@ -1492,14 +1486,16 @@ bool Clipper::ExecuteInternal()
|
|||||||
|
|
||||||
void Clipper::InsertScanbeam(const cInt Y)
|
void Clipper::InsertScanbeam(const cInt Y)
|
||||||
{
|
{
|
||||||
m_Scanbeam.insert(Y);
|
//if (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) return;// avoid duplicates.
|
||||||
|
m_Scanbeam.push(Y);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
cInt Clipper::PopScanbeam()
|
cInt Clipper::PopScanbeam()
|
||||||
{
|
{
|
||||||
cInt Y = *m_Scanbeam.begin();
|
const cInt Y = m_Scanbeam.top();
|
||||||
m_Scanbeam.erase(m_Scanbeam.begin());
|
m_Scanbeam.pop();
|
||||||
|
while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { m_Scanbeam.pop(); } // Pop duplicates.
|
||||||
return Y;
|
return Y;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -1858,7 +1854,7 @@ void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt)
|
|||||||
|
|
||||||
void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
|
void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
|
||||||
{
|
{
|
||||||
while( m_CurrentLM && ( m_CurrentLM->Y == botY ) )
|
while (m_CurrentLM != m_MinimaList.end() && (m_CurrentLM->Y == botY))
|
||||||
{
|
{
|
||||||
TEdge* lb = m_CurrentLM->LeftBound;
|
TEdge* lb = m_CurrentLM->LeftBound;
|
||||||
TEdge* rb = m_CurrentLM->RightBound;
|
TEdge* rb = m_CurrentLM->RightBound;
|
||||||
@ -2712,11 +2708,11 @@ void Clipper::UpdateEdgeIntoAEL(TEdge *&e)
|
|||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
bool Clipper::ProcessIntersections(const cInt botY, const cInt topY)
|
bool Clipper::ProcessIntersections(const cInt topY)
|
||||||
{
|
{
|
||||||
if( !m_ActiveEdges ) return true;
|
if( !m_ActiveEdges ) return true;
|
||||||
try {
|
try {
|
||||||
BuildIntersectList(botY, topY);
|
BuildIntersectList(topY);
|
||||||
size_t IlSize = m_IntersectList.size();
|
size_t IlSize = m_IntersectList.size();
|
||||||
if (IlSize == 0) return true;
|
if (IlSize == 0) return true;
|
||||||
if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList();
|
if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList();
|
||||||
@ -2741,7 +2737,7 @@ void Clipper::DisposeIntersectNodes()
|
|||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void Clipper::BuildIntersectList(const cInt botY, const cInt topY)
|
void Clipper::BuildIntersectList(const cInt topY)
|
||||||
{
|
{
|
||||||
if ( !m_ActiveEdges ) return;
|
if ( !m_ActiveEdges ) return;
|
||||||
|
|
||||||
@ -3466,13 +3462,23 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
|
|||||||
}
|
}
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
static OutRec* ParseFirstLeft(OutRec* FirstLeft)
|
||||||
|
{
|
||||||
|
while (FirstLeft && !FirstLeft->Pts)
|
||||||
|
FirstLeft = FirstLeft->FirstLeft;
|
||||||
|
return FirstLeft;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec)
|
void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec)
|
||||||
{
|
{
|
||||||
|
//tests if NewOutRec contains the polygon before reassigning FirstLeft
|
||||||
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
|
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
|
||||||
{
|
{
|
||||||
OutRec* outRec = m_PolyOuts[i];
|
OutRec* outRec = m_PolyOuts[i];
|
||||||
if (outRec->Pts && outRec->FirstLeft == OldOutRec)
|
if (!outRec->Pts || !outRec->FirstLeft) continue;
|
||||||
|
OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft);
|
||||||
|
if (firstLeft == OldOutRec)
|
||||||
{
|
{
|
||||||
if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts))
|
if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts))
|
||||||
outRec->FirstLeft = NewOutRec;
|
outRec->FirstLeft = NewOutRec;
|
||||||
@ -3483,6 +3489,7 @@ void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec)
|
|||||||
|
|
||||||
void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec)
|
void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec)
|
||||||
{
|
{
|
||||||
|
//reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon
|
||||||
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
|
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
|
||||||
{
|
{
|
||||||
OutRec* outRec = m_PolyOuts[i];
|
OutRec* outRec = m_PolyOuts[i];
|
||||||
@ -3491,14 +3498,6 @@ void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec)
|
|||||||
}
|
}
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
static OutRec* ParseFirstLeft(OutRec* FirstLeft)
|
|
||||||
{
|
|
||||||
while (FirstLeft && !FirstLeft->Pts)
|
|
||||||
FirstLeft = FirstLeft->FirstLeft;
|
|
||||||
return FirstLeft;
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void Clipper::JoinCommonEdges()
|
void Clipper::JoinCommonEdges()
|
||||||
{
|
{
|
||||||
for (JoinList::size_type i = 0; i < m_Joins.size(); i++)
|
for (JoinList::size_type i = 0; i < m_Joins.size(); i++)
|
||||||
@ -3782,6 +3781,7 @@ void ClipperOffset::Execute(PolyTree& solution, double delta)
|
|||||||
PolyNode* outerNode = solution.Childs[0];
|
PolyNode* outerNode = solution.Childs[0];
|
||||||
solution.Childs.reserve(outerNode->ChildCount());
|
solution.Childs.reserve(outerNode->ChildCount());
|
||||||
solution.Childs[0] = outerNode->Childs[0];
|
solution.Childs[0] = outerNode->Childs[0];
|
||||||
|
solution.Childs[0]->Parent = outerNode->Parent;
|
||||||
for (int i = 1; i < outerNode->ChildCount(); ++i)
|
for (int i = 1; i < outerNode->ChildCount(); ++i)
|
||||||
solution.AddChild(*outerNode->Childs[i]);
|
solution.AddChild(*outerNode->Childs[i]);
|
||||||
}
|
}
|
||||||
@ -4033,7 +4033,7 @@ void ClipperOffset::DoRound(int j, int k)
|
|||||||
{
|
{
|
||||||
double a = std::atan2(m_sinA,
|
double a = std::atan2(m_sinA,
|
||||||
m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y);
|
m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y);
|
||||||
int steps = (int)Round(m_StepsPerRad * std::fabs(a));
|
int steps = std::max((int)Round(m_StepsPerRad * std::fabs(a)), 1);
|
||||||
|
|
||||||
double X = m_normals[k].X, Y = m_normals[k].Y, X2;
|
double X = m_normals[k].X, Y = m_normals[k].Y, X2;
|
||||||
for (int i = 0; i < steps; ++i)
|
for (int i = 0; i < steps; ++i)
|
||||||
@ -4061,7 +4061,7 @@ void Clipper::DoSimplePolygons()
|
|||||||
{
|
{
|
||||||
OutRec* outrec = m_PolyOuts[i++];
|
OutRec* outrec = m_PolyOuts[i++];
|
||||||
OutPt* op = outrec->Pts;
|
OutPt* op = outrec->Pts;
|
||||||
if (!op) continue;
|
if (!op || outrec->IsOpen) continue;
|
||||||
do //for each Pt in Polygon until duplicate found do ...
|
do //for each Pt in Polygon until duplicate found do ...
|
||||||
{
|
{
|
||||||
OutPt* op2 = op->Next;
|
OutPt* op2 = op->Next;
|
||||||
@ -4086,6 +4086,7 @@ void Clipper::DoSimplePolygons()
|
|||||||
//OutRec2 is contained by OutRec1 ...
|
//OutRec2 is contained by OutRec1 ...
|
||||||
outrec2->IsHole = !outrec->IsHole;
|
outrec2->IsHole = !outrec->IsHole;
|
||||||
outrec2->FirstLeft = outrec;
|
outrec2->FirstLeft = outrec;
|
||||||
|
if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts))
|
if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts))
|
||||||
@ -4095,12 +4096,15 @@ void Clipper::DoSimplePolygons()
|
|||||||
outrec->IsHole = !outrec2->IsHole;
|
outrec->IsHole = !outrec2->IsHole;
|
||||||
outrec2->FirstLeft = outrec->FirstLeft;
|
outrec2->FirstLeft = outrec->FirstLeft;
|
||||||
outrec->FirstLeft = outrec2;
|
outrec->FirstLeft = outrec2;
|
||||||
} else
|
if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
//the 2 polygons are separate ...
|
//the 2 polygons are separate ...
|
||||||
outrec2->IsHole = outrec->IsHole;
|
outrec2->IsHole = outrec->IsHole;
|
||||||
outrec2->FirstLeft = outrec->FirstLeft;
|
outrec2->FirstLeft = outrec->FirstLeft;
|
||||||
}
|
if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2);
|
||||||
|
}
|
||||||
op2 = op; //ie get ready for the Next iteration
|
op2 = op; //ie get ready for the Next iteration
|
||||||
}
|
}
|
||||||
op2 = op2->Next;
|
op2 = op2->Next;
|
||||||
@ -4180,7 +4184,7 @@ bool SlopesNearCollinear(const IntPoint& pt1,
|
|||||||
//this function is more accurate when the point that's geometrically
|
//this function is more accurate when the point that's geometrically
|
||||||
//between the other 2 points is the one that's tested for distance.
|
//between the other 2 points is the one that's tested for distance.
|
||||||
//ie makes it more likely to pick up 'spikes' ...
|
//ie makes it more likely to pick up 'spikes' ...
|
||||||
if (std::abs(pt1.X - pt2.X) > std::abs(pt1.Y - pt2.Y))
|
if (Abs(pt1.X - pt2.X) > Abs(pt1.Y - pt2.Y))
|
||||||
{
|
{
|
||||||
if ((pt1.X > pt2.X) == (pt1.X < pt3.X))
|
if ((pt1.X > pt2.X) == (pt1.X < pt3.X))
|
||||||
return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
|
return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
|
||||||
@ -4390,7 +4394,7 @@ void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution)
|
|||||||
|
|
||||||
enum NodeType {ntAny, ntOpen, ntClosed};
|
enum NodeType {ntAny, ntOpen, ntClosed};
|
||||||
|
|
||||||
void AddPolyNodeToPolygons(const PolyNode& polynode, NodeType nodetype, Paths& paths)
|
void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& paths)
|
||||||
{
|
{
|
||||||
bool match = true;
|
bool match = true;
|
||||||
if (nodetype == ntClosed) match = !polynode.IsOpen();
|
if (nodetype == ntClosed) match = !polynode.IsOpen();
|
||||||
@ -4399,7 +4403,7 @@ void AddPolyNodeToPolygons(const PolyNode& polynode, NodeType nodetype, Paths& p
|
|||||||
if (!polynode.Contour.empty() && match)
|
if (!polynode.Contour.empty() && match)
|
||||||
paths.push_back(polynode.Contour);
|
paths.push_back(polynode.Contour);
|
||||||
for (int i = 0; i < polynode.ChildCount(); ++i)
|
for (int i = 0; i < polynode.ChildCount(); ++i)
|
||||||
AddPolyNodeToPolygons(*polynode.Childs[i], nodetype, paths);
|
AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -4407,7 +4411,7 @@ void PolyTreeToPaths(const PolyTree& polytree, Paths& paths)
|
|||||||
{
|
{
|
||||||
paths.resize(0);
|
paths.resize(0);
|
||||||
paths.reserve(polytree.Total());
|
paths.reserve(polytree.Total());
|
||||||
AddPolyNodeToPolygons(polytree, ntAny, paths);
|
AddPolyNodeToPaths(polytree, ntAny, paths);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -4415,7 +4419,7 @@ void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths)
|
|||||||
{
|
{
|
||||||
paths.resize(0);
|
paths.resize(0);
|
||||||
paths.reserve(polytree.Total());
|
paths.reserve(polytree.Total());
|
||||||
AddPolyNodeToPolygons(polytree, ntClosed, paths);
|
AddPolyNodeToPaths(polytree, ntClosed, paths);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -4457,18 +4461,4 @@ std::ostream& operator <<(std::ostream &s, const Paths &p)
|
|||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifdef use_deprecated
|
|
||||||
|
|
||||||
void OffsetPaths(const Paths &in_polys, Paths &out_polys,
|
|
||||||
double delta, JoinType jointype, EndType_ endtype, double limit)
|
|
||||||
{
|
|
||||||
ClipperOffset co(limit, limit);
|
|
||||||
co.AddPaths(in_polys, jointype, (EndType)endtype);
|
|
||||||
co.Execute(out_polys, delta);
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
} //ClipperLib namespace
|
} //ClipperLib namespace
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* *
|
* *
|
||||||
* Author : Angus Johnson *
|
* Author : Angus Johnson *
|
||||||
* Version : 6.1.5 *
|
* Version : 6.2.1 *
|
||||||
* Date : 22 May 2014 *
|
* Date : 31 October 2014 *
|
||||||
* Website : http://www.angusj.com *
|
* Website : http://www.angusj.com *
|
||||||
* Copyright : Angus Johnson 2010-2014 *
|
* Copyright : Angus Johnson 2010-2014 *
|
||||||
* *
|
* *
|
||||||
@ -34,7 +34,7 @@
|
|||||||
#ifndef clipper_hpp
|
#ifndef clipper_hpp
|
||||||
#define clipper_hpp
|
#define clipper_hpp
|
||||||
|
|
||||||
#define CLIPPER_VERSION "6.1.5"
|
#define CLIPPER_VERSION "6.2.0"
|
||||||
|
|
||||||
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
|
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
|
||||||
//improve performance but coordinate values are limited to the range +/- 46340
|
//improve performance but coordinate values are limited to the range +/- 46340
|
||||||
@ -46,8 +46,7 @@
|
|||||||
//use_lines: Enables line clipping. Adds a very minor cost to performance.
|
//use_lines: Enables line clipping. Adds a very minor cost to performance.
|
||||||
#define use_lines
|
#define use_lines
|
||||||
|
|
||||||
//use_deprecated: Enables support for the obsolete OffsetPaths() function
|
//use_deprecated: Enables temporary support for the obsolete functions
|
||||||
//which has been replace with the ClipperOffset class.
|
|
||||||
//#define use_deprecated
|
//#define use_deprecated
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -57,6 +56,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
namespace ClipperLib {
|
namespace ClipperLib {
|
||||||
|
|
||||||
@ -70,14 +70,15 @@ enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
|
|||||||
|
|
||||||
#ifdef use_int32
|
#ifdef use_int32
|
||||||
typedef int cInt;
|
typedef int cInt;
|
||||||
static cInt const loRange = 46340;
|
static cInt const loRange = 0x7FFF;
|
||||||
static cInt const hiRange = 46340;
|
static cInt const hiRange = 0x7FFF;
|
||||||
#else
|
#else
|
||||||
typedef signed long long cInt;
|
typedef signed long long cInt;
|
||||||
typedef signed long long long64; //used by Int128 class
|
|
||||||
typedef unsigned long long ulong64;
|
|
||||||
static cInt const loRange = 0x3FFFFFFF;
|
static cInt const loRange = 0x3FFFFFFF;
|
||||||
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
||||||
|
typedef signed long long long64; //used by Int128 class
|
||||||
|
typedef unsigned long long ulong64;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct IntPoint {
|
struct IntPoint {
|
||||||
@ -121,15 +122,12 @@ struct DoublePoint
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifdef use_xyz
|
#ifdef use_xyz
|
||||||
typedef void (*TZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
|
typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
|
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
|
||||||
enum JoinType {jtSquare, jtRound, jtMiter};
|
enum JoinType {jtSquare, jtRound, jtMiter};
|
||||||
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
|
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
|
||||||
#ifdef use_deprecated
|
|
||||||
enum EndType_ {etClosed, etButt = 2, etSquare, etRound};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class PolyNode;
|
class PolyNode;
|
||||||
typedef std::vector< PolyNode* > PolyNodes;
|
typedef std::vector< PolyNode* > PolyNodes;
|
||||||
@ -138,6 +136,7 @@ class PolyNode
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PolyNode();
|
PolyNode();
|
||||||
|
virtual ~PolyNode(){};
|
||||||
Path Contour;
|
Path Contour;
|
||||||
PolyNodes Childs;
|
PolyNodes Childs;
|
||||||
PolyNode* Parent;
|
PolyNode* Parent;
|
||||||
@ -172,11 +171,6 @@ bool Orientation(const Path &poly);
|
|||||||
double Area(const Path &poly);
|
double Area(const Path &poly);
|
||||||
int PointInPolygon(const IntPoint &pt, const Path &path);
|
int PointInPolygon(const IntPoint &pt, const Path &path);
|
||||||
|
|
||||||
#ifdef use_deprecated
|
|
||||||
void OffsetPaths(const Paths &in_polys, Paths &out_polys,
|
|
||||||
double delta, JoinType jointype, EndType_ endtype, double limit = 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||||
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||||
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
|
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
|
||||||
@ -205,7 +199,7 @@ enum EdgeSide { esLeft = 1, esRight = 2};
|
|||||||
//forward declarations (for stuff used internally) ...
|
//forward declarations (for stuff used internally) ...
|
||||||
struct TEdge;
|
struct TEdge;
|
||||||
struct IntersectNode;
|
struct IntersectNode;
|
||||||
struct LocalMinima;
|
struct LocalMinimum;
|
||||||
struct Scanbeam;
|
struct Scanbeam;
|
||||||
struct OutPt;
|
struct OutPt;
|
||||||
struct OutRec;
|
struct OutRec;
|
||||||
@ -216,7 +210,6 @@ 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;
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
//ClipperBase is the ancestor to the Clipper class. It should not be
|
//ClipperBase is the ancestor to the Clipper class. It should not be
|
||||||
@ -239,12 +232,14 @@ protected:
|
|||||||
void PopLocalMinima();
|
void PopLocalMinima();
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
TEdge* ProcessBound(TEdge* E, bool IsClockwise);
|
TEdge* ProcessBound(TEdge* E, bool IsClockwise);
|
||||||
void InsertLocalMinima(LocalMinima *newLm);
|
|
||||||
void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
|
void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
|
||||||
TEdge* DescendToMin(TEdge *&E);
|
TEdge* DescendToMin(TEdge *&E);
|
||||||
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
|
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
|
||||||
LocalMinima *m_CurrentLM;
|
|
||||||
LocalMinima *m_MinimaList;
|
typedef std::vector<LocalMinimum> MinimaList;
|
||||||
|
MinimaList::iterator m_CurrentLM;
|
||||||
|
MinimaList m_MinimaList;
|
||||||
|
|
||||||
bool m_UseFullRange;
|
bool m_UseFullRange;
|
||||||
EdgeList m_edges;
|
EdgeList m_edges;
|
||||||
bool m_PreserveCollinear;
|
bool m_PreserveCollinear;
|
||||||
@ -271,7 +266,7 @@ 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(TZFillCallback zFillFunc);
|
void ZFillFunction(ZFillCallback zFillFunc);
|
||||||
#endif
|
#endif
|
||||||
protected:
|
protected:
|
||||||
void Reset();
|
void Reset();
|
||||||
@ -282,7 +277,8 @@ private:
|
|||||||
JoinList m_GhostJoins;
|
JoinList m_GhostJoins;
|
||||||
IntersectList m_IntersectList;
|
IntersectList m_IntersectList;
|
||||||
ClipType m_ClipType;
|
ClipType m_ClipType;
|
||||||
std::set< cInt, std::greater<cInt> > m_Scanbeam;
|
typedef std::priority_queue<cInt> ScanbeamList;
|
||||||
|
ScanbeamList m_Scanbeam;
|
||||||
TEdge *m_ActiveEdges;
|
TEdge *m_ActiveEdges;
|
||||||
TEdge *m_SortedEdges;
|
TEdge *m_SortedEdges;
|
||||||
bool m_ExecuteLocked;
|
bool m_ExecuteLocked;
|
||||||
@ -292,7 +288,7 @@ private:
|
|||||||
bool m_UsingPolyTree;
|
bool m_UsingPolyTree;
|
||||||
bool m_StrictSimple;
|
bool m_StrictSimple;
|
||||||
#ifdef use_xyz
|
#ifdef use_xyz
|
||||||
TZFillCallback m_ZFill; //custom callback
|
ZFillCallback m_ZFill; //custom callback
|
||||||
#endif
|
#endif
|
||||||
void SetWindingCount(TEdge& edge);
|
void SetWindingCount(TEdge& edge);
|
||||||
bool IsEvenOddFillType(const TEdge& edge) const;
|
bool IsEvenOddFillType(const TEdge& edge) const;
|
||||||
@ -322,8 +318,8 @@ private:
|
|||||||
OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
|
OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
|
||||||
void DisposeAllOutRecs();
|
void DisposeAllOutRecs();
|
||||||
void DisposeOutRec(PolyOutList::size_type index);
|
void DisposeOutRec(PolyOutList::size_type index);
|
||||||
bool ProcessIntersections(const cInt botY, const cInt topY);
|
bool ProcessIntersections(const cInt topY);
|
||||||
void BuildIntersectList(const cInt botY, const cInt topY);
|
void BuildIntersectList(const cInt topY);
|
||||||
void ProcessIntersectList();
|
void ProcessIntersectList();
|
||||||
void ProcessEdgesAtTopOfScanbeam(const cInt topY);
|
void ProcessEdgesAtTopOfScanbeam(const cInt topY);
|
||||||
void BuildResult(Paths& polys);
|
void BuildResult(Paths& polys);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user