Esempio n. 1
0
 //constructor
 public Clipper(int InitOptions = 0)
     : base()
 {
     m_Scanbeam = null;
     m_Maxima = null;
     m_ActiveEdges = null;
     m_SortedEdges = null;
     m_IntersectList = new List<IntersectNode>();
     m_IntersectNodeComparer = new MyIntersectNodeSort();
     m_ExecuteLocked = false;
     m_UsingPolyTree = false;
     m_PolyOuts = new List<OutRec>();
     m_Joins = new List<Join>();
     m_GhostJoins = new List<Join>();
     ReverseSolution = (ioReverseSolution & InitOptions) != 0;
     StrictlySimple = (ioStrictlySimple & InitOptions) != 0;
     PreserveCollinear = (ioPreserveCollinear & InitOptions) != 0;
     #if use_xyz
       ZFillFunction = null;
     #endif
 }
Esempio n. 2
0
        //------------------------------------------------------------------------------
        private void ProcessEdgesAtTopOfScanbeam(int topY)
        {
            TEdge e = m_ActiveEdges;
            while (e != null)
            {
                //1. process maxima, treating them as if they're 'bent' horizontal edges,
                //   but exclude maxima with horizontal edges. nb: e can't be a horizontal.
                bool IsMaximaEdge = IsMaxima(e, topY);

                if (IsMaximaEdge)
                {
                    TEdge eMaxPair = GetMaximaPairEx(e);
                    IsMaximaEdge = (eMaxPair == null || !IsHorizontal(eMaxPair));
                }

                if (IsMaximaEdge)
                {
                    if (StrictlySimple) InsertMaxima(e.Top.X);
                    TEdge ePrev = e.PrevInAEL;
                    DoMaxima(e);
                    if (ePrev == null) e = m_ActiveEdges;
                    else e = ePrev.NextInAEL;
                }
                else
                {
                    //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ...
                    if (IsIntermediate(e, topY) && IsHorizontal(e.NextInLML))
                    {
                        UpdateEdgeIntoAEL(ref e);
                        if (e.OutIdx >= 0)
                            AddOutPt(e, e.Bot);
                        AddEdgeToSEL(e);
                    }
                    else
                    {
                        e.Curr.X = TopX(e, topY);
                        e.Curr.Y = topY;
                    }

                    //When StrictlySimple and 'e' is being touched by another edge, then
                    //make sure both edges have a vertex here ...
                    if (StrictlySimple)
                    {
                        TEdge ePrev = e.PrevInAEL;
                        if ((e.OutIdx >= 0) && (e.WindDelta != 0) && ePrev != null &&
                          (ePrev.OutIdx >= 0) && (ePrev.Curr.X == e.Curr.X) &&
                          (ePrev.WindDelta != 0))
                        {
                            IntPoint ip = new IntPoint(e.Curr);
            #if use_xyz
                SetZ(ref ip, ePrev, e);
            #endif
                            OutPt op = AddOutPt(ePrev, ip);
                            OutPt op2 = AddOutPt(e, ip);
                            AddJoin(op, op2, ip); //StrictlySimple (type-3) join
                        }
                    }

                    e = e.NextInAEL;
                }
            }

            //3. Process horizontals at the Top of the scanbeam ...
            ProcessHorizontals();
            m_Maxima = null;

            //4. Promote intermediate vertices ...
            e = m_ActiveEdges;
            while (e != null)
            {
                if (IsIntermediate(e, topY))
                {
                    OutPt op = null;
                    if (e.OutIdx >= 0)
                        op = AddOutPt(e, e.Top);
                    UpdateEdgeIntoAEL(ref e);

                    //if output polygons share an edge, they'll need joining later ...
                    TEdge ePrev = e.PrevInAEL;
                    TEdge eNext = e.NextInAEL;
                    if (ePrev != null && ePrev.Curr.X == e.Bot.X &&
                      ePrev.Curr.Y == e.Bot.Y && op != null &&
                      ePrev.OutIdx >= 0 && ePrev.Curr.Y > ePrev.Top.Y &&
                      SlopesEqual(e.Curr, e.Top, ePrev.Curr, ePrev.Top, m_UseFullRange) &&
                      (e.WindDelta != 0) && (ePrev.WindDelta != 0))
                    {
                        OutPt op2 = AddOutPt(ePrev, e.Bot);
                        AddJoin(op, op2, e.Top);
                    }
                    else if (eNext != null && eNext.Curr.X == e.Bot.X &&
                      eNext.Curr.Y == e.Bot.Y && op != null &&
                      eNext.OutIdx >= 0 && eNext.Curr.Y > eNext.Top.Y &&
                      SlopesEqual(e.Curr, e.Top, eNext.Curr, eNext.Top, m_UseFullRange) &&
                      (e.WindDelta != 0) && (eNext.WindDelta != 0))
                    {
                        OutPt op2 = AddOutPt(eNext, e.Bot);
                        AddJoin(op, op2, e.Top);
                    }
                }
                e = e.NextInAEL;
            }
        }
Esempio n. 3
0
        //------------------------------------------------------------------------------
        private bool ExecuteInternal()
        {
            try
            {
                Reset();
                m_SortedEdges = null;
                m_Maxima = null;

                int botY, topY;
                if (!PopScanbeam(out botY)) return false;
                InsertLocalMinimaIntoAEL(botY);
                while (PopScanbeam(out topY) || LocalMinimaPending())
                {
                    ProcessHorizontals();
                    m_GhostJoins.Clear();
                    if (!ProcessIntersections(topY)) return false;
                    ProcessEdgesAtTopOfScanbeam(topY);
                    botY = topY;
                    InsertLocalMinimaIntoAEL(botY);
                }

                //fix orientations ...
                foreach (OutRec outRec in m_PolyOuts)
                {
                    if (outRec.Pts == null || outRec.IsOpen) continue;
                    if ((outRec.IsHole ^ ReverseSolution) == (Area(outRec) > 0))
                        ReversePolyPtLinks(outRec.Pts);
                }

                JoinCommonEdges();

                foreach (OutRec outRec in m_PolyOuts)
                {
                    if (outRec.Pts == null)
                        continue;
                    else if (outRec.IsOpen)
                        FixupOutPolyline(outRec);
                    else
                        FixupOutPolygon(outRec);
                }

                if (StrictlySimple) DoSimplePolygons();
                return true;
            }
            //catch { return false; }
            finally
            {
                m_Joins.Clear();
                m_GhostJoins.Clear();
            }
        }
Esempio n. 4
0
 //------------------------------------------------------------------------------
 private void InsertMaxima(int X)
 {
     //double-linked list: sorted ascending, ignoring dups.
     Maxima newMax = new Maxima();
     newMax.X = X;
     if (m_Maxima == null)
     {
         m_Maxima = newMax;
         m_Maxima.Next = null;
         m_Maxima.Prev = null;
     }
     else if (X < m_Maxima.X)
     {
         newMax.Next = m_Maxima;
         newMax.Prev = null;
         m_Maxima = newMax;
     }
     else
     {
         Maxima m = m_Maxima;
         while (m.Next != null && (X >= m.Next.X)) m = m.Next;
         if (X == m.X) return; //ie ignores duplicates (& CG to clean up newMax)
                               //insert newMax between m and m.Next ...
         newMax.Next = m.Next;
         newMax.Prev = m;
         if (m.Next != null) m.Next.Prev = newMax;
         m.Next = newMax;
     }
 }
 /// <summary>
 /// Reset all fields to default values in preparation for object recycling
 /// </summary>
 public void PrepareForRecycle()
 {
     X    = new cInt();
     Next = Prev = null;
 }