Example #1
0
 //------------------------------------------------------------------------------
 private void UpdateEdgeIntoAEL(ref TEdge4 e)
 {
     if (e.nextInLML == null)
         throw new ClipperException("UpdateEdgeIntoAEL: invalid call");
     TEdge4 AelPrev = e.prevInAEL;
     TEdge4 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);
         //if output polygons share an edge, they'll need joining later ...
         if (e.outIdx >= 0 && AelPrev != null && AelPrev.outIdx >= 0 &&
           AelPrev.xbot == e.xcurr && SlopesEqual(e, AelPrev))
             AddJoin(e, AelPrev);
     }
 }
Example #2
0
        //------------------------------------------------------------------------------
        private bool FixupIntersections()
        {
            if ( m_IntersectNodes.next == null ) return true;

              CopyAELToSEL();
              IntersectNode int1 = m_IntersectNodes;
              IntersectNode int2 = m_IntersectNodes.next;
              while (int2 != null)
              {
            TEdge4 e1 = int1.edge1;
            TEdge4 e2;
            if (e1.prevInSEL == int1.edge2) e2 = e1.prevInSEL;
            else if (e1.nextInSEL == int1.edge2) e2 = e1.nextInSEL;
            else
            {
              //The current intersection is out of order, so try and swap it with
              //a subsequent intersection ...
              while (int2 != null)
              {
                if (int2.edge1.nextInSEL == int2.edge2 ||
                  int2.edge1.prevInSEL == int2.edge2) break;
                else int2 = int2.next;
              }
              if (int2 == null) return false; //oops!!!

              //found an intersect node that can be swapped ...
              SwapIntersectNodes(int1, int2);
              e1 = int1.edge1;
              e2 = int1.edge2;
            }
            SwapPositionsInSEL(e1, e2);
            int1 = int1.next;
            int2 = int1.next;
              }

              m_SortedEdges = null;

              //finally, check the last intersection too ...
              return (int1.edge1.prevInSEL == int1.edge2 || int1.edge1.nextInSEL == int1.edge2);
        }
Example #3
0
 //------------------------------------------------------------------------------
 private TEdge4 GetNextInAEL(TEdge4 e, Direction Direction)
 {
     if (Direction == Direction.dLeftToRight) return e.nextInAEL;
     else return e.prevInAEL;
 }
Example #4
0
 //------------------------------------------------------------------------------
 private void DeleteFromSEL(TEdge4 e)
 {
     TEdge4 SelPrev = e.prevInSEL;
     TEdge4 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;
 }
Example #5
0
 //------------------------------------------------------------------------------
 private void DoMaxima(TEdge4 e, int topY)
 {
     TEdge4 eMaxPair = GetMaximaPair(e);
       int X = e.xtop;
       TEdge4 eNext = e.nextInAEL;
       while( eNext != eMaxPair )
       {
     if (eNext == null) throw new ClipperException("DoMaxima error");
     IntersectEdges( e, eNext, new IntPoint(X, topY), Protects.ipBoth );
     eNext = eNext.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");
 }
Example #6
0
        //------------------------------------------------------------------------------
        private void AppendPolygon(TEdge4 e1, TEdge4 e2)
        {
            //get the start and ends of both output polygons ...
              PolyPt p1_lft = m_PolyPts[e1.outIdx];
              PolyPt p1_rt = p1_lft.prev;
              PolyPt p2_lft = m_PolyPts[e2.outIdx];
              PolyPt p2_rt = p2_lft.prev;

              //fixup orientation (hole) flag if necessary ...
              if (p1_lft.isHole != p2_lft.isHole)
              {
            PolyPt p, pp;
            PolyPt bottom1 = PolygonBottom(p1_lft);
            PolyPt bottom2 = PolygonBottom(p2_lft);
            if (bottom1.pt.Y > bottom2.pt.Y) p = p2_lft;
            else if (bottom1.pt.Y < bottom2.pt.Y) p = p1_lft;
            else if (bottom1.pt.X < bottom2.pt.X) p = p2_lft;
            else if (bottom1.pt.X > bottom2.pt.X) p = p1_lft;
            //todo - the following line still isn't 100% ...
            else if (bottom1.isHole) p = p1_lft; else p = p2_lft;

            bool hole = !p.isHole;
            pp = p;
            do
            {
              pp.isHole = hole;
              pp = pp.next;
            }
            while (pp != p);
              }

            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;
              m_PolyPts[e1.outIdx] = 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;
              m_PolyPts[e1.outIdx] = 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;
              }

              int OKIdx = e1.outIdx;
              int ObsoleteIdx = e2.outIdx;
              m_PolyPts[ObsoleteIdx] = null;

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

              TEdge4 e = m_ActiveEdges;
              while( e != null )
              {
            if( e.outIdx == ObsoleteIdx )
            {
              e.outIdx = OKIdx;
              e.side = side;
              break;
            }
            e = e.nextInAEL;
              }
        }
