//------------------------------------------------------------------------------ private void AddGhostJoin(OutPt Op, IntPoint OffPt) { Join j = new Join(); j.OutPt1 = Op; j.OffPt = OffPt; m_GhostJoins.Add(j); }
//------------------------------------------------------------------------------ private bool JoinPoints(Join j, out OutPt p1, out OutPt p2) { OutRec outRec1 = GetOutRec(j.OutPt1.Idx); OutRec outRec2 = GetOutRec(j.OutPt2.Idx); OutPt op1 = j.OutPt1, op1b; OutPt op2 = j.OutPt2, op2b; p1 = null; p2 = null; //There are 3 kinds of joins for output polygons ... //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are a 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). //3. StrictlySimple joins where edges touch but are not collinear and where //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point. bool isHorizontal = (j.OutPt1.Pt.Y == j.OffPt.Y); if (isHorizontal && (j.OffPt == j.OutPt1.Pt) && (j.OffPt == j.OutPt2.Pt)) { //Strictly Simple join ... op1b = j.OutPt1.Next; while (op1b != op1 && (op1b.Pt == j.OffPt)) op1b = op1b.Next; bool reverse1 = (op1b.Pt.Y > j.OffPt.Y); op2b = j.OutPt2.Next; while (op2b != op2 && (op2b.Pt == j.OffPt)) op2b = op2b.Next; bool reverse2 = (op2b.Pt.Y > j.OffPt.Y); if (reverse1 == reverse2) return false; if (reverse1) { op1b = DupOutPt(op1, false); op2b = DupOutPt(op2, true); op1.Prev = op2; op2.Next = op1; op1b.Next = op2b; op2b.Prev = op1b; p1 = op1; p2 = op1b; return true; } else { op1b = DupOutPt(op1, true); op2b = DupOutPt(op2, false); op1.Next = op2; op2.Prev = op1; op1b.Prev = op2b; op2b.Next = op1b; p1 = op1; p2 = op1b; return true; } } else if (isHorizontal) { //treat horizontal joins differently to non-horizontal joins since with //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt //may be anywhere along the horizontal edge. op1b = op1; while (op1.Prev.Pt.Y == op1.Pt.Y && op1.Prev != op1b && op1.Prev != op2) op1 = op1.Prev; while (op1b.Next.Pt.Y == op1b.Pt.Y && op1b.Next != op1 && op1b.Next != op2) op1b = op1b.Next; if (op1b.Next == op1 || op1b.Next == op2) return false; //a flat 'polygon' op2b = op2; while (op2.Prev.Pt.Y == op2.Pt.Y && op2.Prev != op2b && op2.Prev != op1b) op2 = op2.Prev; while (op2b.Next.Pt.Y == op2b.Pt.Y && op2b.Next != op2 && op2b.Next != op1) op2b = op2b.Next; if (op2b.Next == op2 || op2b.Next == op1) return false; //a flat 'polygon' cInt Left, Right; //Op1 -. Op1b & Op2 -. Op2b are the extremites of the horizontal edges if (!GetOverlap(op1.Pt.X, op1b.Pt.X, op2.Pt.X, op2b.Pt.X, out Left, out Right)) return false; //DiscardLeftSide: when overlapping edges are joined, a spike will created //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up //on the discard Side as either may still be needed for other joins ... IntPoint Pt; bool DiscardLeftSide; if (op1.Pt.X >= Left && op1.Pt.X <= Right) { Pt = op1.Pt; DiscardLeftSide = (op1.Pt.X > op1b.Pt.X); } else if (op2.Pt.X >= Left&& op2.Pt.X <= Right) { Pt = op2.Pt; DiscardLeftSide = (op2.Pt.X > op2b.Pt.X); } else if (op1b.Pt.X >= Left && op1b.Pt.X <= Right) { Pt = op1b.Pt; DiscardLeftSide = op1b.Pt.X > op1.Pt.X; } else { Pt = op2b.Pt; DiscardLeftSide = (op2b.Pt.X > op2.Pt.X); } p1 = op1; p2 = op2; return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide); } else { //nb: For non-horizontal joins ... // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y // 2. Jr.OutPt1.Pt > Jr.OffPt.Y //make sure the polygons are correctly oriented ... op1b = op1.Next; while ((op1b.Pt == op1.Pt) && (op1b != op1)) op1b = op1b.Next; bool Reverse1 = ((op1b.Pt.Y > op1.Pt.Y) || !SlopesEqual(op1.Pt, op1b.Pt, j.OffPt, m_UseFullRange)); if (Reverse1) { op1b = op1.Prev; while ((op1b.Pt == op1.Pt) && (op1b != op1)) op1b = op1b.Prev; if ((op1b.Pt.Y > op1.Pt.Y) || !SlopesEqual(op1.Pt, op1b.Pt, j.OffPt, m_UseFullRange)) return false; }; op2b = op2.Next; while ((op2b.Pt == op2.Pt) && (op2b != op2)) op2b = op2b.Next; bool Reverse2 = ((op2b.Pt.Y > op2.Pt.Y) || !SlopesEqual(op2.Pt, op2b.Pt, j.OffPt, m_UseFullRange)); if (Reverse2) { op2b = op2.Prev; while ((op2b.Pt == op2.Pt) && (op2b != op2)) op2b = op2b.Prev; if ((op2b.Pt.Y > op2.Pt.Y) || !SlopesEqual(op2.Pt, op2b.Pt, j.OffPt, m_UseFullRange)) return false; } if ((op1b == op1) || (op2b == op2) || (op1b == op2b) || ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false; if (Reverse1) { op1b = DupOutPt(op1, false); op2b = DupOutPt(op2, true); op1.Prev = op2; op2.Next = op1; op1b.Next = op2b; op2b.Prev = op1b; p1 = op1; p2 = op1b; return true; } else { op1b = DupOutPt(op1, true); op2b = DupOutPt(op2, false); op1.Next = op2; op2.Prev = op1; op1b.Prev = op2b; op2b.Next = op1b; p1 = op1; p2 = op1b; return true; } } }
//------------------------------------------------------------------------------ private void AddJoin(OutPt Op1, OutPt Op2, IntPoint OffPt) { Join j = new Join(); j.OutPt1 = Op1; j.OutPt2 = Op2; j.OffPt = OffPt; m_Joins.Add(j); }