Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Ranellucci <aar@cpan.org>2015-02-15 18:10:04 +0300
committerAlessandro Ranellucci <aar@cpan.org>2015-02-15 18:10:04 +0300
commit32b8eb489c32451c1ef3b6f635eb0d72a2f0ecac (patch)
treed6baa3cc88f4f05c5ae9a67142bea8f2a7d65b83 /xs/src/clipper.cpp
parent43f48061425b3e4c8b8e6d7ff5af2c961294c2c9 (diff)
Updated Clipper to 6.2.8. This fixes several minor issues, including infill paths not being trimmed correctly. #2448
Diffstat (limited to 'xs/src/clipper.cpp')
-rw-r--r--xs/src/clipper.cpp356
1 files changed, 233 insertions, 123 deletions
diff --git a/xs/src/clipper.cpp b/xs/src/clipper.cpp
index f44201a89..3662fd1a5 100644
--- a/xs/src/clipper.cpp
+++ b/xs/src/clipper.cpp
@@ -1,10 +1,10 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
-* Version : 6.2.1 *
-* Date : 31 October 2014 *
+* Version : 6.2.8 *
+* Date : 10 February 2015 *
* Website : http://www.angusj.com *
-* Copyright : Angus Johnson 2010-2014 *
+* Copyright : Angus Johnson 2010-2015 *
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
@@ -381,13 +381,6 @@ Int128 Int128Mul (long64 lhs, long64 rhs)
// Miscellaneous global functions
//------------------------------------------------------------------------------
-void Swap(cInt& val1, cInt& val2)
-{
- cInt tmp = val1;
- val1 = val2;
- val2 = tmp;
-}
-//------------------------------------------------------------------------------
bool Orientation(const Path &poly)
{
return Area(poly) >= 0;
@@ -435,11 +428,11 @@ bool PointIsVertex(const IntPoint &Pt, OutPt *pp)
}
//------------------------------------------------------------------------------
-int PointInPolygon (const IntPoint &pt, const Path &path)
+//See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos
+//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
+int PointInPolygon(const IntPoint &pt, const Path &path)
{
//returns 0 if false, +1 if true, -1 if pt ON polygon boundary
- //See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos
- //http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
int result = 0;
size_t cnt = path.size();
if (cnt < 3) return 0;
@@ -758,9 +751,9 @@ inline void ReverseHorizontal(TEdge &e)
//swap horizontal edges' Top and Bottom x's so they follow the natural
//progression of the bounds - ie so their xbots will align with the
//adjoining lower edge. [Helpful in the ProcessHorizontal() method.]
- Swap(e.Top.X, e.Bot.X);
+ std::swap(e.Top.X, e.Bot.X);
#ifdef use_xyz
- Swap(e.Top.Z, e.Bot.Z);
+ std::swap(e.Top.Z, e.Bot.Z);
#endif
}
//------------------------------------------------------------------------------
@@ -866,8 +859,8 @@ bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1,
bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b)
{
- if (seg1a > seg1b) Swap(seg1a, seg1b);
- if (seg2a > seg2b) Swap(seg2a, seg2b);
+ if (seg1a > seg1b) std::swap(seg1a, seg1b);
+ if (seg2a > seg2b) std::swap(seg2a, seg2b);
return (seg1a < seg2b) && (seg2a < seg1b);
}
@@ -1000,11 +993,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
//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;
+ if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev;
}
while (E != Result)
{
@@ -1024,11 +1013,8 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
{
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;
+ if (Horz->Next->Top.X == Result->Prev->Top.X ||
+ Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next;
}
while (E != Result)
@@ -1155,17 +1141,17 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
return false;
}
E->Prev->OutIdx = Skip;
- if (E->Prev->Bot.X < E->Prev->Top.X) ReverseHorizontal(*E->Prev);
MinimaList::value_type locMin;
locMin.Y = E->Bot.Y;
locMin.LeftBound = 0;
locMin.RightBound = E;
locMin.RightBound->Side = esRight;
locMin.RightBound->WindDelta = 0;
- while (E->Next->OutIdx != Skip)
+ for (;;)
{
- E->NextInLML = E->Next;
if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
+ if (E->Next->OutIdx == Skip) break;
+ E->NextInLML = E->Next;
E = E->Next;
}
m_MinimaList.push_back(locMin);
@@ -1371,6 +1357,7 @@ void Clipper::Reset()
{
ClipperBase::Reset();
m_Scanbeam = ScanbeamList();
+ m_Maxima = MaximaList();
m_ActiveEdges = 0;
m_SortedEdges = 0;
for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm)
@@ -1378,12 +1365,24 @@ void Clipper::Reset()
}
//------------------------------------------------------------------------------
+bool Clipper::Execute(ClipType clipType, Paths &solution, PolyFillType fillType)
+{
+ return Execute(clipType, solution, fillType, fillType);
+}
+//------------------------------------------------------------------------------
+
+bool Clipper::Execute(ClipType clipType, PolyTree &polytree, PolyFillType fillType)
+{
+ return Execute(clipType, polytree, fillType, fillType);
+}
+//------------------------------------------------------------------------------
+
bool Clipper::Execute(ClipType clipType, Paths &solution,
PolyFillType subjFillType, PolyFillType clipFillType)
{
if( m_ExecuteLocked ) return false;
if (m_HasOpenPaths)
- throw clipperException("Error: PolyTree struct is need for open path clipping.");
+ throw clipperException("Error: PolyTree struct is needed for open path clipping.");
m_ExecuteLocked = true;
solution.resize(0);
m_SubjFillType = subjFillType;
@@ -1439,9 +1438,9 @@ bool Clipper::ExecuteInternal()
cInt botY = PopScanbeam();
do {
InsertLocalMinimaIntoAEL(botY);
- ClearGhostJoins();
- ProcessHorizontals(false);
- if (m_Scanbeam.empty()) break;
+ ProcessHorizontals();
+ ClearGhostJoins();
+ if (m_Scanbeam.empty()) break;
cInt topY = PopScanbeam();
succeeded = ProcessIntersections(topY);
if (!succeeded) break;
@@ -1471,7 +1470,10 @@ bool Clipper::ExecuteInternal()
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
{
OutRec *outRec = m_PolyOuts[i];
- if (outRec->Pts && !outRec->IsOpen)
+ if (!outRec->Pts) continue;
+ if (outRec->IsOpen)
+ FixupOutPolyline(*outRec);
+ else
FixupOutPolygon(*outRec);
}
@@ -1486,17 +1488,16 @@ bool Clipper::ExecuteInternal()
void Clipper::InsertScanbeam(const cInt Y)
{
- //if (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) return;// avoid duplicates.
- m_Scanbeam.push(Y);
+ m_Scanbeam.push(Y);
}
//------------------------------------------------------------------------------
cInt Clipper::PopScanbeam()
{
- const cInt Y = m_Scanbeam.top();
- m_Scanbeam.pop();
- while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { m_Scanbeam.pop(); } // Pop duplicates.
- return Y;
+ const cInt Y = m_Scanbeam.top();
+ m_Scanbeam.pop();
+ while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { m_Scanbeam.pop(); } // Pop duplicates.
+ return Y;
}
//------------------------------------------------------------------------------
@@ -2356,7 +2357,6 @@ OutRec* Clipper::CreateOutRec()
OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
{
- bool ToFront = (e->Side == esLeft);
if( e->OutIdx < 0 )
{
OutRec *outRec = CreateOutRec();
@@ -2377,7 +2377,8 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
//OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most'
OutPt* op = outRec->Pts;
- if (ToFront && (pt == op->Pt)) return op;
+ bool ToFront = (e->Side == esLeft);
+ if (ToFront && (pt == op->Pt)) return op;
else if (!ToFront && (pt == op->Prev->Pt)) return op->Prev;
OutPt* newOp = new OutPt;
@@ -2393,13 +2394,23 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
}
//------------------------------------------------------------------------------
-void Clipper::ProcessHorizontals(bool IsTopOfScanbeam)
+OutPt* Clipper::GetLastOutPt(TEdge *e)
+{
+ OutRec *outRec = m_PolyOuts[e->OutIdx];
+ if (e->Side == esLeft)
+ return outRec->Pts;
+ else
+ return outRec->Pts->Prev;
+}
+//------------------------------------------------------------------------------
+
+void Clipper::ProcessHorizontals()
{
TEdge* horzEdge = m_SortedEdges;
while(horzEdge)
{
DeleteFromSEL(horzEdge);
- ProcessHorizontal(horzEdge, IsTopOfScanbeam);
+ ProcessHorizontal(horzEdge);
horzEdge = m_SortedEdges;
}
}
@@ -2564,10 +2575,11 @@ void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right)
* the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. *
*******************************************************************************/
-void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
+void Clipper::ProcessHorizontal(TEdge *horzEdge)
{
Direction dir;
cInt horzLeft, horzRight;
+ bool IsOpen = (horzEdge->OutIdx >= 0 && m_PolyOuts[horzEdge->OutIdx]->IsOpen);
GetHorzDirection(*horzEdge, dir, horzLeft, horzRight);
@@ -2577,50 +2589,100 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
if (!eLastHorz->NextInLML)
eMaxPair = GetMaximaPair(eLastHorz);
- for (;;)
+ MaximaList::const_iterator maxIt;
+ MaximaList::const_reverse_iterator maxRit;
+ if (m_Maxima.size() > 0)
+ {
+ //get the first maxima in range (X) ...
+ if (dir == dLeftToRight)
+ {
+ maxIt = m_Maxima.begin();
+ while (maxIt != m_Maxima.end() && *maxIt <= horzEdge->Bot.X) maxIt++;
+ if (maxIt != m_Maxima.end() && *maxIt >= eLastHorz->Top.X)
+ maxIt = m_Maxima.end();
+ }
+ else
+ {
+ maxRit = m_Maxima.rbegin();
+ while (maxRit != m_Maxima.rend() && *maxRit > horzEdge->Bot.X) maxRit++;
+ if (maxRit != m_Maxima.rend() && *maxRit <= eLastHorz->Top.X)
+ maxRit = m_Maxima.rend();
+ }
+ }
+
+ OutPt* op1 = 0;
+
+ for (;;) //loop through consec. horizontal edges
{
+
bool IsLastHorz = (horzEdge == eLastHorz);
TEdge* e = GetNextInAEL(horzEdge, dir);
while(e)
{
- //Break if we've got to the end of an intermediate horizontal edge ...
- //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal.
- if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML &&
- e->Dx < horzEdge->NextInLML->Dx) break;
- TEdge* eNext = GetNextInAEL(e, dir); //saves eNext for later
-
- if ((dir == dLeftToRight && e->Curr.X <= horzRight) ||
- (dir == dRightToLeft && e->Curr.X >= horzLeft))
- {
- //so far we're still in range of the horizontal Edge but make sure
+ //this code block inserts extra coords into horizontal edges (in output
+ //polygons) whereever maxima touch these horizontal edges. This helps
+ //'simplifying' polygons (ie if the Simplify property is set).
+ if (m_Maxima.size() > 0)
+ {
+ if (dir == dLeftToRight)
+ {
+ while (maxIt != m_Maxima.end() && *maxIt < e->Curr.X)
+ {
+ if (horzEdge->OutIdx >= 0 && !IsOpen)
+ AddOutPt(horzEdge, IntPoint(*maxIt, horzEdge->Bot.Y));
+ maxIt++;
+ }
+ }
+ else
+ {
+ while (maxRit != m_Maxima.rend() && *maxRit > e->Curr.X)
+ {
+ if (horzEdge->OutIdx >= 0 && !IsOpen)
+ AddOutPt(horzEdge, IntPoint(*maxRit, horzEdge->Bot.Y));
+ maxRit++;
+ }
+ }
+ };
+
+ if ((dir == dLeftToRight && e->Curr.X > horzRight) ||
+ (dir == dRightToLeft && e->Curr.X < horzLeft)) break;
+
+ //Also break if we've got to the end of an intermediate horizontal edge ...
+ //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal.
+ if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML &&
+ e->Dx < horzEdge->NextInLML->Dx) break;
+
+ if (horzEdge->OutIdx >= 0 && !IsOpen) //note: may be done multiple times
+ {
+ op1 = AddOutPt(horzEdge, e->Curr);
+ TEdge* eNextHorz = m_SortedEdges;
+ while (eNextHorz)
+ {
+ if (eNextHorz->OutIdx >= 0 &&
+ HorzSegmentsOverlap(horzEdge->Bot.X,
+ horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
+ {
+ OutPt* op2 = GetLastOutPt(eNextHorz);
+ AddJoin(op2, op1, eNextHorz->Top);
+ }
+ eNextHorz = eNextHorz->NextInSEL;
+ }
+ AddGhostJoin(op1, horzEdge->Bot);
+ }
+
+ //OK, so far we're still in range of the horizontal Edge but make sure
//we're at the last of consec. horizontals when matching with eMaxPair
if(e == eMaxPair && IsLastHorz)
{
-
if (horzEdge->OutIdx >= 0)
- {
- OutPt* op1 = AddOutPt(horzEdge, horzEdge->Top);
- TEdge* eNextHorz = m_SortedEdges;
- while (eNextHorz)
- {
- if (eNextHorz->OutIdx >= 0 &&
- HorzSegmentsOverlap(horzEdge->Bot.X,
- horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
- {
- OutPt* op2 = AddOutPt(eNextHorz, eNextHorz->Bot);
- AddJoin(op2, op1, eNextHorz->Top);
- }
- eNextHorz = eNextHorz->NextInSEL;
- }
- AddGhostJoin(op1, horzEdge->Bot);
AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top);
- }
DeleteFromAEL(horzEdge);
DeleteFromAEL(eMaxPair);
return;
}
- else if(dir == dLeftToRight)
+
+ if(dir == dLeftToRight)
{
IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y);
IntersectEdges(horzEdge, e, Pt);
@@ -2630,28 +2692,43 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y);
IntersectEdges( e, horzEdge, Pt);
}
+ TEdge* eNext = GetNextInAEL(e, dir);
SwapPositionsInAEL( horzEdge, e );
- }
- else if( (dir == dLeftToRight && e->Curr.X >= horzRight) ||
- (dir == dRightToLeft && e->Curr.X <= horzLeft) ) break;
- e = eNext;
- } //end while
+ e = eNext;
+ } //end while(e)
+
+ //Break out of loop if HorzEdge.NextInLML is not also horizontal ...
+ if (!horzEdge->NextInLML || !IsHorizontal(*horzEdge->NextInLML)) break;
+
+ UpdateEdgeIntoAEL(horzEdge);
+ if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot);
+ GetHorzDirection(*horzEdge, dir, horzLeft, horzRight);
- if (horzEdge->NextInLML && IsHorizontal(*horzEdge->NextInLML))
- {
- UpdateEdgeIntoAEL(horzEdge);
- if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot);
- GetHorzDirection(*horzEdge, dir, horzLeft, horzRight);
- } else
- break;
} //end for (;;)
- if(horzEdge->NextInLML)
+ if (horzEdge->OutIdx >= 0 && !op1)
+ {
+ op1 = GetLastOutPt(horzEdge);
+ TEdge* eNextHorz = m_SortedEdges;
+ while (eNextHorz)
+ {
+ if (eNextHorz->OutIdx >= 0 &&
+ HorzSegmentsOverlap(horzEdge->Bot.X,
+ horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
+ {
+ OutPt* op2 = GetLastOutPt(eNextHorz);
+ AddJoin(op2, op1, eNextHorz->Top);
+ }
+ eNextHorz = eNextHorz->NextInSEL;
+ }
+ AddGhostJoin(op1, horzEdge->Top);
+ }
+
+ if (horzEdge->NextInLML)
{
if(horzEdge->OutIdx >= 0)
{
- OutPt* op1 = AddOutPt( horzEdge, horzEdge->Top);
- if (isTopOfScanbeam) AddGhostJoin(op1, horzEdge->Bot);
+ op1 = AddOutPt( horzEdge, horzEdge->Top);
UpdateEdgeIntoAEL(horzEdge);
if (horzEdge->WindDelta == 0) return;
//nb: HorzEdge is no longer horizontal here
@@ -2906,6 +2983,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
if(IsMaximaEdge)
{
+ if (m_StrictSimple) m_Maxima.push_back(e->Top.X);
TEdge* ePrev = e->PrevInAEL;
DoMaxima(e);
if( !ePrev ) e = m_ActiveEdges;
@@ -2927,6 +3005,8 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
e->Curr.Y = topY;
}
+ //When StrictlySimple and 'e' is being touched by another edge, then
+ //make sure both edges have a vertex here ...
if (m_StrictSimple)
{
TEdge* ePrev = e->PrevInAEL;
@@ -2948,7 +3028,9 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
}
//3. Process horizontals at the Top of the scanbeam ...
- ProcessHorizontals(true);
+ m_Maxima.sort();
+ ProcessHorizontals();
+ m_Maxima.clear();
//4. Promote intermediate vertices ...
e = m_ActiveEdges;
@@ -2988,44 +3070,71 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
}
//------------------------------------------------------------------------------
-void Clipper::FixupOutPolygon(OutRec &outrec)
+void Clipper::FixupOutPolyline(OutRec &outrec)
{
- //FixupOutPolygon() - removes duplicate points and simplifies consecutive
- //parallel edges by removing the middle vertex.
- OutPt *lastOK = 0;
- outrec.BottomPt = 0;
OutPt *pp = outrec.Pts;
-
- for (;;)
+ OutPt *lastPP = pp->Prev;
+ while (pp != lastPP)
{
- if (pp->Prev == pp || pp->Prev == pp->Next )
+ pp = pp->Next;
+ if (pp->Pt == pp->Prev->Pt)
{
- DisposeOutPts(pp);
- outrec.Pts = 0;
- return;
+ if (pp == lastPP) lastPP = pp->Prev;
+ OutPt *tmpPP = pp->Prev;
+ tmpPP->Next = pp->Next;
+ pp->Next->Prev = tmpPP;
+ delete pp;
+ pp = tmpPP;
}
+ }
- //test for duplicate points and collinear edges ...
- if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) ||
- (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) &&
- (!m_PreserveCollinear ||
- !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt))))
- {
- lastOK = 0;
- OutPt *tmp = pp;
- pp->Prev->Next = pp->Next;
- pp->Next->Prev = pp->Prev;
- pp = pp->Prev;
- delete tmp;
- }
- else if (pp == lastOK) break;
- else
+ if (pp == pp->Prev)
+ {
+ DisposeOutPts(pp);
+ outrec.Pts = 0;
+ return;
+ }
+}
+//------------------------------------------------------------------------------
+
+void Clipper::FixupOutPolygon(OutRec &outrec)
+{
+ //FixupOutPolygon() - removes duplicate points and simplifies consecutive
+ //parallel edges by removing the middle vertex.
+ OutPt *lastOK = 0;
+ outrec.BottomPt = 0;
+ OutPt *pp = outrec.Pts;
+ bool preserveCol = m_PreserveCollinear || m_StrictSimple;
+
+ for (;;)
{
- if (!lastOK) lastOK = pp;
- pp = pp->Next;
+ if (pp->Prev == pp || pp->Prev == pp->Next)
+ {
+ DisposeOutPts(pp);
+ outrec.Pts = 0;
+ return;
+ }
+
+ //test for duplicate points and collinear edges ...
+ if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) ||
+ (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) &&
+ (!preserveCol || !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt))))
+ {
+ lastOK = 0;
+ OutPt *tmp = pp;
+ pp->Prev->Next = pp->Next;
+ pp->Next->Prev = pp->Prev;
+ pp = pp->Prev;
+ delete tmp;
+ }
+ else if (pp == lastOK) break;
+ else
+ {
+ if (!lastOK) lastOK = pp;
+ pp = pp->Next;
+ }
}
- }
- outrec.Pts = pp;
+ outrec.Pts = pp;
}
//------------------------------------------------------------------------------
@@ -3309,7 +3418,7 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
OutPt *op2 = j->OutPt2, *op2b;
//There are 3 kinds of joins for output polygons ...
- //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are a vertices anywhere
+ //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are vertices anywhere
//along (horizontal) collinear edges (& Join.OffPt is on the same horizontal).
//2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same
//location at the Bottom of the overlapping segment (& Join.OffPt is above).
@@ -3508,6 +3617,7 @@ void Clipper::JoinCommonEdges()
OutRec *outRec2 = GetOutRec(join->OutPt2->Idx);
if (!outRec1->Pts || !outRec2->Pts) continue;
+ if (outRec1->IsOpen || outRec2->IsOpen) continue;
//get the polygon fragment with the correct hole state (FirstLeft)
//before calling JoinPoints() ...
@@ -4355,7 +4465,7 @@ void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool p
}
//------------------------------------------------------------------------------
-void TranslatePath(const Path& input, Path& output, IntPoint delta)
+void TranslatePath(const Path& input, Path& output, const IntPoint delta)
{
//precondition: input != output
output.resize(input.size());