53static double const pi = 3.141592653589793238;
62#define HORIZONTAL (-1.0E+40)
63#define TOLERANCE (1.0e-20)
64#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE))
129 return locMin2.
Y < locMin1.
Y;
138 if ((val < 0))
return static_cast<cInt>(val - 0.5);
139 else return static_cast<cInt>(val + 0.5);
145 return val < 0 ? -val : val;
154 for (PolyNodes::size_type
i = 0;
i <
AllNodes.size(); ++
i)
189 return (
int)
Childs.size();
195 unsigned cnt = (unsigned)
Childs.size();
260 if (_lo < 0)
hi = -1;
else hi = 0;
271 if (val < 0)
hi = -1;
else hi = 0;
276 {
return (
hi == val.
hi &&
lo == val.
lo);}
279 {
return !(*
this == val);}
298 {
return !(*
this < val);}
301 {
return !(*
this > val);}
341 const double shift64 = 18446744073709551616.0;
344 if (
lo == 0)
return (
double)
hi * shift64;
348 return (
double)(
lo +
hi * shift64);
356 bool negate = (lhs < 0) != (rhs < 0);
358 if (lhs < 0) lhs = -lhs;
362 if (rhs < 0) rhs = -rhs;
369 ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi;
375 if (tmp.
lo < b) tmp.
hi++;
376 if (negate) tmp = -tmp;
387 return Area(poly) >= 0;
393 int size = (int)poly.size();
394 if (size < 3)
return 0;
397 for (
int i = 0,
j = size -1;
i < size; ++
i)
399 a += ((
double)poly[
j].X + poly[
i].X) * ((
double)poly[
j].Y - poly[
i].Y);
408 const OutPt *startOp = op;
414 }
while (op != startOp);
430 if (pp2->
Pt == Pt)
return true;
444 size_t cnt = path.size();
445 if (cnt < 3)
return 0;
447 for(
size_t i = 1;
i <= cnt; ++
i)
449 IntPoint ipNext = (
i == cnt ? path[0] : path[
i]);
450 if (ipNext.
Y == pt.
Y)
452 if ((ipNext.
X == pt.
X) || (ip.
Y == pt.
Y &&
453 ((ipNext.
X > pt.
X) == (ip.
X < pt.
X))))
return -1;
455 if ((ip.
Y < pt.
Y) != (ipNext.
Y < pt.
Y))
459 if (ipNext.
X > pt.
X) result = 1 - result;
462 double d = (
double)(ip.
X - pt.
X) * (ipNext.
Y - pt.
Y) -
463 (
double)(ipNext.
X - pt.
X) * (ip.
Y - pt.
Y);
465 if ((d > 0) == (ipNext.
Y > ip.
Y)) result = 1 - result;
471 double d = (
double)(ip.
X - pt.
X) * (ipNext.
Y - pt.
Y) -
472 (
double)(ipNext.
X - pt.
X) * (ip.
Y - pt.
Y);
474 if ((d > 0) == (ipNext.
Y > ip.
Y)) result = 1 - result;
494 ((op->
Next->
Pt.
X > pt.
X) == (op->
Pt.
X < pt.
X))))
return -1;
498 if (op->
Pt.
X >= pt.
X)
500 if (op->
Next->
Pt.
X > pt.
X) result = 1 - result;
506 if ((d > 0) == (op->
Next->
Pt.
Y > op->
Pt.
Y)) result = 1 - result;
515 if ((d > 0) == (op->
Next->
Pt.
Y > op->
Pt.
Y)) result = 1 - result;
520 if (startOp == op)
break;
533 if (res >= 0)
return res > 0;
536 while (op != OutPt1);
544 if (UseFullInt64Range)
555 const IntPoint pt3,
bool UseFullInt64Range)
558 if (UseFullInt64Range)
562 return (pt1.
Y-pt2.
Y)*(pt2.
X-pt3.
X) == (pt1.
X-pt2.
X)*(pt2.
Y-pt3.
Y);
570 if (UseFullInt64Range)
574 return (pt1.
Y-pt2.
Y)*(pt3.
X-pt4.
X) == (pt1.
X-pt2.
X)*(pt3.
Y-pt4.
Y);
586 return (pt1.
Y == pt2.
Y) ?
609 int OutIdx = Edge1.
OutIdx;
617 return ( currentY == edge.
Top.
Y ) ?
629 if (Edge1.
Dx == Edge2.
Dx)
635 else if (Edge1.
Dx == 0)
646 else if (Edge2.
Dx == 0)
661 double q = (b2-b1) / (Edge1.
Dx - Edge2.
Dx);
663 if (std::fabs(Edge1.
Dx) < std::fabs(Edge2.
Dx))
675 if (std::fabs(Edge1.
Dx) < std::fabs(Edge2.
Dx))
685 if (std::fabs(Edge1.
Dx) > std::fabs(Edge2.
Dx))
686 ip.
X =
TopX(Edge2, ip.
Y);
else
702 }
while( pp1 != pp );
721 std::memset(e, 0,
sizeof(
TEdge));
763 std::swap(e.
Top.Z, e.
Bot.Z);
780 if (
Abs(pt1a.
X - pt1b.
X) >
Abs(pt1a.
Y - pt1b.
Y))
784 if (pt1a.
X > pt2a.
X) pt1 = pt1a;
else pt1 = pt2a;
785 if (pt1b.
X < pt2b.
X) pt2 = pt1b;
else pt2 = pt2b;
786 return pt1.
X < pt2.
X;
791 if (pt1a.
Y < pt2a.
Y) pt1 = pt1a;
else pt1 = pt2a;
792 if (pt1b.
Y > pt2b.
Y) pt2 = pt1b;
else pt2 = pt2b;
793 return pt1.
Y > pt2.
Y;
801 while ((p->
Pt == btmPt1->
Pt) && (p != btmPt1)) p = p->
Prev;
802 double dx1p = std::fabs(
GetDx(btmPt1->
Pt, p->
Pt));
804 while ((p->
Pt == btmPt1->
Pt) && (p != btmPt1)) p = p->
Next;
805 double dx1n = std::fabs(
GetDx(btmPt1->
Pt, p->
Pt));
808 while ((p->
Pt == btmPt2->
Pt) && (p != btmPt2)) p = p->
Prev;
809 double dx2p = std::fabs(
GetDx(btmPt2->
Pt, p->
Pt));
811 while ((p->
Pt == btmPt2->
Pt) && (p != btmPt2)) p = p->
Next;
812 double dx2n = std::fabs(
GetDx(btmPt2->
Pt, p->
Pt));
814 if (std::max(dx1p, dx1n) == std::max(dx2p, dx2n) &&
815 std::min(dx1p, dx1n) == std::min(dx2p, dx2n))
816 return Area(btmPt1) > 0;
818 return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n);
841 if (p->
Next != pp && p->
Prev != pp) dups = p;
853 while (dups->
Pt != pp->
Pt) dups = dups->
Next;
863 if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2))
865 else if (pt1.
X != pt3.
X)
866 return (pt2.
X > pt1.
X) == (pt2.
X < pt3.
X);
868 return (pt2.
Y > pt1.
Y) == (pt2.
Y < pt3.
Y);
874 if (seg1a > seg1b) std::swap(seg1a, seg1b);
875 if (seg2a > seg2b) std::swap(seg2a, seg2b);
876 return (seg1a < seg2b) && (seg2a < seg1b);
915 while (
E->Bot !=
E->Prev->Bot ||
E->Curr ==
E->Top)
E =
E->Next;
920 if (
E->Top.Y ==
E->Prev->Bot.Y)
continue;
933 if (
E->OutIdx ==
Skip)
939 while (
E->Top.Y ==
E->Next->Bot.Y)
E =
E->Next;
946 while (
E->Top.Y ==
E->Prev->Bot.Y)
E =
E->Prev;
952 if (NextIsForward) Result =
E->Next;
953 else Result =
E->Prev;
962 MinimaList::value_type locMin;
964 locMin.LeftBound = 0;
965 locMin.RightBound =
E;
986 if (EStart->
Bot.
X !=
E->Bot.X && EStart->
Top.
X !=
E->Bot.X)
989 else if (EStart->
Bot.
X !=
E->Bot.X)
997 Result = Result->
Next;
1009 E->NextInLML =
E->Next;
1016 Result = Result->
Next;
1020 Result = Result->
Prev;
1031 E->NextInLML =
E->Prev;
1038 Result = Result->
Prev;
1048 if (!Closed && PolyTyp ==
ptClip)
1055 int highI = (int)pg.size() -1;
1056 if (Closed)
while (highI > 0 && (pg[highI] == pg[0])) --highI;
1057 while (highI > 0 && (pg[highI] == pg[highI -1])) --highI;
1058 if ((Closed && highI < 2) || (!Closed && highI < 1))
return false;
1067 edges[1].
Curr = pg[1];
1070 InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]);
1071 InitEdge(&edges[highI], &edges[0], &edges[highI-1], pg[highI]);
1072 for (
int i = highI - 1;
i >= 1; --
i)
1083 TEdge *eStart = &edges[0];
1086 TEdge *
E = eStart, *eLoopStop = eStart;
1090 if (
E->Curr ==
E->Next->Curr && (Closed ||
E->Next != eStart))
1092 if (
E ==
E->Next)
break;
1093 if (
E == eStart) eStart =
E->Next;
1098 if (
E->Prev ==
E->Next)
1109 if (
E == eStart) eStart =
E->Next;
1116 if ((
E == eLoopStop) || (!Closed &&
E->Next == eStart))
break;
1119 if ((!Closed && (
E ==
E->Next)) || (Closed && (
E->Prev ==
E->Next)))
1137 if (IsFlat &&
E->Curr.Y != eStart->
Curr.
Y) IsFlat =
false;
1139 while (
E != eStart);
1152 E->Prev->OutIdx =
Skip;
1153 MinimaList::value_type locMin;
1154 locMin.Y =
E->Bot.Y;
1155 locMin.LeftBound = 0;
1156 locMin.RightBound =
E;
1157 locMin.RightBound->Side =
esRight;
1158 locMin.RightBound->WindDelta = 0;
1162 if (
E->Next->OutIdx ==
Skip)
break;
1163 E->NextInLML =
E->Next;
1172 bool leftBoundIsForward;
1177 if (
E->Prev->Bot ==
E->Prev->Top)
E =
E->Next;
1182 if (
E == EMin)
break;
1183 else if (!EMin) EMin =
E;
1187 MinimaList::value_type locMin;
1188 locMin.Y =
E->Bot.Y;
1189 if (
E->Dx <
E->Prev->Dx)
1191 locMin.LeftBound =
E->Prev;
1192 locMin.RightBound =
E;
1193 leftBoundIsForward =
false;
1196 locMin.LeftBound =
E;
1197 locMin.RightBound =
E->Prev;
1198 leftBoundIsForward =
true;
1201 if (!Closed) locMin.LeftBound->WindDelta = 0;
1202 else if (locMin.LeftBound->Next == locMin.RightBound)
1203 locMin.LeftBound->WindDelta = -1;
1204 else locMin.LeftBound->WindDelta = 1;
1205 locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta;
1213 if (locMin.LeftBound->OutIdx ==
Skip)
1214 locMin.LeftBound = 0;
1215 else if (locMin.RightBound->OutIdx ==
Skip)
1216 locMin.RightBound = 0;
1218 if (!leftBoundIsForward)
E = E2;
1226 bool result =
false;
1227 for (Paths::size_type
i = 0;
i < ppg.size(); ++
i)
1228 if (
AddPath(ppg[
i], PolyTyp, Closed)) result =
true;
1236 for (EdgeList::size_type
i = 0;
i <
m_edges.size(); ++
i)
1258 TEdge* e = lm->LeftBound;
1289 locMin = &(*m_CurrentLM);
1304 result.
left = lm->LeftBound->Bot.X;
1305 result.
top = lm->LeftBound->Bot.Y;
1306 result.
right = lm->LeftBound->Bot.X;
1307 result.
bottom = lm->LeftBound->Bot.Y;
1311 result.
bottom = std::max(result.
bottom, lm->LeftBound->Bot.Y);
1312 TEdge* e = lm->LeftBound;
1326 if (bottomE == lm->LeftBound) e = lm->RightBound;
1352 for (PolyOutList::size_type
i = 0;
i <
m_PolyOuts.size(); ++
i)
1372 if (AelPrev) AelPrev->
NextInAEL = AelNext;
1374 if (AelNext) AelNext->
PrevInAEL = AelPrev;
1489void Clipper::ZFillFunction(ZFillCallback zFillFunc)
1491 m_ZFill = zFillFunc;
1498 return Execute(clipType, solution, fillType, fillType);
1504 return Execute(clipType, polytree, fillType, fillType);
1513 throw clipperException(
"Error: PolyTree struct is needed for open path clipping.");
1562 bool succeeded =
true;
1594 for (PolyOutList::size_type
i = 0;
i <
m_PolyOuts.size(); ++
i)
1597 if (!outRec->
Pts || outRec->
IsOpen)
continue;
1605 for (PolyOutList::size_type
i = 0;
i <
m_PolyOuts.size(); ++
i)
1608 if (!outRec->
Pts)
continue;
1661 edge.
WindCnt = (Inside ? 0 : 1);
1716 while ( e != &edge )
1764 if (edge.
WindCnt != 1)
return false;
1767 if (edge.
WindCnt != -1)
return false;
1869 if (prevE && prevE->
OutIdx >= 0)
1954 for (JoinList::size_type
i = 0;
i <
m_Joins.size();
i++)
2026 if (!lb || !rb)
continue;
2085 if( SelPrev ) SelPrev->
NextInSEL = SelNext;
2087 if( SelNext ) SelNext->
PrevInSEL = SelPrev;
2096 if (pt.Z != 0 || !m_ZFill)
return;
2097 else if (pt == e1.
Bot) pt.Z = e1.
Bot.Z;
2098 else if (pt == e1.
Top) pt.Z = e1.
Top.Z;
2099 else if (pt == e2.
Bot) pt.Z = e2.
Bot.Z;
2100 else if (pt == e2.
Top) pt.Z = e2.
Top.Z;
2108 bool e1Contributing = ( e1->
OutIdx >= 0 );
2109 bool e2Contributing = ( e2->
OutIdx >= 0 );
2170 int oldE1WindCnt = e1->
WindCnt;
2188 PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2;
2222 if ( e1Contributing && e2Contributing )
2224 if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) ||
2237 else if ( e1Contributing )
2239 if (e2Wc == 0 || e2Wc == 1)
2246 else if ( e2Contributing )
2248 if (e1Wc == 0 || e1Wc == 1)
2255 else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1))
2260 switch (e1FillType2)
2266 switch (e2FillType2)
2277 else if (e1Wc == 1 && e2Wc == 1)
2280 if (e1Wc2 > 0 && e2Wc2 > 0)
2284 if ( e1Wc2 <= 0 && e2Wc2 <= 0 )
2288 if (((e1->
PolyTyp ==
ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) ||
2309 if (!eTmp) eTmp = e2;
2336 if (OutPt1->
Pt.
Y > OutPt2->
Pt.
Y)
return outRec1;
2337 else if (OutPt1->
Pt.
Y < OutPt2->
Pt.
Y)
return outRec2;
2338 else if (OutPt1->
Pt.
X < OutPt2->
Pt.
X)
return outRec1;
2339 else if (OutPt1->
Pt.
X > OutPt2->
Pt.
X)
return outRec2;
2340 else if (OutPt1->
Next == OutPt1)
return outRec2;
2341 else if (OutPt2->
Next == OutPt2)
return outRec1;
2343 else return outRec2;
2352 if (outRec1 == outRec2)
return true;
2375 holeStateRec = outRec2;
2377 holeStateRec = outRec1;
2396 p2_lft->
Next = p1_lft;
2397 p1_lft->
Prev = p2_lft;
2398 p1_rt->
Next = p2_rt;
2399 p2_rt->
Prev = p1_rt;
2400 outRec1->
Pts = p2_rt;
2404 p2_rt->
Next = p1_lft;
2405 p1_lft->
Prev = p2_rt;
2406 p2_lft->
Prev = p1_rt;
2407 p1_rt->
Next = p2_lft;
2408 outRec1->
Pts = p2_lft;
2416 p1_rt->
Next = p2_rt;
2417 p2_rt->
Prev = p1_rt;
2418 p2_lft->
Next = p1_lft;
2419 p1_lft->
Prev = p2_lft;
2423 p1_rt->
Next = p2_lft;
2424 p2_lft->
Prev = p1_rt;
2425 p1_lft->
Prev = p2_rt;
2426 p2_rt->
Next = p1_lft;
2431 if (holeStateRec == outRec2)
2442 int ObsoleteIdx = e2->
OutIdx;
2450 if( e->
OutIdx == ObsoleteIdx )
2459 outRec2->
Idx = outRec1->
Idx;
2470 outRec->
Pts = newOp;
2471 newOp->
Idx = outRec->
Idx;
2473 newOp->
Next = newOp;
2474 newOp->
Prev = newOp;
2486 if (ToFront && (pt == op->
Pt))
return op;
2487 else if (!ToFront && (pt == op->
Prev->
Pt))
return op->
Prev;
2490 newOp->
Idx = outRec->
Idx;
2496 if (ToFront) outRec->
Pts = newOp;
2612 if (HorzEdge.
Bot.
X < HorzEdge.
Top.
X)
2614 Left = HorzEdge.
Bot.
X;
2615 Right = HorzEdge.
Top.
X;
2619 Left = HorzEdge.
Top.
X;
2620 Right = HorzEdge.
Bot.
X;
2639 cInt horzLeft, horzRight;
2640 bool IsOpen = (horzEdge->
WindDelta == 0);
2644 TEdge* eLastHorz = horzEdge, *eMaxPair = 0;
2650 MaximaList::const_iterator maxIt;
2651 MaximaList::const_reverse_iterator maxRit;
2658 while (maxIt !=
m_Maxima.end() && *maxIt <= horzEdge->Bot.X) maxIt++;
2659 if (maxIt !=
m_Maxima.end() && *maxIt >= eLastHorz->
Top.
X)
2665 while (maxRit !=
m_Maxima.rend() && *maxRit > horzEdge->
Bot.
X) maxRit++;
2666 if (maxRit !=
m_Maxima.rend() && *maxRit <= eLastHorz->Top.X)
2676 bool IsLastHorz = (horzEdge == eLastHorz);
2688 while (maxIt !=
m_Maxima.end() && *maxIt < e->Curr.X)
2690 if (horzEdge->
OutIdx >= 0 && !IsOpen)
2699 if (horzEdge->
OutIdx >= 0 && !IsOpen)
2714 if (horzEdge->
OutIdx >= 0 && !IsOpen)
2720 if (eNextHorz->
OutIdx >= 0 &&
2734 if(e == eMaxPair && IsLastHorz)
2736 if (horzEdge->
OutIdx >= 0)
2767 if (horzEdge->
OutIdx >= 0 && !op1)
2773 if (eNextHorz->
OutIdx >= 0 &&
2787 if(horzEdge->
OutIdx >= 0)
2795 if (ePrev && ePrev->
Curr.
X == horzEdge->
Bot.
X &&
2803 else if (eNext && eNext->
Curr.
X == horzEdge->
Bot.
X &&
2829 if (IlSize == 0)
return true;
2883 newNode->
Edge2 = eNext;
2896 while ( isModified );
2919 return node2->
Pt.
Y < node1->
Pt.
Y;
2938 for (
size_t i = 0;
i < cnt; ++
i)
2944 if (
j == cnt)
return false;
2965 while(eNext && eNext != eMaxPair)
2993 if (eMaxPair->
OutIdx >= 0)
3012 bool IsMaximaEdge =
IsMaxima(e, topY);
3017 IsMaximaEdge = (!eMaxPair || !
IsHorizontal(*eMaxPair));
3054 SetZ(pt, *ePrev, *e);
3085 if (ePrev && ePrev->
Curr.
X == e->
Bot.
X &&
3094 else if (eNext && eNext->
Curr.
X == e->
Bot.
X &&
3113 while (pp != lastPP)
3118 if (pp == lastPP) lastPP = pp->
Prev;
3166 else if (pp == lastOK)
break;
3169 if (!lastOK) lastOK = pp;
3195 for (PolyOutList::size_type
i = 0;
i <
m_PolyOuts.size(); ++
i)
3201 if (cnt < 2)
continue;
3203 for (
int i = 0;
i < cnt; ++
i)
3205 pg.push_back(p->
Pt);
3208 polys.push_back(pg);
3218 for (PolyOutList::size_type
i = 0;
i <
m_PolyOuts.size();
i++)
3222 if ((outRec->
IsOpen && cnt < 2) || (!outRec->
IsOpen && cnt < 3))
continue;
3232 for (
int j = 0;
j < cnt;
j++)
3241 for (PolyOutList::size_type
i = 0;
i <
m_PolyOuts.size();
i++)
3244 if (!outRec->
PolyNd)
continue;
3288 if (b1 < b2) {Left = std::max(
a1,b1); Right = std::min(
a2,b2);}
3289 else {Left = std::max(
a1,b2); Right = std::min(
a2,b1);}
3293 if (b1 < b2) {Left = std::max(
a2,b1); Right = std::min(
a1,b2);}
3294 else {Left = std::max(
a2,b2); Right = std::min(
a1,b1);}
3296 return Left < Right;
3308 while(op != outrec.
Pts);
3344 result->
Pt = outPt->
Pt;
3345 result->
Idx = outPt->
Idx;
3349 result->
Prev = outPt;
3351 outPt->
Next = result;
3356 result->
Next = outPt;
3358 outPt->
Prev = result;
3365 const IntPoint Pt,
bool DiscardLeft)
3369 if (Dir1 == Dir2)
return false;
3381 if (DiscardLeft && (op1->
Pt.
X != Pt.
X)) op1 = op1->
Next;
3382 op1b =
DupOutPt(op1, !DiscardLeft);
3387 op1b =
DupOutPt(op1, !DiscardLeft);
3395 if (!DiscardLeft && (op1->
Pt.
X != Pt.
X)) op1 = op1->
Next;
3410 if (DiscardLeft && (op2->
Pt.
X != Pt.
X)) op2 = op2->
Next;
3411 op2b =
DupOutPt(op2, !DiscardLeft);
3416 op2b =
DupOutPt(op2, !DiscardLeft);
3423 if (!DiscardLeft && (op2->
Pt.
X != Pt.
X)) op2 = op2->
Next;
3453 OutPt *op1 =
j->OutPt1, *op1b;
3454 OutPt *op2 =
j->OutPt2, *op2b;
3463 bool isHorizontal = (
j->OutPt1->Pt.Y ==
j->OffPt.Y);
3465 if (isHorizontal && (
j->OffPt ==
j->OutPt1->Pt) &&
3466 (
j->OffPt ==
j->OutPt2->Pt))
3469 if (outRec1 != outRec2)
return false;
3470 op1b =
j->OutPt1->Next;
3471 while (op1b != op1 && (op1b->Pt ==
j->OffPt))
3473 bool reverse1 = (op1b->Pt.Y >
j->OffPt.Y);
3474 op2b =
j->OutPt2->Next;
3475 while (op2b != op2 && (op2b->Pt ==
j->OffPt))
3477 bool reverse2 = (op2b->Pt.Y >
j->OffPt.Y);
3478 if (reverse1 == reverse2)
return false;
3503 else if (isHorizontal)
3511 while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->
Next != op2)
3513 if (op1b->Next == op1 || op1b->
Next == op2)
return false;
3518 while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->
Next != op1)
3520 if (op2b->Next == op2 || op2b->
Next == op1)
return false;
3524 if (!
GetOverlap(op1->
Pt.
X, op1b->Pt.X, op2->
Pt.
X, op2b->Pt.X, Left, Right))
3531 bool DiscardLeftSide;
3532 if (op1->
Pt.
X >= Left && op1->
Pt.
X <= Right)
3534 Pt = op1->
Pt; DiscardLeftSide = (op1->
Pt.
X > op1b->Pt.X);
3536 else if (op2->
Pt.
X >= Left&& op2->
Pt.
X <= Right)
3538 Pt = op2->
Pt; DiscardLeftSide = (op2->
Pt.
X > op2b->Pt.X);
3540 else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right)
3542 Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->
Pt.
X;
3546 Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->
Pt.
X);
3548 j->OutPt1 = op1;
j->OutPt2 = op2;
3549 return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide);
3558 while ((op1b->Pt == op1->
Pt) && (op1b != op1)) op1b = op1b->
Next;
3559 bool Reverse1 = ((op1b->Pt.Y > op1->
Pt.
Y) ||
3564 while ((op1b->Pt == op1->
Pt) && (op1b != op1)) op1b = op1b->
Prev;
3565 if ((op1b->Pt.Y > op1->
Pt.
Y) ||
3569 while ((op2b->Pt == op2->
Pt) && (op2b != op2))op2b = op2b->
Next;
3570 bool Reverse2 = ((op2b->Pt.Y > op2->
Pt.
Y) ||
3575 while ((op2b->Pt == op2->
Pt) && (op2b != op2)) op2b = op2b->
Prev;
3576 if ((op2b->Pt.Y > op2->
Pt.
Y) ||
3580 if ((op1b == op1) || (op2b == op2) || (op1b == op2b) ||
3581 ((outRec1 == outRec2) && (Reverse1 == Reverse2)))
return false;
3612 while (FirstLeft && !FirstLeft->
Pts)
3621 for (PolyOutList::size_type
i = 0;
i <
m_PolyOuts.size(); ++
i)
3625 if (outRec->
Pts && firstLeft == OldOutRec)
3641 for (PolyOutList::size_type
i = 0;
i <
m_PolyOuts.size(); ++
i)
3645 if (!outRec->
Pts || outRec == OuterOutRec || outRec == InnerOutRec)
3648 if (firstLeft != orfl && firstLeft != InnerOutRec && firstLeft != OuterOutRec)
3662 for (PolyOutList::size_type
i = 0;
i <
m_PolyOuts.size(); ++
i)
3674 for (JoinList::size_type
i = 0;
i <
m_Joins.size();
i++)
3681 if (!outRec1->
Pts || !outRec2->
Pts)
continue;
3687 if (outRec1 == outRec2) holeStateRec = outRec1;
3692 if (!
JoinPoints(join, outRec1, outRec2))
continue;
3694 if (outRec1 == outRec2)
3746 outRec2->
Idx = outRec1->
Idx;
3749 if (holeStateRec == outRec2)
3764 if(pt2.
X == pt1.
X && pt2.
Y == pt1.
Y)
3767 double Dx = (
double)(pt2.
X - pt1.
X);
3768 double dy = (
double)(pt2.
Y - pt1.
Y);
3769 double f = 1 *1.0/ std::sqrt( Dx*Dx + dy*dy );
3804 int highI = (int)path.size() - 1;
3805 if (highI < 0)
return;
3812 while (highI > 0 && path[0] == path[highI]) highI--;
3813 newNode->
Contour.reserve(highI + 1);
3814 newNode->
Contour.push_back(path[0]);
3816 for (
int i = 1;
i <= highI;
i++)
3820 newNode->
Contour.push_back(path[
i]);
3821 if (path[
i].Y > newNode->
Contour[
k].Y ||
3849 for (Paths::size_type
i = 0;
i < paths.size(); ++
i)
3850 AddPath(paths[
i], joinType, endType);
3897 outer[0] =
IntPoint(r.left - 10, r.bottom + 10);
3898 outer[1] =
IntPoint(r.right + 10, r.bottom + 10);
3899 outer[2] =
IntPoint(r.right + 10, r.top - 10);
3900 outer[3] =
IntPoint(r.left - 10, r.top - 10);
3905 if (solution.size() > 0) solution.erase(solution.begin());
3927 outer[0] =
IntPoint(r.left - 10, r.bottom + 10);
3928 outer[1] =
IntPoint(r.right + 10, r.bottom + 10);
3929 outer[2] =
IntPoint(r.right + 10, r.top - 10);
3930 outer[3] =
IntPoint(r.left - 10, r.top - 10);
3979 double steps =
pi / std::acos(1 - y / std::fabs(
delta));
3980 if (steps > std::fabs(
delta) *
pi)
3981 steps = std::fabs(
delta) *
pi;
4002 double X = 1.0, Y = 0.0;
4003 for (
cInt j = 1;
j <= steps;
j++)
4015 double X = -1.0, Y = -1.0;
4016 for (
int j = 0;
j < 4; ++
j)
4022 else if (Y < 0) Y = 1;
4032 for (
int j = 0;
j < len - 1; ++
j)
4042 for (
int j = 0;
j < len; ++
j)
4049 for (
int j = 0;
j < len; ++
j)
4055 for (
int j = len - 1;
j > 0;
j--)
4059 for (
int j = len - 1;
j >= 0;
j--)
4066 for (
int j = 1;
j < len - 1; ++
j)
4093 for (
int j = len - 1;
j > 0;
j--)
4170 double dx = std::tan(std::atan2(
m_sinA,
4196 for (
int i = 0;
i < steps; ++
i)
4216 PolyOutList::size_type
i = 0;
4221 if (!op || outrec->
IsOpen)
continue;
4225 while (op2 != outrec->
Pts)
4227 if ((op->
Pt == op2->
Pt) && op2->
Next != op && op2->
Prev != op)
4271 while (op != outrec->
Pts);
4278 std::reverse(p.begin(), p.end());
4284 for (Paths::size_type
i = 0;
i < p.size(); ++
i)
4292 c.StrictlySimple(
true);
4294 c.Execute(
ctUnion, out_polys, fillType, fillType);
4301 c.StrictlySimple(
true);
4303 c.Execute(
ctUnion, out_polys, fillType, fillType);
4315 double Dx = ((
double)pt1.
X - pt2.
X);
4316 double dy = ((
double)pt1.
Y - pt2.
Y);
4317 return (Dx*Dx + dy*dy);
4332 double C = A * ln1.
X +
B * ln1.
Y;
4333 C = A * pt.
X +
B * pt.
Y - C;
4334 return (C * C) / (A * A +
B *
B);
4346 if ((pt1.
X > pt2.
X) == (pt1.
X < pt3.
X))
4348 else if ((pt2.
X > pt1.
X) == (pt2.
X < pt3.
X))
4355 if ((pt1.
Y > pt2.
Y) == (pt1.
Y < pt3.
Y))
4357 else if ((pt2.
Y > pt1.
Y) == (pt2.
Y < pt3.
Y))
4369 return ((Dx * Dx) + (dy * dy) <= distSqrd);
4388 size_t size = in_poly.size();
4397 for (
size_t i = 0;
i < size; ++
i)
4399 outPts[
i].
Pt = in_poly[
i];
4400 outPts[
i].
Next = &outPts[(
i + 1) % size];
4405 double distSqrd = distance * distance;
4406 OutPt* op = &outPts[0];
4432 if (size < 3) size = 0;
4433 out_poly.resize(size);
4434 for (
size_t i = 0;
i < size; ++
i)
4436 out_poly[
i] = op->
Pt;
4451 out_polys.resize(in_polys.size());
4452 for (Paths::size_type
i = 0;
i < in_polys.size(); ++
i)
4464 Paths& solution,
bool isSum,
bool isClosed)
4466 int delta = (isClosed ? 1 : 0);
4467 size_t polyCnt = poly.size();
4468 size_t pathCnt = path.size();
4470 pp.reserve(pathCnt);
4472 for (
size_t i = 0;
i < pathCnt; ++
i)
4476 for (
size_t j = 0;
j < poly.size(); ++
j)
4477 p.push_back(
IntPoint(path[
i].X + poly[
j].X, path[
i].Y + poly[
j].Y));
4481 for (
size_t i = 0;
i < pathCnt; ++
i)
4485 for (
size_t j = 0;
j < poly.size(); ++
j)
4486 p.push_back(
IntPoint(path[
i].X - poly[
j].X, path[
i].Y - poly[
j].Y));
4491 solution.reserve((pathCnt +
delta) * (polyCnt + 1));
4492 for (
size_t i = 0;
i < pathCnt - 1 +
delta; ++
i)
4493 for (
size_t j = 0;
j < polyCnt; ++
j)
4497 quad.push_back(pp[
i % pathCnt][
j % polyCnt]);
4498 quad.push_back(pp[(
i + 1) % pathCnt][
j % polyCnt]);
4499 quad.push_back(pp[(
i + 1) % pathCnt][(
j + 1) % polyCnt]);
4500 quad.push_back(pp[
i % pathCnt][(
j + 1) % polyCnt]);
4502 solution.push_back(quad);
4509 Minkowski(pattern, path, solution,
true, pathIsClosed);
4519 output.resize(input.size());
4520 for (
size_t i = 0;
i < input.size(); ++
i)
4528 for (
size_t i = 0;
i < paths.size(); ++
i)
4531 Minkowski(pattern, paths[
i], tmp,
true, pathIsClosed);
4537 c.AddPath(tmp2,
ptClip,
true);
4546 Minkowski(poly1, poly2, solution,
false,
true);
4559 else if (nodetype ==
ntOpen)
return;
4561 if (!polynode.
Contour.empty() && match)
4562 paths.push_back(polynode.
Contour);
4571 paths.reserve(polytree.
Total());
4579 paths.reserve(polytree.
Total());
4587 paths.reserve(polytree.
Total());
4590 if (polytree.
Childs[
i]->IsOpen())
4591 paths.push_back(polytree.
Childs[
i]->Contour);
4597 s <<
"(" << p.
X <<
"," << p.
Y <<
")";
4604 if (p.empty())
return s;
4605 Path::size_type last = p.size() -1;
4606 for (Path::size_type
i = 0;
i < last;
i++)
4607 s <<
"(" << p[
i].X <<
"," << p[
i].Y <<
"), ";
4608 s <<
"(" << p[last].X <<
"," << p[last].Y <<
")\n";
4615 for (Paths::size_type
i = 0;
i < p.size();
i++)
std::priority_queue< cInt > ScanbeamList
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed)
TEdge * ProcessBound(TEdge *E, bool IsClockwise)
void DisposeLocalMinimaList()
void UpdateEdgeIntoAEL(TEdge *&e)
virtual bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
void DeleteFromAEL(TEdge *e)
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2)
MinimaList::iterator m_CurrentLM
void InsertScanbeam(const cInt Y)
bool PopScanbeam(cInt &Y)
bool LocalMinimaPending()
void DisposeOutRec(PolyOutList::size_type index)
bool PopLocalMinima(cInt Y, const LocalMinimum *&locMin)
bool FixupIntersectionOrder()
void ProcessHorizontal(TEdge *horzEdge)
void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt)
void InsertEdgeIntoAEL(TEdge *edge, TEdge *startEdge)
void SetWindingCount(TEdge &edge)
void InsertLocalMinimaIntoAEL(const cInt botY)
void ProcessIntersectList()
void BuildResult(Paths &polys)
bool IsContributing(const TEdge &edge) const
OutPt * AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt)
void BuildIntersectList(const cInt topY)
bool JoinPoints(Join *j, OutRec *outRec1, OutRec *outRec2)
bool Execute(ClipType clipType, Paths &solution, PolyFillType fillType=pftEvenOdd)
void AddEdgeToSEL(TEdge *edge)
void AppendPolygon(TEdge *e1, TEdge *e2)
virtual bool ExecuteInternal()
std::list< cInt > MaximaList
OutPt * AddOutPt(TEdge *e, const IntPoint &pt)
void SetHoleState(TEdge *e, OutRec *outrec)
void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt)
OutRec * GetOutRec(int idx)
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt)
void BuildResult2(PolyTree &polytree)
void ProcessHorizontals()
void FixupFirstLefts3(OutRec *OldOutRec, OutRec *NewOutRec)
bool IsEvenOddAltFillType(const TEdge &edge) const
void FixupFirstLefts2(OutRec *InnerOutRec, OutRec *OuterOutRec)
PolyFillType m_SubjFillType
void ProcessEdgesAtTopOfScanbeam(const cInt topY)
bool IsEvenOddFillType(const TEdge &edge) const
void AddGhostJoin(OutPt *op, const IntPoint offPt)
IntersectList m_IntersectList
void FixupFirstLefts1(OutRec *OldOutRec, OutRec *NewOutRec)
bool ProcessIntersections(const cInt topY)
PolyFillType m_ClipFillType
OutPt * GetLastOutPt(TEdge *e)
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2)
void FixHoleLinkage(OutRec &outrec)
Clipper(int initOptions=0)
void DeleteFromSEL(TEdge *e)
bool PopEdgeFromSEL(TEdge *&edge)
void FixupOutPolyline(OutRec &outrec)
void FixupOutPolygon(OutRec &outrec)
void DisposeIntersectNodes()
void AddPath(const Path &path, JoinType joinType, EndType endType)
void AddPaths(const Paths &paths, JoinType joinType, EndType endType)
void DoSquare(int j, int k)
ClipperOffset(double miterLimit=2.0, double roundPrecision=0.25)
void DoOffset(double delta)
void DoRound(int j, int k)
std::vector< DoublePoint > m_normals
void OffsetPoint(int j, int &k, JoinType jointype)
void Execute(Paths &solution, double delta)
void DoMiter(int j, int k, double r)
Int128 & operator+=(const Int128 &rhs)
bool operator==(const Int128 &val) const
bool operator<=(const Int128 &val) const
Int128 & operator-=(const Int128 &rhs)
bool operator<(const Int128 &val) const
Int128(const long64 &_hi, const ulong64 &_lo)
bool operator>(const Int128 &val) const
Int128 & operator=(const long64 &val)
Int128(const Int128 &val)
Int128 operator+(const Int128 &rhs) const
bool operator!=(const Int128 &val) const
bool operator>=(const Int128 &val) const
void AddChild(PolyNode &child)
PolyNode * GetNext() const
PolyNode * GetNextSiblingUp() const
PolyNode * GetFirst() const
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
unsigned long long ulong64
bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range)
void UpdateOutPtIdxs(OutRec &outrec)
bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3)
OutPt * ExcludeOp(OutPt *op)
int PointCount(OutPt *Pts)
bool EdgesAdjacent(const IntersectNode &inode)
void SwapPolyIndexes(TEdge &Edge1, TEdge &Edge2)
void InitEdge(TEdge *e, TEdge *eNext, TEdge *ePrev, const IntPoint &Pt)
OutPt * DupOutPt(OutPt *outPt, bool InsertAfter)
void ReverseHorizontal(TEdge &e)
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType=pftEvenOdd)
void PolyTreeToPaths(const PolyTree &polytree, Paths &paths)
void GetHorzDirection(TEdge &HorzEdge, Direction &Dir, cInt &Left, cInt &Right)
OutRec * GetLowermostRec(OutRec *outRec1, OutRec *outRec2)
void TranslatePath(const Path &input, Path &output, const IntPoint delta)
TEdge * GetMaximaPairEx(TEdge *e)
void AddPolyNodeToPaths(const PolyNode &polynode, NodeType nodetype, Paths &paths)
bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2, cInt &Left, cInt &Right)
double Area(const Path &poly)
std::vector< Path > Paths
void CleanPolygons(const Paths &in_polys, Paths &out_polys, double distance=1.415)
void ReversePolyPtLinks(OutPt *pp)
bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd)
Int128 Int128Mul(long64 lhs, long64 rhs)
DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2)
TEdge * RemoveEdge(TEdge *e)
void Minkowski(const Path &poly, const Path &path, Paths &solution, bool isSum, bool isClosed)
void SwapSides(TEdge &Edge1, TEdge &Edge2)
cInt TopX(TEdge &edge, const cInt currentY)
static cInt const hiRange
bool SlopesNearCollinear(const IntPoint &pt1, const IntPoint &pt2, const IntPoint &pt3, double distSqrd)
TEdge * FindNextLocMin(TEdge *E)
void MinkowskiDiff(const Path &poly1, const Path &poly2, Paths &solution)
bool IsMaxima(TEdge *e, const cInt Y)
bool Orientation(const Path &poly)
void ClosedPathsFromPolyTree(const PolyTree &polytree, Paths &paths)
bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, IntPoint pt2b, IntPoint &pt1, IntPoint &pt2)
bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b)
bool FirstIsBottomPt(const OutPt *btmPt1, const OutPt *btmPt2)
bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2)
bool PointIsVertex(const IntPoint &Pt, OutPt *pp)
TEdge * GetNextInAEL(TEdge *e, Direction dir)
void OpenPathsFromPolyTree(PolyTree &polytree, Paths &paths)
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType=pftEvenOdd)
double DistanceSqrd(const IntPoint &pt1, const IntPoint &pt2)
static double const def_arc_tolerance
void ReversePath(Path &p)
bool OutRec1RightOfOutRec2(OutRec *outRec1, OutRec *outRec2)
static cInt const loRange
void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2)
double DistanceFromLineSqrd(const IntPoint &pt, const IntPoint &ln1, const IntPoint &ln2)
int PointInPolygon(const IntPoint &pt, const Path &path)
void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip)
bool JoinHorz(OutPt *op1, OutPt *op1b, OutPt *op2, OutPt *op2b, const IntPoint Pt, bool DiscardLeft)
void MinkowskiSum(const Path &pattern, const Path &path, Paths &solution, bool pathIsClosed)
Path & operator<<(Path &poly, const IntPoint &p)
OutPt * GetBottomPt(OutPt *pp)
double GetDx(const IntPoint pt1, const IntPoint pt2)
void RangeTest(const IntPoint &Pt, bool &useFullRange)
void ReversePaths(Paths &p)
bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2)
void CleanPolygon(const Path &in_poly, Path &out_poly, double distance=1.415)
void InitEdge2(TEdge &e, PolyType Pt)
static int const Unassigned
bool IntersectListSort(IntersectNode *node1, IntersectNode *node2)
TEdge * GetMaximaPair(TEdge *e)
void DisposeOutPts(OutPt *&pp)
static OutRec * ParseFirstLeft(OutRec *FirstLeft)
std::vector< IntPoint > Path
bool IsIntermediate(TEdge *e, const cInt Y)
void SwapPoints(IntPoint &pt1, IntPoint &pt2)
bool IsHorizontal(TEdge &e)
static double const two_pi
static constexpr double delta
bool operator()(const LocalMinimum &locMin1, const LocalMinimum &locMin2)