Beispiel #1
0
        //------------------------------------------------------------------------------


        private void AddLocalMaxPoly(TEdge e1, TEdge e2, IntPoint pt)
        {
            AddOutPt(e1, pt);
            if (e1.outIdx == e2.outIdx)
            {
                e1.outIdx = -1;
                e2.outIdx = -1;
            }
            else if (e1.outIdx < e2.outIdx)
                AppendPolygon(e1, e2);
            else
                AppendPolygon(e2, e1);
        }
Beispiel #2
0
        //------------------------------------------------------------------------------

        private void InitEdge(TEdge e, TEdge eNext,
          TEdge ePrev, IntPoint pt, PolyType polyType)
        {
            e.next = eNext;
            e.prev = ePrev;
            e.xcurr = pt.X;
            e.ycurr = pt.Y;
            if (e.ycurr >= e.next.ycurr)
            {
                e.xbot = e.xcurr;
                e.ybot = e.ycurr;
                e.xtop = e.next.xcurr;
                e.ytop = e.next.ycurr;
                e.windDelta = 1;
            }
            else
            {
                e.xtop = e.xcurr;
                e.ytop = e.ycurr;
                e.xbot = e.next.xcurr;
                e.ybot = e.next.ycurr;
                e.windDelta = -1;
            }
            SetDx(e);
            e.polyType = polyType;
            e.outIdx = -1;
        }
Beispiel #3
0
        //---------------------------------------------------------------------------

        TEdge AddBoundsToLML(TEdge e)
        {
            //Starting at the top of one bound we progress to the bottom where there's
            //a local minima. We then go to the top of the next bound. These two bounds
            //form the left and right (or right and left) bounds of the local minima.
            e.nextInLML = null;
            e = e.next;
            for (; ; )
            {
                if (e.dx == horizontal)
                {
                    //nb: proceed through horizontals when approaching from their right,
                    //    but break on horizontal minima if approaching from their left.
                    //    This ensures 'local minima' are always on the left of horizontals.
                    if (e.next.ytop < e.ytop && e.next.xbot > e.prev.xbot) break;
                    if (e.xtop != e.prev.xbot) SwapX(e);
                    e.nextInLML = e.prev;
                }
                else if (e.ycurr == e.prev.ycurr) break;
                else e.nextInLML = e.prev;
                e = e.next;
            }

            //e and e.prev are now at a local minima ...
            LocalMinima newLm = new LocalMinima();
            newLm.next = null;
            newLm.Y = e.prev.ybot;

            if (e.dx == horizontal) //horizontal edges never start a left bound
            {
                if (e.xbot != e.prev.xbot) SwapX(e);
                newLm.leftBound = e.prev;
                newLm.rightBound = e;
            }
            else if (e.dx < e.prev.dx)
            {
                newLm.leftBound = e.prev;
                newLm.rightBound = e;
            }
            else
            {
                newLm.leftBound = e;
                newLm.rightBound = e.prev;
            }
            newLm.leftBound.side = EdgeSide.esLeft;
            newLm.rightBound.side = EdgeSide.esRight;
            InsertLocalMinima(newLm);

            for (; ; )
            {
                if (e.next.ytop == e.ytop && e.next.dx != horizontal) break;
                e.nextInLML = e.next;
                e = e.next;
                if (e.dx == horizontal && e.xbot != e.prev.xtop) SwapX(e);
            }
            return e.next;
        }
Beispiel #4
0
        //------------------------------------------------------------------------------

        private void InsertIntersectNode(TEdge e1, TEdge e2, IntPoint pt)
        {
            IntersectNode newNode = new IntersectNode();
            newNode.edge1 = e1;
            newNode.edge2 = e2;
            newNode.pt = pt;
            newNode.next = null;
            if (m_IntersectNodes == null) m_IntersectNodes = newNode;
            else if (newNode.pt.Y > m_IntersectNodes.pt.Y)
            {
                newNode.next = m_IntersectNodes;
                m_IntersectNodes = newNode;
            }
            else
            {
                IntersectNode iNode = m_IntersectNodes;
                while (iNode.next != null && newNode.pt.Y < iNode.next.pt.Y)
                    iNode = iNode.next;
                newNode.next = iNode.next;
                iNode.next = newNode;
            }
        }
