private static void ReversePolyPtLinks(OutPt pp) { if (pp == null) return; var pp1 = pp; do { var pp2 = pp1.Next; pp1.Next = pp1.Prev; pp1.Prev = pp2; pp1 = pp2; } while (pp1 != pp); }
private void AddOutPt(TEdge e, IntPoint pt) { Contract.Requires(e != null); Contract.Requires(e.OutIdx < 0 || e.OutIdx < _polyOuts.Count); var toFront = e.Side == EdgeSide.Left; if (e.OutIdx < 0) { var outRec = CreateOutRec(); e.OutIdx = outRec.Idx; var op = new OutPt(); outRec.Pts = op; op.Pt = pt; op.Next = op; op.Prev = op; SetHoleState(e, outRec); } else { var outRec = _polyOuts[e.OutIdx]; var op = outRec.Pts; if (toFront && pt.Equals(op.Pt) || (!toFront && pt.Equals(op.Prev.Pt))) return; var op2 = new OutPt { Pt = pt, Next = op, Prev = op.Prev }; op2.Prev.Next = op2; op.Prev = op2; if (toFront) outRec.Pts = op2; } }
private static int PointCount(OutPt pts) { if (pts == null) return 0; var result = 0; var p = pts; do { result++; p = p.Next; } while (p != pts); return result; }
private static bool Poly2ContainsPoly1(OutPt outPt1, OutPt outPt2) { Contract.Requires(outPt1 != null); Contract.Requires(outPt2 != null); var pt = outPt1; //Because the polygons may be touching, we need to find a vertex that //isn't touching the other polygon ... if (InternalHelpers.PointOnPolygon(pt.Pt, outPt2)) { pt = pt.Next; while (pt != outPt1 && InternalHelpers.PointOnPolygon(pt.Pt, outPt2)) pt = pt.Next; if (pt == outPt1) return true; } return InternalHelpers.PointInPolygon(pt.Pt, outPt2); }
private static OutPt InsertPolyPtBetween(OutPt p1, OutPt p2, IntPoint pt) { Contract.Requires(p1 != null); Contract.Requires(p2 != null); Contract.Ensures(Contract.Result<OutPt>() != null); var result = new OutPt {Pt = pt}; if (p2 == p1.Next) { p1.Next = result; p2.Prev = result; result.Next = p2; result.Prev = p1; } else { p2.Next = result; p1.Prev = result; result.Next = p1; result.Prev = p2; } return result; }
private static bool FindSegment(ref OutPt pp, ref IntPoint pt1, ref IntPoint pt2) { if (pp == null) return false; var pp2 = pp; var pt1A = pt1; var pt2A = pt2; do { if (InternalHelpers.SlopesEqual(pt1A, pt2A, pp.Pt, pp.Prev.Pt) && InternalHelpers.SlopesEqual(pt1A, pt2A, pp.Pt) && GetOverlapSegment(pt1A, pt2A, pp.Pt, pp.Prev.Pt, out pt1, out pt2)) return true; pp = pp.Next; } while (pp != pp2); return false; }
private static void DisposeOutPts(OutPt pp) { Contract.Requires(pp == null || pp.Prev != null); if (pp == null) return; pp.Prev.Next = null; while (pp != null) { pp = pp.Next; } }
private bool JoinPoints(JoinRec j, out OutPt p1, out OutPt p2) { Contract.Requires(j != null); Contract.Requires(j.Poly1Idx >= 0 && j.Poly1Idx < _polyOuts.Count); Contract.Requires(j.Poly2Idx >= 0 && j.Poly2Idx < _polyOuts.Count); p1 = null; p2 = null; var outRec1 = _polyOuts[j.Poly1Idx]; var outRec2 = _polyOuts[j.Poly2Idx]; if (outRec1 == null || outRec2 == null) return false; var pp1A = outRec1.Pts; var pp2A = outRec2.Pts; IntPoint pt1 = j.Pt2A, pt2 = j.Pt2B; IntPoint pt3 = j.Pt1A, pt4 = j.Pt1B; if (!FindSegment(ref pp1A, ref pt1, ref pt2)) return false; if (outRec1 == outRec2) { //we're searching the same polygon for overlapping segments so //segment 2 mustn't be the same as segment 1 ... pp2A = pp1A.Next; if (!FindSegment(ref pp2A, ref pt3, ref pt4) || (pp2A == pp1A)) return false; } else if (!FindSegment(ref pp2A, ref pt3, ref pt4)) return false; if (!GetOverlapSegment(pt1, pt2, pt3, pt4, out pt1, out pt2)) return false; OutPt p3, p4, prev = pp1A.Prev; //get p1 & p2 polypts - the overlap start & endpoints on poly1 if (pp1A.Pt.Equals(pt1)) p1 = pp1A; else if (prev.Pt.Equals(pt1)) p1 = prev; else p1 = InsertPolyPtBetween(pp1A, prev, pt1); if (pp1A.Pt.Equals(pt2)) p2 = pp1A; else if (prev.Pt.Equals(pt2)) p2 = prev; else if ((p1 == pp1A) || (p1 == prev)) p2 = InsertPolyPtBetween(pp1A, prev, pt2); else if (Pt3IsBetweenPt1AndPt2(pp1A.Pt, p1.Pt, pt2)) p2 = InsertPolyPtBetween(pp1A, p1, pt2); else p2 = InsertPolyPtBetween(p1, prev, pt2); //get p3 & p4 polypts - the overlap start & endpoints on poly2 prev = pp2A.Prev; if (pp2A.Pt.Equals(pt1)) p3 = pp2A; else if (prev.Pt.Equals(pt1)) p3 = prev; else p3 = InsertPolyPtBetween(pp2A, prev, pt1); if (pp2A.Pt.Equals(pt2)) p4 = pp2A; else if (prev.Pt.Equals(pt2)) p4 = prev; else if ((p3 == pp2A) || (p3 == prev)) p4 = InsertPolyPtBetween(pp2A, prev, pt2); else if (Pt3IsBetweenPt1AndPt2(pp2A.Pt, p3.Pt, pt2)) p4 = InsertPolyPtBetween(pp2A, p3, pt2); else p4 = InsertPolyPtBetween(p3, prev, pt2); //p1.pt == p3.pt and p2.pt == p4.pt so join p1 to p3 and p2 to p4 ... if (p1.Next == p2 && p3.Prev == p4) { p1.Next = p3; p3.Prev = p1; p2.Prev = p4; p4.Next = p2; return true; } else if (p1.Prev == p2 && p3.Next == p4) { p1.Prev = p3; p3.Next = p1; p2.Next = p4; p4.Prev = p2; return true; } else return false; //an orientation is probably wrong }
private void FixupJoinRecs(JoinRec j, OutPt pt, int startIdx) { for (var k = startIdx; k < _joins.Count; k++) { var j2 = _joins[k]; if (j2.Poly1Idx == j.Poly1Idx && InternalHelpers.PointIsVertex(j2.Pt1A, pt)) j2.Poly1Idx = j.Poly2Idx; if (j2.Poly2Idx == j.Poly1Idx && InternalHelpers.PointIsVertex(j2.Pt2A, pt)) j2.Poly2Idx = j.Poly2Idx; } }