private void IntersectEdges(TEdge e1, TEdge e2, IntPoint pt, Protects protects) { Contract.Requires(e1 != null); Contract.Requires(e2 != null); //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before //e2 in AEL except when e1 is being inserted at the intersection point ... var e1Stops = (Protects.Left & protects) == 0 && e1.NextInLML == null && e1.XTop == pt.X && e1.YTop == pt.Y; var e2Stops = (Protects.Right & protects) == 0 && e2.NextInLML == null && e2.XTop == pt.X && e2.YTop == pt.Y; var e1Contributing = e1.OutIdx >= 0; var e2Contributing = e2.OutIdx >= 0; //update winding counts... //assumes that e1 will be to the right of e2 ABOVE the intersection if (e1.PolyType == e2.PolyType) { if (IsEvenOddFillType(e1)) { var oldE1WindCnt = e1.WindCnt; e1.WindCnt = e2.WindCnt; e2.WindCnt = oldE1WindCnt; } else { if (e1.WindCnt + e2.WindDelta == 0) e1.WindCnt = -e1.WindCnt; else e1.WindCnt += e2.WindDelta; if (e2.WindCnt - e1.WindDelta == 0) e2.WindCnt = -e2.WindCnt; else e2.WindCnt -= e1.WindDelta; } } else { if (!IsEvenOddFillType(e2)) e1.WindCnt2 += e2.WindDelta; else e1.WindCnt2 = e1.WindCnt2 == 0 ? 1 : 0; if (!IsEvenOddFillType(e1)) e2.WindCnt2 -= e1.WindDelta; else e2.WindCnt2 = e2.WindCnt2 == 0 ? 1 : 0; } PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; if (e1.PolyType == PolyType.Subject) { e1FillType = _subjFillType; e1FillType2 = _clipFillType; } else { e1FillType = _clipFillType; e1FillType2 = _subjFillType; } if (e2.PolyType == PolyType.Subject) { e2FillType = _subjFillType; e2FillType2 = _clipFillType; } else { e2FillType = _clipFillType; e2FillType2 = _subjFillType; } int e1Wc, e2Wc; switch (e1FillType) { case PolyFillType.Positive: e1Wc = e1.WindCnt; break; case PolyFillType.Negative: e1Wc = -e1.WindCnt; break; default: e1Wc = Math.Abs(e1.WindCnt); break; } switch (e2FillType) { case PolyFillType.Positive: e2Wc = e2.WindCnt; break; case PolyFillType.Negative: e2Wc = -e2.WindCnt; break; default: e2Wc = Math.Abs(e2.WindCnt); break; } if (e1Contributing && e2Contributing) { if (e1Stops || e2Stops || (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || (e1.PolyType != e2.PolyType && _clipType != ClipType.Xor)) AddLocalMaxPoly(e1, e2, pt); else { AddOutPt(e1, pt); AddOutPt(e2, pt); InternalHelpers.Swap(ref e1.Side, ref e2.Side); InternalHelpers.Swap(ref e1.OutIdx, ref e2.OutIdx); } } else if (e1Contributing) { if (e2Wc == 0 || e2Wc == 1) { AddOutPt(e1, pt); InternalHelpers.Swap(ref e1.Side, ref e2.Side); InternalHelpers.Swap(ref e1.OutIdx, ref e2.OutIdx); } } else if (e2Contributing) { if (e1Wc == 0 || e1Wc == 1) { AddOutPt(e2, pt); InternalHelpers.Swap(ref e1.Side, ref e2.Side); InternalHelpers.Swap(ref e1.OutIdx, ref e2.OutIdx); } } else if ((e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1) && !e1Stops && !e2Stops) { //neither edge is currently contributing ... long e1Wc2, e2Wc2; switch (e1FillType2) { case PolyFillType.Positive: e1Wc2 = e1.WindCnt2; break; case PolyFillType.Negative: e1Wc2 = -e1.WindCnt2; break; default: e1Wc2 = Math.Abs(e1.WindCnt2); break; } switch (e2FillType2) { case PolyFillType.Positive: e2Wc2 = e2.WindCnt2; break; case PolyFillType.Negative: e2Wc2 = -e2.WindCnt2; break; default: e2Wc2 = Math.Abs(e2.WindCnt2); break; } if (e1.PolyType != e2.PolyType) AddLocalMinPoly(e1, e2, pt); else if (e1Wc == 1 && e2Wc == 1) switch (_clipType) { case ClipType.Intersection: if (e1Wc2 > 0 && e2Wc2 > 0) AddLocalMinPoly(e1, e2, pt); break; case ClipType.Union: if (e1Wc2 <= 0 && e2Wc2 <= 0) AddLocalMinPoly(e1, e2, pt); break; case ClipType.Difference: if (((e1.PolyType == PolyType.Clip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || ((e1.PolyType == PolyType.Subject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) AddLocalMinPoly(e1, e2, pt); break; case ClipType.Xor: AddLocalMinPoly(e1, e2, pt); break; } else InternalHelpers.Swap(ref e1.Side, ref e2.Side); } if ((e1Stops != e2Stops) && ((e1Stops && (e1.OutIdx >= 0)) || (e2Stops && (e2.OutIdx >= 0)))) { InternalHelpers.Swap(ref e1.Side, ref e2.Side); InternalHelpers.Swap(ref e1.OutIdx, ref e2.OutIdx); } //finally, delete any non-contributing maxima edges ... if (e1Stops) DeleteFromAEL(e1); if (e2Stops) DeleteFromAEL(e2); }
//------------------------------------------------------------------------------ private void IntersectEdges(TEdge e1, TEdge e2, IntPoint pt, Protects protects) { //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before //e2 in AEL except when e1 is being inserted at the intersection point ... bool e1stops = (Protects.ipLeft & protects) == 0 && e1.nextInLML == null && e1.xtop == pt.X && e1.ytop == pt.Y; bool e2stops = (Protects.ipRight & protects) == 0 && e2.nextInLML == null && e2.xtop == pt.X && e2.ytop == pt.Y; bool e1Contributing = (e1.outIdx >= 0); bool e2contributing = (e2.outIdx >= 0); //update winding counts... //assumes that e1 will be to the right of e2 ABOVE the intersection if (e1.polyType == e2.polyType) { if (IsEvenOddFillType(e1)) { int oldE1WindCnt = e1.windCnt; e1.windCnt = e2.windCnt; e2.windCnt = oldE1WindCnt; } else { if (e1.windCnt + e2.windDelta == 0) e1.windCnt = -e1.windCnt; else e1.windCnt += e2.windDelta; if (e2.windCnt - e1.windDelta == 0) e2.windCnt = -e2.windCnt; else e2.windCnt -= e1.windDelta; } } else { if (!IsEvenOddFillType(e2)) e1.windCnt2 += e2.windDelta; else e1.windCnt2 = (e1.windCnt2 == 0) ? 1 : 0; if (!IsEvenOddFillType(e1)) e2.windCnt2 -= e1.windDelta; else e2.windCnt2 = (e2.windCnt2 == 0) ? 1 : 0; } PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; if (e1.polyType == PolyType.ptSubject) { e1FillType = m_SubjFillType; e1FillType2 = m_ClipFillType; } else { e1FillType = m_ClipFillType; e1FillType2 = m_SubjFillType; } if (e2.polyType == PolyType.ptSubject) { e2FillType = m_SubjFillType; e2FillType2 = m_ClipFillType; } else { e2FillType = m_ClipFillType; e2FillType2 = m_SubjFillType; } int e1Wc, e2Wc; switch (e1FillType) { case PolyFillType.pftPositive: e1Wc = e1.windCnt; break; case PolyFillType.pftNegative: e1Wc = -e1.windCnt; break; default: e1Wc = Math.Abs(e1.windCnt); break; } switch (e2FillType) { case PolyFillType.pftPositive: e2Wc = e2.windCnt; break; case PolyFillType.pftNegative: e2Wc = -e2.windCnt; break; default: e2Wc = Math.Abs(e2.windCnt); break; } if (e1Contributing && e2contributing) { if ( e1stops || e2stops || (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || (e1.polyType != e2.polyType && m_ClipType != ClipType.ctXor)) AddLocalMaxPoly(e1, e2, pt); else DoBothEdges(e1, e2, pt); } else if (e1Contributing) { if ((e2Wc == 0 || e2Wc == 1) && (m_ClipType != ClipType.ctIntersection || e2.polyType == PolyType.ptSubject || (e2.windCnt2 != 0))) DoEdge1(e1, e2, pt); } else if (e2contributing) { if ((e1Wc == 0 || e1Wc == 1) && (m_ClipType != ClipType.ctIntersection || e1.polyType == PolyType.ptSubject || (e1.windCnt2 != 0))) DoEdge2(e1, e2, pt); } else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops ) { //neither edge is currently contributing ... Int64 e1Wc2, e2Wc2; switch (e1FillType2) { case PolyFillType.pftPositive: e1Wc2 = e1.windCnt2; break; case PolyFillType.pftNegative: e1Wc2 = -e1.windCnt2; break; default: e1Wc2 = Math.Abs(e1.windCnt2); break; } switch (e2FillType2) { case PolyFillType.pftPositive: e2Wc2 = e2.windCnt2; break; case PolyFillType.pftNegative: e2Wc2 = -e2.windCnt2; break; default: e2Wc2 = Math.Abs(e2.windCnt2); break; } if (e1.polyType != e2.polyType) AddLocalMinPoly(e1, e2, pt); else if (e1Wc == 1 && e2Wc == 1) switch (m_ClipType) { case ClipType.ctIntersection: { if (e1Wc2 > 0 && e2Wc2 > 0) AddLocalMinPoly(e1, e2, pt); break; } case ClipType.ctUnion: { if (e1Wc2 <= 0 && e2Wc2 <= 0) AddLocalMinPoly(e1, e2, pt); break; } case ClipType.ctDifference: { if (e1.polyType == PolyType.ptClip && e1Wc2 > 0 && e2Wc2 > 0 || e1.polyType == PolyType.ptSubject && e1Wc2 <= 0 && e2Wc2 <= 0) AddLocalMinPoly(e1, e2, pt); break; } case ClipType.ctXor: { AddLocalMinPoly(e1, e2, pt); break; } } else SwapSides(e1, e2); } if ((e1stops != e2stops) && ((e1stops && (e1.outIdx >= 0)) || (e2stops && (e2.outIdx >= 0)))) { SwapSides(e1, e2); SwapPolyIndexes(e1, e2); } //finally, delete any non-contributing maxima edges ... if (e1stops) DeleteFromAEL(e1); if (e2stops) DeleteFromAEL(e2); }
//------------------------------------------------------------------------------ private void IntersectEdges(TEdge4 e1, TEdge4 e2, IntPoint pt, Protects protects) { //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before //e2 in AEL except when e1 is being inserted at the intersection point ... bool e1stops = (Protects.ipLeft & protects) == 0 && e1.nextInLML == null && e1.xtop == pt.X && e1.ytop == pt.Y; bool e2stops = (Protects.ipRight & protects) == 0 && e2.nextInLML == null && e2.xtop == pt.X && e2.ytop == pt.Y; bool e1Contributing = (e1.outIdx >= 0); bool e2contributing = (e2.outIdx >= 0); //update winding counts... //assumes that e1 will be to the right of e2 ABOVE the intersection if (e1.polyType == e2.polyType) { if (IsNonZeroFillType(e1)) { if (e1.windCnt + e2.windDelta == 0) e1.windCnt = -e1.windCnt; else e1.windCnt += e2.windDelta; if (e2.windCnt - e1.windDelta == 0) e2.windCnt = -e2.windCnt; else e2.windCnt -= e1.windDelta; } else { int oldE1WindCnt = e1.windCnt; e1.windCnt = e2.windCnt; e2.windCnt = oldE1WindCnt; } } else { if (IsNonZeroFillType(e2)) e1.windCnt2 += e2.windDelta; else e1.windCnt2 = (e1.windCnt2 == 0) ? 1 : 0; if (IsNonZeroFillType(e1)) e2.windCnt2 -= e1.windDelta; else e2.windCnt2 = (e2.windCnt2 == 0) ? 1 : 0; } if (e1Contributing && e2contributing) { if (e1stops || e2stops || Math.Abs(e1.windCnt) > 1 || Math.Abs(e2.windCnt) > 1 || (e1.polyType != e2.polyType && m_ClipType != ClipType.ctXor)) AddLocalMaxPoly(e1, e2, pt); else DoBothEdges(e1, e2, pt); } else if (e1Contributing) { if (m_ClipType == ClipType.ctIntersection) { if ((e2.polyType == PolyType.ptSubject || e2.windCnt2 != 0) && Math.Abs(e2.windCnt) < 2) DoEdge1(e1, e2, pt); } else { if (Math.Abs(e2.windCnt) < 2) DoEdge1(e1, e2, pt); } } else if (e2contributing) { if (m_ClipType == ClipType.ctIntersection) { if ((e1.polyType == PolyType.ptSubject || e1.windCnt2 != 0) && Math.Abs(e1.windCnt) < 2) DoEdge2(e1, e2, pt); } else { if (Math.Abs(e1.windCnt) < 2) DoEdge2(e1, e2, pt); } } else if (Math.Abs(e1.windCnt) < 2 && Math.Abs(e2.windCnt) < 2) { //neither edge is currently contributing ... if (e1.polyType != e2.polyType && !e1stops && !e2stops && Math.Abs(e1.windCnt) < 2 && Math.Abs(e2.windCnt) < 2) AddLocalMinPoly(e1, e2, pt); else if (Math.Abs(e1.windCnt) == 1 && Math.Abs(e2.windCnt) == 1) switch (m_ClipType) { case ClipType.ctIntersection: { if (Math.Abs(e1.windCnt2) > 0 && Math.Abs(e2.windCnt2) > 0) AddLocalMinPoly(e1, e2, pt); break; } case ClipType.ctUnion: { if (e1.windCnt2 == 0 && e2.windCnt2 == 0) AddLocalMinPoly(e1, e2, pt); break; } case ClipType.ctDifference: { if ((e1.polyType == PolyType.ptClip && e2.polyType == PolyType.ptClip && e1.windCnt2 != 0 && e2.windCnt2 != 0) || (e1.polyType == PolyType.ptSubject && e2.polyType == PolyType.ptSubject && e1.windCnt2 == 0 && e2.windCnt2 == 0)) AddLocalMinPoly(e1, e2, pt); break; } case ClipType.ctXor: { AddLocalMinPoly(e1, e2, pt); break; } } else if (Math.Abs(e1.windCnt) < 2 && Math.Abs(e2.windCnt) < 2) SwapSides(e1, e2); } if ((e1stops != e2stops) && ((e1stops && (e1.outIdx >= 0)) || (e2stops && (e2.outIdx >= 0)))) { SwapSides(e1, e2); SwapPolyIndexes(e1, e2); } //finally, delete any non-contributing maxima edges ... if (e1stops) DeleteFromAEL(e1); if (e2stops) DeleteFromAEL(e2); }