Beispiel #5
0
        //------------------------------------------------------------------------------

        private void DoMaxima(TEdge e, Int64 topY)
        {
            TEdge eMaxPair = GetMaximaPair(e);
            Int64 X = e.xtop;
            TEdge eNext = e.nextInAEL;
            while (eNext != eMaxPair)
            {
                if (eNext == null) throw new ClipperException("DoMaxima error");
                IntersectEdges(e, eNext, new IntPoint(X, topY), Protects.ipBoth);
                SwapPositionsInAEL(e, eNext);
                eNext = e.nextInAEL;
            }
            if (e.outIdx < 0 && eMaxPair.outIdx < 0)
            {
                DeleteFromAEL(e);
                DeleteFromAEL(eMaxPair);
            }
            else if (e.outIdx >= 0 && eMaxPair.outIdx >= 0)
            {
                IntersectEdges(e, eMaxPair, new IntPoint(X, topY), Protects.ipNone);
            }
            else throw new ClipperException("DoMaxima error");
        }
Beispiel #6
0
        //------------------------------------------------------------------------------

        private TEdge GetMaximaPair(TEdge e)
        {
            if (!IsMaxima(e.next, e.ytop) || (e.next.xtop != e.xtop))
                return e.prev;
            else
                return e.next;
        }
Beispiel #7
0
        //------------------------------------------------------------------------------

        private void BuildIntersectList(Int64 botY, Int64 topY)
        {
            if (m_ActiveEdges == null) return;

            //prepare for sorting ...
            TEdge e = m_ActiveEdges;
            m_SortedEdges = e;
            while (e != null)
            {
                e.prevInSEL = e.prevInAEL;
                e.nextInSEL = e.nextInAEL;
                e.xcurr = TopX(e, topY);
                e = e.nextInAEL;
            }

            //bubblesort ...
            bool isModified = true;
            while (isModified && m_SortedEdges != null)
            {
                isModified = false;
                e = m_SortedEdges;
                while (e.nextInSEL != null)
                {
                    TEdge eNext = e.nextInSEL;
                    IntPoint pt = new IntPoint();
                    if (e.xcurr > eNext.xcurr)
                    {
                        if (!IntersectPoint(e, eNext, ref pt) && e.xcurr > eNext.xcurr + 1)
                            throw new ClipperException("Intersection error");
                        if (pt.Y > botY)
                        {
                            pt.Y = botY;
                            pt.X = TopX(e, pt.Y);
                        }
                        InsertIntersectNode(e, eNext, pt);
                        SwapPositionsInSEL(e, eNext);
                        isModified = true;
                    }
                    else
                        e = eNext;
                }
                if (e.prevInSEL != null) e.prevInSEL.nextInSEL = null;
                else break;
            }
            m_SortedEdges = null;
        }
Beispiel #8
0
        //------------------------------------------------------------------------------

        private static void SwapPolyIndexes(TEdge edge1, TEdge edge2)
        {
            int outIdx = edge1.outIdx;
            edge1.outIdx = edge2.outIdx;
            edge2.outIdx = outIdx;
        }
Beispiel #9
0
        //------------------------------------------------------------------------------

        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
                {
                    AddOutPt(e1, pt);
                    AddOutPt(e2, pt);
                    SwapSides(e1, e2);
                    SwapPolyIndexes(e1, e2);
                }
            }
            else if (e1Contributing)
            {
                if (e2Wc == 0 || e2Wc == 1)
                {
                    AddOutPt(e1, pt);
                    SwapSides(e1, e2);
                    SwapPolyIndexes(e1, e2);
                }

            }
            else if (e2contributing)
            {
                if (e1Wc == 0 || e1Wc == 1)
                {
                    AddOutPt(e2, pt);
                    SwapSides(e1, e2);
                    SwapPolyIndexes(e1, e2);
                }
            }
            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);
        }