Example #7
0
 //------------------------------------------------------------------------------
 private void CopyAELToSEL()
 {
     TEdge4 e = m_ActiveEdges;
     m_SortedEdges = e;
     if (m_ActiveEdges == null)
         return;
     m_SortedEdges.prevInSEL = null;
     e = e.nextInAEL;
     while (e != null)
     {
         e.prevInSEL = e.prevInAEL;
         e.prevInSEL.nextInSEL = e;
         e.nextInSEL = null;
         e = e.nextInAEL;
     }
 }
Example #8
0
 //------------------------------------------------------------------------------
 protected override bool Reset()
 {
     if ( !base.Reset() ) return false;
       m_Scanbeam = null;
       m_ActiveEdges = null;
       m_SortedEdges = null;
       LocalMinima lm = m_MinimaList;
       while (lm != null)
       {
     InsertScanbeam(lm.Y);
     InsertScanbeam(lm.leftBound.ytop);
     lm = lm.next;
       }
       return true;
 }
Example #9
0
 //------------------------------------------------------------------------------
 private static void SwapPolyIndexes(TEdge4 edge1, TEdge4 edge2)
 {
     int outIdx = edge1.outIdx;
     edge1.outIdx = edge2.outIdx;
     edge2.outIdx = outIdx;
 }
Example #10
0
 //------------------------------------------------------------------------------
 private void SetDx(TEdge4 e)
 {
     if (e.ybot == e.ytop) e.dx = horizontal;
       else e.dx = (double)(e.xtop - e.xbot)/(e.ytop - e.ybot);
 }
Example #11
0
 //------------------------------------------------------------------------------
 private void SwapX(TEdge4 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;
 }
Example #12
0
 //------------------------------------------------------------------------------
 private void InitEdge(TEdge4 e, TEdge4 eNext,
     TEdge4 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;
 }
Example #13
0
        //---------------------------------------------------------------------------
        TEdge4 AddBoundsToLML(TEdge4 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;
        }
Example #14
0
 //------------------------------------------------------------------------------
 internal bool SlopesEqual(TEdge4 e1, TEdge4 e2)
 {
     if (e1.ybot == e1.ytop) return (e2.ybot == e2.ytop);
       else if (e2.ybot == e2.ytop) return false;
       else return (Int64)(e1.ytop - e1.ybot)*(e2.xtop - e2.xbot) -
       (Int64)(e1.xtop - e1.xbot)*(e2.ytop - e2.ybot) == 0;
 }
Example #15
0
 //------------------------------------------------------------------------------
 private void AddLocalMinPoly(TEdge4 e1, TEdge4 e2, IntPoint pt)
 {
     if (e2.dx == horizontal || (e1.dx > e2.dx))
     {
         AddPolyPt(e1, pt);
         e2.outIdx = e1.outIdx;
         e1.side = EdgeSide.esLeft;
         e2.side = EdgeSide.esRight;
     }
     else
     {
         AddPolyPt(e2, pt);
         e1.outIdx = e2.outIdx;
         e1.side = EdgeSide.esRight;
         e2.side = EdgeSide.esLeft;
     }
 }
Example #16
0
 //------------------------------------------------------------------------------
 private static void SwapSides(TEdge4 edge1, TEdge4 edge2)
 {
     EdgeSide side = edge1.side;
     edge1.side = edge2.side;
     edge2.side = side;
 }
