//------------------------------------------------------------------------------ double Area(OutRec outRec, bool UseFull64BitRange) { OutPt op = outRec.pts; if (UseFull64BitRange) { Int128 a = new Int128(0); do { a += Int128.Int128Mul(op.prev.pt.X, op.pt.Y) - Int128.Int128Mul(op.pt.X, op.prev.pt.Y); op = op.next; } while (op != outRec.pts); return a.ToDouble() / 2; } else { double a = 0; do { a += (op.prev.pt.X * op.pt.Y) - (op.pt.X * op.prev.pt.Y); op = op.next; } while (op != outRec.pts); return a/2; } }
//------------------------------------------------------------------------------ private void CheckHoleLinkages1(OutRec outRec1, OutRec outRec2) { //when a polygon is split into 2 polygons, make sure any holes the original //polygon contained link to the correct polygon ... for (int i = 0; i < m_PolyOuts.Count; ++i) { if (m_PolyOuts[i].isHole && m_PolyOuts[i].bottomPt != null && m_PolyOuts[i].FirstLeft == outRec1 && !PointInPolygon(m_PolyOuts[i].bottomPt.pt, outRec1.pts, m_UseFullRange)) m_PolyOuts[i].FirstLeft = outRec2; } }
//---------------------------------------------------------------------- private void CheckHoleLinkages2(OutRec outRec1, OutRec outRec2) { //if a hole is owned by outRec2 then make it owned by outRec1 ... for (int i = 0; i < m_PolyOuts.Count; ++i) if (m_PolyOuts[i].isHole && m_PolyOuts[i].bottomPt != null && m_PolyOuts[i].FirstLeft == outRec2) m_PolyOuts[i].FirstLeft = outRec1; }
//------------------------------------------------------------------------------ private bool Orientation(OutRec outRec, bool UseFull64BitRange) { //first make sure bottomPt is correctly assigned ... OutPt opBottom = outRec.pts, op = outRec.pts.next; while (op != outRec.pts) { if (op.pt.Y >= opBottom.pt.Y) { if (op.pt.Y > opBottom.pt.Y || op.pt.X < opBottom.pt.X) opBottom = op; } op = op.next; } outRec.bottomPt = opBottom; opBottom.idx = outRec.idx; op = opBottom; //find vertices either side of bottomPt (skipping duplicate points) .... OutPt opPrev = op.prev; OutPt opNext = op.next; while (op != opPrev && PointsEqual(op.pt, opPrev.pt)) opPrev = opPrev.prev; while (op != opNext && PointsEqual(op.pt, opNext.pt)) opNext = opNext.next; IntPoint vec1 = new IntPoint(op.pt.X - opPrev.pt.X, op.pt.Y - opPrev.pt.Y); IntPoint vec2 = new IntPoint(opNext.pt.X - op.pt.X, opNext.pt.Y - op.pt.Y); if (UseFull64BitRange) { Int128 cross = Int128.Int128Mul(vec1.X, vec2.Y) - Int128.Int128Mul(vec2.X, vec1.Y); return !cross.IsNegative(); } else return (vec1.X * vec2.Y - vec2.X * vec1.Y) > 0; }
//------------------------------------------------------------------------------ private void FixupOutPolygon(OutRec outRec) { //FixupOutPolygon() - removes duplicate points and simplifies consecutive //parallel edges by removing the middle vertex. OutPt lastOK = null; outRec.pts = outRec.bottomPt; OutPt pp = outRec.bottomPt; for (;;) { if (pp.prev == pp || pp.prev == pp.next) { DisposeOutPts(pp); outRec.pts = null; outRec.bottomPt = null; return; } //test for duplicate points and for same slope (cross-product) ... if (PointsEqual(pp.pt, pp.next.pt) || SlopesEqual(pp.prev.pt, pp.pt, pp.next.pt, m_UseFullRange)) { lastOK = null; if (pp == outRec.bottomPt) outRec.bottomPt = null; //flags need for updating pp.prev.next = pp.next; pp.next.prev = pp.prev; pp = pp.prev; } else if (pp == lastOK) break; else { if (lastOK == null) lastOK = pp; pp = pp.next; } } if (outRec.bottomPt == null) { outRec.bottomPt = GetBottomPt(pp); outRec.bottomPt.idx = outRec.idx; outRec.pts = outRec.bottomPt; } }
//------------------------------------------------------------------------------ private void SetHoleState(TEdge e, OutRec outRec) { bool isHole = false; TEdge e2 = e.prevInAEL; while (e2 != null) { if (e2.outIdx >= 0) { isHole = !isHole; if (outRec.FirstLeft == null) outRec.FirstLeft = m_PolyOuts[e2.outIdx]; } e2 = e2.prevInAEL; } if (isHole) outRec.isHole = true; }
//------------------------------------------------------------------------------ private OutRec GetLowermostRec(OutRec outRec1, OutRec outRec2) { //work out which polygon fragment has the correct hole state ... OutPt bPt1 = outRec1.bottomPt; OutPt bPt2 = outRec2.bottomPt; if (bPt1.pt.Y > bPt2.pt.Y) return outRec1; else if (bPt1.pt.Y < bPt2.pt.Y) return outRec2; else if (bPt1.pt.X < bPt2.pt.X) return outRec1; else if (bPt1.pt.X > bPt2.pt.X) return outRec2; else if (bPt1.next == bPt1) return outRec2; else if (bPt2.next == bPt2) return outRec1; else if (FirstIsBottomPt(bPt1, bPt2)) return outRec1; else return outRec2; }
//------------------------------------------------------------------------------ private OutRec CreateOutRec() { OutRec result = new OutRec(); result.idx = -1; result.isHole = false; result.FirstLeft = null; result.AppendLink = null; result.pts = null; result.bottomPt = null; result.bottomFlag = null; result.sides = EdgeSide.esNeither; return result; }
//------------------------------------------------------------------------------ void DisposeBottomPt(OutRec outRec) { OutPt next = outRec.bottomPt.next; OutPt prev = outRec.bottomPt.prev; if (outRec.pts == outRec.bottomPt) outRec.pts = next; outRec.bottomPt = null; next.prev = prev; prev.next = next; outRec.bottomPt = next; }
//------------------------------------------------------------------------------ internal void FixHoleLinkage(OutRec outRec) { OutRec tmp; if (outRec.bottomPt != null) tmp = m_PolyOuts[outRec.bottomPt.idx].FirstLeft; else tmp = outRec.FirstLeft; if (outRec == tmp) throw new ClipperException("HoleLinkage error"); if (tmp != null) { if (tmp.AppendLink != null) tmp = FindAppendLinkEnd(tmp); if (tmp == outRec) tmp = null; else if (tmp.isHole) { FixHoleLinkage(tmp); tmp = tmp.FirstLeft; } } outRec.FirstLeft = tmp; if (tmp == null) outRec.isHole = false; outRec.AppendLink = null; }
//------------------------------------------------------------------------------ internal OutRec FindAppendLinkEnd(OutRec outRec) { while (outRec.AppendLink != null) outRec = outRec.AppendLink; return outRec; }
//------------------------------------------------------------------------------ internal int PolySort(OutRec or1, OutRec or2) { if (or1 == or2) return 0; else if (or1.pts == null || or2.pts == null) { if ((or1.pts == null) != (or2.pts == null)) { return or1.pts == null ? 1 : -1; } else return 0; } int i1, i2; if (or1.isHole) i1 = or1.FirstLeft.idx; else i1 = or1.idx; if (or2.isHole) i2 = or2.FirstLeft.idx; else i2 = or2.idx; int result = i1 - i2; if (result == 0 && (or1.isHole != or2.isHole)) { return or1.isHole ? 1 : -1; } return result; }