Beispiel #10
0
        //------------------------------------------------------------------------------

        private void AppendPolygon(TEdge e1, TEdge e2)
        {
            //get the start and ends of both output polygons ...
            OutRec outRec1 = m_PolyOuts[e1.outIdx];
            OutRec outRec2 = m_PolyOuts[e2.outIdx];

            OutRec holeStateRec;
            if (Param1RightOfParam2(outRec1, outRec2))
                holeStateRec = outRec2;
            else if (Param1RightOfParam2(outRec2, outRec1))
                holeStateRec = outRec1;
            else
                holeStateRec = GetLowermostRec(outRec1, outRec2);

            OutPt p1_lft = outRec1.pts;
            OutPt p1_rt = p1_lft.prev;
            OutPt p2_lft = outRec2.pts;
            OutPt p2_rt = p2_lft.prev;

            EdgeSide side;
            //join e2 poly onto e1 poly and delete pointers to e2 ...
            if (e1.side == EdgeSide.esLeft)
            {
                if (e2.side == EdgeSide.esLeft)
                {
                    //z y x a b c
                    ReversePolyPtLinks(p2_lft);
                    p2_lft.next = p1_lft;
                    p1_lft.prev = p2_lft;
                    p1_rt.next = p2_rt;
                    p2_rt.prev = p1_rt;
                    outRec1.pts = p2_rt;
                }
                else
                {
                    //x y z a b c
                    p2_rt.next = p1_lft;
                    p1_lft.prev = p2_rt;
                    p2_lft.prev = p1_rt;
                    p1_rt.next = p2_lft;
                    outRec1.pts = p2_lft;
                }
                side = EdgeSide.esLeft;
            }
            else
            {
                if (e2.side == EdgeSide.esRight)
                {
                    //a b c z y x
                    ReversePolyPtLinks(p2_lft);
                    p1_rt.next = p2_rt;
                    p2_rt.prev = p1_rt;
                    p2_lft.next = p1_lft;
                    p1_lft.prev = p2_lft;
                }
                else
                {
                    //a b c x y z
                    p1_rt.next = p2_lft;
                    p2_lft.prev = p1_rt;
                    p1_lft.prev = p2_rt;
                    p2_rt.next = p1_lft;
                }
                side = EdgeSide.esRight;
            }

            outRec1.bottomPt = null;
            if (holeStateRec == outRec2)
            {
                if (outRec2.FirstLeft != outRec1)
                    outRec1.FirstLeft = outRec2.FirstLeft;
                outRec1.isHole = outRec2.isHole;
            }
            outRec2.pts = null;
            outRec2.bottomPt = null;

            outRec2.FirstLeft = outRec1;

            int OKIdx = e1.outIdx;
            int ObsoleteIdx = e2.outIdx;

            e1.outIdx = -1; //nb: safe because we only get here via AddLocalMaxPoly
            e2.outIdx = -1;

            TEdge e = m_ActiveEdges;
            while (e != null)
            {
                if (e.outIdx == ObsoleteIdx)
                {
                    e.outIdx = OKIdx;
                    e.side = side;
                    break;
                }
                e = e.nextInAEL;
            }
            outRec2.idx = outRec1.idx;
        }
Beispiel #11
0
        //------------------------------------------------------------------------------

        private static void SwapSides(TEdge edge1, TEdge edge2)
        {
            EdgeSide side = edge1.side;
            edge1.side = edge2.side;
            edge2.side = side;
        }
Beispiel #12
0
        //------------------------------------------------------------------------------

        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;
        }
Beispiel #13
0
        //------------------------------------------------------------------------------

        private void AddOutPt(TEdge e, IntPoint pt)
        {
            bool ToFront = (e.side == EdgeSide.esLeft);
            if (e.outIdx < 0)
            {
                OutRec outRec = CreateOutRec();
                e.outIdx = outRec.idx;
                OutPt op = new OutPt();
                outRec.pts = op;
                op.pt = pt;
                op.idx = outRec.idx;
                op.next = op;
                op.prev = op;
                SetHoleState(e, outRec);
            }
            else
            {
                OutRec outRec = m_PolyOuts[e.outIdx];
                OutPt op = outRec.pts, op2;
                if (ToFront && PointsEqual(pt, op.pt) ||
                    (!ToFront && PointsEqual(pt, op.prev.pt))) return;

                op2 = new OutPt();
                op2.pt = pt;
                op2.idx = outRec.idx;
                op2.next = op;
                op2.prev = op.prev;
                op2.prev.next = op2;
                op.prev = op2;
                if (ToFront) outRec.pts = op2;
            }
        }