Example #17
0
        //------------------------------------------------------------------------------
        private PolyPt AddPolyPt(TEdge4 e, IntPoint pt)
        {
            bool ToFront = (e.side == EdgeSide.esLeft);
              if(  e.outIdx < 0 )
              {
            PolyPt newPolyPt = new PolyPt();
            newPolyPt.pt = pt;
            newPolyPt.isHole = IsHole(e);
            m_PolyPts.Add(newPolyPt);
            newPolyPt.next = newPolyPt;
            newPolyPt.prev = newPolyPt;
            e.outIdx = m_PolyPts.Count-1;
            return newPolyPt;
              } else
              {
            PolyPt pp = m_PolyPts[e.outIdx];
            if (ToFront && PointsEqual(pt, pp.pt)) return pp;
            if (!ToFront && PointsEqual(pt, pp.prev.pt)) return pp.prev;

            PolyPt newPolyPt = new PolyPt();
            newPolyPt.pt = pt;
            newPolyPt.isHole = pp.isHole;
            newPolyPt.next = pp;
            newPolyPt.prev = pp.prev;
            newPolyPt.prev.next = newPolyPt;
            pp.prev = newPolyPt;
            if (ToFront) m_PolyPts[e.outIdx] = newPolyPt;
            return newPolyPt;
              }
        }
Example #18
0
 //------------------------------------------------------------------------------
 private static int TopX(TEdge4 edge, int currentY)
 {
     if (currentY == edge.ytop)
         return edge.xtop;
     return edge.xbot + Round(edge.dx *(currentY - edge.ybot));
 }
Example #19
0
        //------------------------------------------------------------------------------
        private void BuildIntersectList(int topY)
        {
            if ( m_ActiveEdges == null ) return;

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

              //bubblesort ...
              bool isModified = true;
              while( isModified && m_SortedEdges != null )
              {
            isModified = false;
            e = m_SortedEdges;
            while( e.nextInSEL != null )
            {
              TEdge4 eNext = e.nextInSEL;
              IntPoint pt = new IntPoint();
              if(e.tmpX > eNext.tmpX && IntersectPoint(e, eNext, ref pt))
              {
                AddIntersectNode( e, eNext, pt );
                SwapPositionsInSEL(e, eNext);
                isModified = true;
              }
              else
                e = eNext;
            }
            if( e.prevInSEL != null ) e.prevInSEL.nextInSEL = null;
            else break;
              }
              m_SortedEdges = null;
        }
Example #20
0
 //------------------------------------------------------------------------------
 private void AddEdgeToSEL(TEdge4 edge)
 {
     //SEL pointers in PEdge are reused to build a list of horizontal edges.
     //However, we don't need to worry about order with horizontal edge processing.
     if (m_SortedEdges == null)
     {
         m_SortedEdges = edge;
         edge.prevInSEL = null;
         edge.nextInSEL = null;
     }
     else
     {
         edge.nextInSEL = m_SortedEdges;
         edge.prevInSEL = null;
         m_SortedEdges.prevInSEL = edge;
         m_SortedEdges = edge;
     }
 }
Example #21
0
 //------------------------------------------------------------------------------
 private void DeleteFromAEL(TEdge4 e)
 {
     TEdge4 AelPrev = e.prevInAEL;
     TEdge4 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;
 }
Example #22
0
 //------------------------------------------------------------------------------
 private void AddHorzJoin(TEdge4 e, int idx)
 {
     HorzJoinRec hj = new HorzJoinRec();
     hj.edge = e;
     hj.savedIdx = idx;
     m_HorizJoins.Add(hj);
 }
Example #23
0
 //------------------------------------------------------------------------------
 private void DoEdge2(TEdge4 edge1, TEdge4 edge2, IntPoint pt)
 {
     AddPolyPt(edge2, pt);
     SwapSides(edge1, edge2);
     SwapPolyIndexes(edge1, edge2);
 }