Beispiel #14
0
        //------------------------------------------------------------------------------

        private void AddLocalMinPoly(TEdge e1, TEdge e2, IntPoint pt)
        {
            TEdge e, prevE;
            if (e2.dx == horizontal || (e1.dx > e2.dx))
            {
                AddOutPt(e1, pt);
                e2.outIdx = e1.outIdx;
                e1.side = EdgeSide.esLeft;
                e2.side = EdgeSide.esRight;
                e = e1;
                if (e.prevInAEL == e2)
                    prevE = e2.prevInAEL;
                else
                    prevE = e.prevInAEL;
            }
            else
            {
                AddOutPt(e2, pt);
                e1.outIdx = e2.outIdx;
                e1.side = EdgeSide.esRight;
                e2.side = EdgeSide.esLeft;
                e = e2;
                if (e.prevInAEL == e1)
                    prevE = e1.prevInAEL;
                else
                    prevE = e.prevInAEL;
            }

            if (prevE != null && prevE.outIdx >= 0 &&
                (TopX(prevE, pt.Y) == TopX(e, pt.Y)) &&
                 SlopesEqual(e, prevE, m_UseFullRange))
                AddJoin(e, prevE, -1, -1);

        }
Beispiel #15
0
        //------------------------------------------------------------------------------

        private bool IsMaxima(TEdge e, double Y)
        {
            return (e != null && e.ytop == Y && e.nextInLML == null);
        }
Beispiel #16
0
        //------------------------------------------------------------------------------

        private void DeleteFromAEL(TEdge e)
        {
            TEdge AelPrev = e.prevInAEL;
            TEdge AelNext = e.nextInAEL;
            if (AelPrev == null && AelNext == null && (e != m_ActiveEdges))
                return; //already deleted
            if (AelPrev != null)
                AelPrev.nextInAEL = AelNext;
            else m_ActiveEdges = AelNext;
            if (AelNext != null)
                AelNext.prevInAEL = AelPrev;
            e.nextInAEL = null;
            e.prevInAEL = null;
        }
Beispiel #17
0
        //------------------------------------------------------------------------------

        private bool IsIntermediate(TEdge e, double Y)
        {
            return (e.ytop == Y && e.nextInLML != null);
        }
Beispiel #18
0
        //------------------------------------------------------------------------------

        private void DeleteFromSEL(TEdge e)
        {
            TEdge SelPrev = e.prevInSEL;
            TEdge SelNext = e.nextInSEL;
            if (SelPrev == null && SelNext == null && (e != m_SortedEdges))
                return; //already deleted
            if (SelPrev != null)
                SelPrev.nextInSEL = SelNext;
            else m_SortedEdges = SelNext;
            if (SelNext != null)
                SelNext.prevInSEL = SelPrev;
            e.nextInSEL = null;
            e.prevInSEL = null;
        }
Beispiel #19
0
        //------------------------------------------------------------------------------

        private bool ProcessIntersections(Int64 botY, Int64 topY)
        {
            if (m_ActiveEdges == null) return true;
            try
            {
                BuildIntersectList(botY, topY);
                if (m_IntersectNodes == null) return true;
                if (m_IntersectNodes.next == null || FixupIntersectionOrder())
                    ProcessIntersectList();
                else
                    return false;
            }
            catch
            {
                m_SortedEdges = null;
                DisposeIntersectNodes();
                throw new ClipperException("ProcessIntersections error");
            }
            m_SortedEdges = null;
            return true;
        }
Beispiel #20
0
        //------------------------------------------------------------------------------

        private void UpdateEdgeIntoAEL(ref TEdge e)
        {
            if (e.nextInLML == null)
                throw new ClipperException("UpdateEdgeIntoAEL: invalid call");
            TEdge AelPrev = e.prevInAEL;
            TEdge AelNext = e.nextInAEL;
            e.nextInLML.outIdx = e.outIdx;
            if (AelPrev != null)
                AelPrev.nextInAEL = e.nextInLML;
            else m_ActiveEdges = e.nextInLML;
            if (AelNext != null)
                AelNext.prevInAEL = e.nextInLML;
            e.nextInLML.side = e.side;
            e.nextInLML.windDelta = e.windDelta;
            e.nextInLML.windCnt = e.windCnt;
            e.nextInLML.windCnt2 = e.windCnt2;
            e = e.nextInLML;
            e.prevInAEL = AelPrev;
            e.nextInAEL = AelNext;
            if (e.dx != horizontal) InsertScanbeam(e.ytop);
        }
Beispiel #21
0
        //------------------------------------------------------------------------------

        private static Int64 TopX(TEdge edge, Int64 currentY)
        {
            if (currentY == edge.ytop)
                return edge.xtop;
            return edge.xbot + Round(edge.dx * (currentY - edge.ybot));
        }
Beispiel #22
0
        //------------------------------------------------------------------------------

        private void ProcessHorizontal(TEdge horzEdge)
        {
            Direction Direction;
            Int64 horzLeft, horzRight;

            if (horzEdge.xcurr < horzEdge.xtop)
            {
                horzLeft = horzEdge.xcurr;
                horzRight = horzEdge.xtop;
                Direction = Direction.dLeftToRight;
            }
            else
            {
                horzLeft = horzEdge.xtop;
                horzRight = horzEdge.xcurr;
                Direction = Direction.dRightToLeft;
            }

            TEdge eMaxPair;
            if (horzEdge.nextInLML != null)
                eMaxPair = null;
            else
                eMaxPair = GetMaximaPair(horzEdge);

            TEdge e = GetNextInAEL(horzEdge, Direction);
            while (e != null)
            {
                if (e.xcurr == horzEdge.xtop && eMaxPair == null)
                {
                    if (SlopesEqual(e, horzEdge.nextInLML, m_UseFullRange))
                    {
                        //if output polygons share an edge, they'll need joining later ...
                        if (horzEdge.outIdx >= 0 && e.outIdx >= 0)
                            AddJoin(horzEdge.nextInLML, e, horzEdge.outIdx, -1);
                        break; //we've reached the end of the horizontal line
                    }
                    else if (e.dx < horzEdge.nextInLML.dx)
                        //we really have got to the end of the intermediate horz edge so quit.
                        //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal.
                        break;
                }

                TEdge eNext = GetNextInAEL(e, Direction);
                if (eMaxPair != null ||
                  ((Direction == Direction.dLeftToRight) && (e.xcurr < horzRight)) ||
                  ((Direction == Direction.dRightToLeft) && (e.xcurr > horzLeft)))
                {
                    //so far we're still in range of the horizontal edge

                    if (e == eMaxPair)
                    {
                        //horzEdge is evidently a maxima horizontal and we've arrived at its end.
                        if (Direction == Direction.dLeftToRight)
                            IntersectEdges(horzEdge, e, new IntPoint(e.xcurr, horzEdge.ycurr), 0);
                        else
                            IntersectEdges(e, horzEdge, new IntPoint(e.xcurr, horzEdge.ycurr), 0);
                        if (eMaxPair.outIdx >= 0) throw new ClipperException("ProcessHorizontal error");
                        return;
                    }
                    else if (e.dx == horizontal && !IsMinima(e) && !(e.xcurr > e.xtop))
                    {
                        if (Direction == Direction.dLeftToRight)
                            IntersectEdges(horzEdge, e, new IntPoint(e.xcurr, horzEdge.ycurr),
                              (IsTopHorz(horzEdge, e.xcurr)) ? Protects.ipLeft : Protects.ipBoth);
                        else
                            IntersectEdges(e, horzEdge, new IntPoint(e.xcurr, horzEdge.ycurr),
                              (IsTopHorz(horzEdge, e.xcurr)) ? Protects.ipRight : Protects.ipBoth);
                    }
                    else if (Direction == Direction.dLeftToRight)
                    {
                        IntersectEdges(horzEdge, e, new IntPoint(e.xcurr, horzEdge.ycurr),
                          (IsTopHorz(horzEdge, e.xcurr)) ? Protects.ipLeft : Protects.ipBoth);
                    }
                    else
                    {
                        IntersectEdges(e, horzEdge, new IntPoint(e.xcurr, horzEdge.ycurr),
                          (IsTopHorz(horzEdge, e.xcurr)) ? Protects.ipRight : Protects.ipBoth);
                    }
                    SwapPositionsInAEL(horzEdge, e);
                }
                else if ((Direction == Direction.dLeftToRight && e.xcurr >= horzRight) ||
                    (Direction == Direction.dRightToLeft && e.xcurr <= horzLeft)) break;
                e = eNext;
            } //end while ( e )

            if (horzEdge.nextInLML != null)
            {
                if (horzEdge.outIdx >= 0)
                    AddOutPt(horzEdge, new IntPoint(horzEdge.xtop, horzEdge.ytop));
                UpdateEdgeIntoAEL(ref horzEdge);
            }
            else
            {
                if (horzEdge.outIdx >= 0)
                    IntersectEdges(horzEdge, eMaxPair,
                        new IntPoint(horzEdge.xtop, horzEdge.ycurr), Protects.ipBoth);
                DeleteFromAEL(eMaxPair);
                DeleteFromAEL(horzEdge);
            }
        }