Example #24
0
 //------------------------------------------------------------------------------
 private void AddIntersectNode(TEdge4 e1, TEdge4 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( Process1Before2(newNode, m_IntersectNodes) )
       {
     newNode.next = m_IntersectNodes;
     m_IntersectNodes = newNode;
       }
       else
       {
     IntersectNode iNode = m_IntersectNodes;
     while( iNode.next != null  && Process1Before2(iNode.next, newNode) )
         iNode = iNode.next;
     newNode.next = iNode.next;
     iNode.next = newNode;
       }
 }
Example #25
0
 //----------------------------------------------------------------------
 private bool E2InsertsBeforeE1(TEdge4 e1, TEdge4 e2)
 {
     if (e2.xcurr == e1.xcurr) return e2.dx > e1.dx;
       else return e2.xcurr < e1.xcurr;
 }
Example #26
0
 //------------------------------------------------------------------------------
 private void AddJoin(TEdge4 e1, TEdge4 e2, int e1OutIdx = -1)
 {
     JoinRec jr = new JoinRec();
     if (e1OutIdx >= 0)
         jr.poly1Idx = e1OutIdx; else
     jr.poly1Idx = e1.outIdx;
     jr.pt1a = new IntPoint(e1.xbot, e1.ybot);
     jr.pt1b = new IntPoint(e1.xtop, e1.ytop);
     jr.poly2Idx = e2.outIdx;
     jr.pt2a = new IntPoint(e2.xbot, e2.ybot);
     jr.pt2b = new IntPoint(e2.xtop, e2.ytop);
     m_Joins.Add(jr);
 }
Example #27
0
 //------------------------------------------------------------------------------
 private TEdge4 GetMaximaPair(TEdge4 e)
 {
     if (!IsMaxima(e.next, e.ytop) || (e.next.xtop != e.xtop))
         return e.prev; else
         return e.next;
 }
Example #28
0
 //------------------------------------------------------------------------------
 private void AddLocalMaxPoly(TEdge4 e1, TEdge4 e2, IntPoint pt)
 {
     AddPolyPt(e1, pt);
     if (e1.outIdx == e2.outIdx)
     {
         e1.outIdx = -1;
         e2.outIdx = -1;
     }
     else AppendPolygon(e1, e2);
 }
Example #29
0
 //------------------------------------------------------------------------------
 private void InsertEdgeIntoAEL(TEdge4 edge)
 {
     edge.prevInAEL = null;
       edge.nextInAEL = null;
       if (m_ActiveEdges == null)
       {
     m_ActiveEdges = edge;
       }
       else if( E2InsertsBeforeE1(m_ActiveEdges, edge) )
       {
     edge.nextInAEL = m_ActiveEdges;
     m_ActiveEdges.prevInAEL = edge;
     m_ActiveEdges = edge;
       } else
       {
     TEdge4 e = m_ActiveEdges;
     while (e.nextInAEL != null && !E2InsertsBeforeE1(e.nextInAEL, edge))
       e = e.nextInAEL;
     edge.nextInAEL = e.nextInAEL;
     if (e.nextInAEL != null) e.nextInAEL.prevInAEL = edge;
     edge.prevInAEL = e;
     e.nextInAEL = edge;
       }
 }
Example #30
0
        //------------------------------------------------------------------------------
        private void SwapPositionsInSEL(TEdge4 edge1, TEdge4 edge2)
        {
            if (edge1.nextInSEL == null && edge1.prevInSEL == null)
                return;
            if (edge2.nextInSEL == null && edge2.prevInSEL == null)
                return;

            if (edge1.nextInSEL == edge2)
            {
                TEdge4 next = edge2.nextInSEL;
                if (next != null)
                    next.prevInSEL = edge1;
                TEdge4 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)
            {
                TEdge4 next = edge1.nextInSEL;
                if (next != null)
                    next.prevInSEL = edge2;
                TEdge4 prev = edge2.prevInSEL;
                if (prev != null)
                    prev.nextInSEL = edge1;
                edge1.prevInSEL = prev;
                edge1.nextInSEL = edge2;
                edge2.prevInSEL = edge1;
                edge2.nextInSEL = next;
            }
            else
            {
                TEdge4 next = edge1.nextInSEL;
                TEdge4 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;
        }