Beispiel #23
0
        //------------------------------------------------------------------------------

        private bool IntersectPoint(TEdge edge1, TEdge edge2, ref IntPoint ip)
        {
            double b1, b2;
            if (SlopesEqual(edge1, edge2, m_UseFullRange))
            {
                if (edge2.ybot > edge1.ybot)
                    ip.Y = edge2.ybot;
                else
                    ip.Y = edge1.ybot;
                return false;
            }
            else if (edge1.dx == 0)
            {
                ip.X = edge1.xbot;
                if (edge2.dx == horizontal)
                {
                    ip.Y = edge2.ybot;
                }
                else
                {
                    b2 = edge2.ybot - (edge2.xbot / edge2.dx);
                    ip.Y = Round(ip.X / edge2.dx + b2);
                }
            }
            else if (edge2.dx == 0)
            {
                ip.X = edge2.xbot;
                if (edge1.dx == horizontal)
                {
                    ip.Y = edge1.ybot;
                }
                else
                {
                    b1 = edge1.ybot - (edge1.xbot / edge1.dx);
                    ip.Y = Round(ip.X / edge1.dx + b1);
                }
            }
            else
            {
                b1 = edge1.xbot - edge1.ybot * edge1.dx;
                b2 = edge2.xbot - edge2.ybot * edge2.dx;
                double q = (b2 - b1) / (edge1.dx - edge2.dx);
                ip.Y = Round(q);
                if (Math.Abs(edge1.dx) < Math.Abs(edge2.dx))
                    ip.X = Round(edge1.dx * q + b1);
                else
                    ip.X = Round(edge2.dx * q + b2);
            }

            if (ip.Y < edge1.ytop || ip.Y < edge2.ytop)
            {
                if (edge1.ytop > edge2.ytop)
                {
                    ip.X = edge1.xtop;
                    ip.Y = edge1.ytop;
                    return TopX(edge2, edge1.ytop) < edge1.xtop;
                }
                else
                {
                    ip.X = edge2.xtop;
                    ip.Y = edge2.ytop;
                    return TopX(edge1, edge2.ytop) > edge2.xtop;
                }
            }
            else
                return true;
        }
Beispiel #24
0
        //------------------------------------------------------------------------------

        private bool IsTopHorz(TEdge horzEdge, double XPos)
        {
            TEdge e = m_SortedEdges;
            while (e != null)
            {
                if ((XPos >= Math.Min(e.xcurr, e.xtop)) && (XPos <= Math.Max(e.xcurr, e.xtop)))
                    return false;
                e = e.nextInSEL;
            }
            return true;
        }
Beispiel #25
0
        //------------------------------------------------------------------------------

        internal static bool SlopesEqual(TEdge e1, TEdge e2, bool UseFullRange)
        {
            if (UseFullRange)
                return Int128.Int128Mul(e1.deltaY, e2.deltaX) ==
                    Int128.Int128Mul(e1.deltaX, e2.deltaY);
            else return (Int64)(e1.deltaY) * (e2.deltaX) ==
              (Int64)(e1.deltaX) * (e2.deltaY);
        }
Beispiel #26
0
        //------------------------------------------------------------------------------

        private TEdge GetNextInAEL(TEdge e, Direction Direction)
        {
            return Direction == Direction.dLeftToRight ? e.nextInAEL : e.prevInAEL;
        }
Beispiel #27
0
        //------------------------------------------------------------------------------

        private void SetDx(TEdge e)
        {
            e.deltaX = (e.xtop - e.xbot);
            e.deltaY = (e.ytop - e.ybot);
            if (e.deltaY == 0) e.dx = horizontal;
            else e.dx = (double)(e.deltaX) / (e.deltaY);
        }
Beispiel #28
0
        //------------------------------------------------------------------------------

        private bool IsMinima(TEdge e)
        {
            return e != null && (e.prev.nextInLML != e) && (e.next.nextInLML != e);
        }
Beispiel #29
0
        //------------------------------------------------------------------------------

        private void SwapX(TEdge e)
        {
            //swap horizontal edges' top and bottom x's so they follow the natural
            //progression of the bounds - ie so their xbots will align with the
            //adjoining lower edge. [Helpful in the ProcessHorizontal() method.]
            e.xcurr = e.xtop;
            e.xtop = e.xbot;
            e.xbot = e.xcurr;
        }
Beispiel #30
0
        //------------------------------------------------------------------------------

        private void SwapPositionsInSEL(TEdge edge1, TEdge edge2)
        {
            if (edge1.nextInSEL == null && edge1.prevInSEL == null)
                return;
            if (edge2.nextInSEL == null && edge2.prevInSEL == null)
                return;

            if (edge1.nextInSEL == edge2)
            {
                TEdge next = edge2.nextInSEL;
                if (next != null)
                    next.prevInSEL = edge1;
                TEdge prev = edge1.prevInSEL;
                if (prev != null)
                    prev.nextInSEL = edge2;
                edge2.prevInSEL = prev;
                edge2.nextInSEL = edge1;
                edge1.prevInSEL = edge2;
                edge1.nextInSEL = next;
            }
            else if (edge2.nextInSEL == edge1)
            {
                TEdge next = edge1.nextInSEL;
                if (next != null)
                    next.prevInSEL = edge2;
                TEdge prev = edge2.prevInSEL;
                if (prev != null)
                    prev.nextInSEL = edge1;
                edge1.prevInSEL = prev;
                edge1.nextInSEL = edge2;
                edge2.prevInSEL = edge1;
                edge2.nextInSEL = next;
            }
            else
            {
                TEdge next = edge1.nextInSEL;
                TEdge prev = edge1.prevInSEL;
                edge1.nextInSEL = edge2.nextInSEL;
                if (edge1.nextInSEL != null)
                    edge1.nextInSEL.prevInSEL = edge1;
                edge1.prevInSEL = edge2.prevInSEL;
                if (edge1.prevInSEL != null)
                    edge1.prevInSEL.nextInSEL = edge1;
                edge2.nextInSEL = next;
                if (edge2.nextInSEL != null)
                    edge2.nextInSEL.prevInSEL = edge2;
                edge2.prevInSEL = prev;
                if (edge2.prevInSEL != null)
                    edge2.prevInSEL.nextInSEL = edge2;
            }

            if (edge1.prevInSEL == null)
                m_SortedEdges = edge1;
            else if (edge2.prevInSEL == null)
                m_SortedEdges = edge2;
        }