Пример #1
0
 //constructor (nb: no external instantiation)
 //------------------------------------------------------------------------------
 internal ClipperBase()
 {
     m_MinimaList = null;
     m_CurrentLM = null;
     m_UseFullRange = false;
     m_HasOpenPaths = false;
 }
Пример #2
0
 protected virtual void Reset()
 {
     m_CurrentLM = m_MinimaList;
     if (m_CurrentLM == null)
     {
         return;
     }
     for (LocalMinima localMinima = m_MinimaList; localMinima != null; localMinima = localMinima.Next)
     {
         TEdge leftBound = localMinima.LeftBound;
         if (leftBound != null)
         {
             leftBound.Curr   = leftBound.Bot;
             leftBound.Side   = EdgeSide.esLeft;
             leftBound.OutIdx = -1;
         }
         leftBound = localMinima.RightBound;
         if (leftBound != null)
         {
             leftBound.Curr   = leftBound.Bot;
             leftBound.Side   = EdgeSide.esRight;
             leftBound.OutIdx = -1;
         }
     }
 }
Пример #3
0
        //------------------------------------------------------------------------------

        internal ClipperBase() //constructor (nb: no external instantiation)
        {
            m_MinimaList   = null;
            m_CurrentLM    = null;
            m_UseFullRange = false;
            m_HasOpenPaths = false;
        }
 protected void PopLocalMinima()
 {
     if (m_CurrentLM != null)
     {
         m_CurrentLM = m_CurrentLM.Next;
     }
 }
 internal ClipperBase()
 {
     m_MinimaList   = null;
     m_CurrentLM    = null;
     m_UseFullRange = false;
     m_HasOpenPaths = false;
 }
Пример #6
0
        //------------------------------------------------------------------------------

        internal virtual void Reset()
        {
            m_CurrentLM = m_MinimaList;
            if (m_CurrentLM == null)
            {
                return;                      //ie nothing to process
            }
            //reset all edges ...
            m_Scanbeam = null;
            LocalMinima lm = m_MinimaList;

            while (lm != null)
            {
                InsertScanbeam(lm.Y);
                TEdge e = lm.LeftBound;
                if (e != null)
                {
                    e.Curr   = e.Bot;
                    e.OutIdx = Unassigned;
                }
                e = lm.RightBound;
                if (e != null)
                {
                    e.Curr   = e.Bot;
                    e.OutIdx = Unassigned;
                }
                lm = lm.Next;
            }
            m_ActiveEdges = null;
        }
Пример #7
0
 internal virtual void Reset()
 {
     m_CurrentLM = m_MinimaList;
     if (m_CurrentLM != null)
     {
         m_Scanbeam = null;
         for (LocalMinima localMinima = m_MinimaList; localMinima != null; localMinima = localMinima.Next)
         {
             InsertScanbeam(localMinima.Y);
             TEdge leftBound = localMinima.LeftBound;
             if (leftBound != null)
             {
                 TEdge tEdge = leftBound;
                 tEdge.Curr       = tEdge.Bot;
                 leftBound.OutIdx = -1;
             }
             leftBound = localMinima.RightBound;
             if (leftBound != null)
             {
                 TEdge tEdge2 = leftBound;
                 tEdge2.Curr      = tEdge2.Bot;
                 leftBound.OutIdx = -1;
             }
         }
         m_ActiveEdges = null;
     }
 }
Пример #8
0
        //------------------------------------------------------------------------------

        protected virtual void Reset()
        {
            m_CurrentLM = m_MinimaList;
            if (m_CurrentLM == null)
            {
                return;                      //ie nothing to process
            }
            //reset all edges ...
            LocalMinima lm = m_MinimaList;

            while (lm != null)
            {
                TEdge e = lm.LeftBound;
                if (e != null)
                {
                    e.Curr = e.Bot;
                    e.Side = EdgeSide.esLeft;
                    if (e.OutIdx != Skip)
                    {
                        e.OutIdx = Unassigned;
                    }
                }
                e      = lm.RightBound;
                e.Curr = e.Bot;
                e.Side = EdgeSide.esRight;
                if (e.OutIdx != Skip)
                {
                    e.OutIdx = Unassigned;
                }

                lm = lm.Next;
            }
        }
Пример #9
0
        //------------------------------------------------------------------------------

        protected void PopLocalMinima()
        {
            if (m_CurrentLM == null)
            {
                return;
            }
            m_CurrentLM = m_CurrentLM.Next;
        }
Пример #10
0
        //------------------------------------------------------------------------------

        internal Boolean PopLocalMinima(int Y, out LocalMinima current)
        {
            current = m_CurrentLM;
            if (m_CurrentLM != null && m_CurrentLM.Y == Y)
            {
                m_CurrentLM = m_CurrentLM.Next;
                return(true);
            }
            return(false);
        }
 private void DisposeLocalMinimaList()
 {
     while (m_MinimaList != null)
     {
         LocalMinima next = m_MinimaList.Next;
         m_MinimaList = null;
         m_MinimaList = next;
     }
     m_CurrentLM = null;
 }
 private void InsertLocalMinima(LocalMinima newLm)
 {
     if (m_MinimaList == null)
     {
         m_MinimaList = newLm;
     }
     else if (newLm.Y >= m_MinimaList.Y)
     {
         newLm.Next   = m_MinimaList;
         m_MinimaList = newLm;
     }
     else
     {
         LocalMinima localMinima = m_MinimaList;
         while (localMinima.Next != null && newLm.Y < localMinima.Next.Y)
         {
             localMinima = localMinima.Next;
         }
         newLm.Next       = localMinima.Next;
         localMinima.Next = newLm;
     }
 }
Пример #13
0
        //---------------------------------------------------------------------------

        private void InsertLocalMinima(LocalMinima newLm)
        {
            if (m_MinimaList == null)
            {
                m_MinimaList = newLm;
            }
            else if (newLm.Y >= m_MinimaList.Y)
            {
                newLm.Next   = m_MinimaList;
                m_MinimaList = newLm;
            }
            else
            {
                LocalMinima tmpLm = m_MinimaList;
                while (tmpLm.Next != null && (newLm.Y < tmpLm.Next.Y))
                {
                    tmpLm = tmpLm.Next;
                }
                newLm.Next = tmpLm.Next;
                tmpLm.Next = newLm;
            }
        }
Пример #14
0
        private TEdge ProcessBound(TEdge E, bool IsClockwise)
        {
            TEdge tEdge  = E;
            TEdge tEdge2 = E;

            if (E.Dx == -3.4E+38)
            {
                long num = (!IsClockwise) ? E.Next.Bot.X : E.Prev.Bot.X;
                if (E.Bot.X != num)
                {
                    ReverseHorizontal(E);
                }
            }
            if (tEdge2.OutIdx != -2)
            {
                if (IsClockwise)
                {
                    while (tEdge2.Top.Y == tEdge2.Next.Bot.Y && tEdge2.Next.OutIdx != -2)
                    {
                        tEdge2 = tEdge2.Next;
                    }
                    if (tEdge2.Dx == -3.4E+38 && tEdge2.Next.OutIdx != -2)
                    {
                        TEdge tEdge3 = tEdge2;
                        while (tEdge3.Prev.Dx == -3.4E+38)
                        {
                            tEdge3 = tEdge3.Prev;
                        }
                        if (tEdge3.Prev.Top.X == tEdge2.Next.Top.X)
                        {
                            if (!IsClockwise)
                            {
                                tEdge2 = tEdge3.Prev;
                            }
                        }
                        else if (tEdge3.Prev.Top.X > tEdge2.Next.Top.X)
                        {
                            tEdge2 = tEdge3.Prev;
                        }
                    }
                    while (E != tEdge2)
                    {
                        E.NextInLML = E.Next;
                        if (E.Dx == -3.4E+38 && E != tEdge && E.Bot.X != E.Prev.Top.X)
                        {
                            ReverseHorizontal(E);
                        }
                        E = E.Next;
                    }
                    if (E.Dx == -3.4E+38 && E != tEdge && E.Bot.X != E.Prev.Top.X)
                    {
                        ReverseHorizontal(E);
                    }
                    tEdge2 = tEdge2.Next;
                }
                else
                {
                    while (tEdge2.Top.Y == tEdge2.Prev.Bot.Y && tEdge2.Prev.OutIdx != -2)
                    {
                        tEdge2 = tEdge2.Prev;
                    }
                    if (tEdge2.Dx == -3.4E+38 && tEdge2.Prev.OutIdx != -2)
                    {
                        TEdge tEdge3 = tEdge2;
                        while (tEdge3.Next.Dx == -3.4E+38)
                        {
                            tEdge3 = tEdge3.Next;
                        }
                        if (tEdge3.Next.Top.X == tEdge2.Prev.Top.X)
                        {
                            if (!IsClockwise)
                            {
                                tEdge2 = tEdge3.Next;
                            }
                        }
                        else if (tEdge3.Next.Top.X > tEdge2.Prev.Top.X)
                        {
                            tEdge2 = tEdge3.Next;
                        }
                    }
                    while (E != tEdge2)
                    {
                        E.NextInLML = E.Prev;
                        if (E.Dx == -3.4E+38 && E != tEdge && E.Bot.X != E.Next.Top.X)
                        {
                            ReverseHorizontal(E);
                        }
                        E = E.Prev;
                    }
                    if (E.Dx == -3.4E+38 && E != tEdge && E.Bot.X != E.Next.Top.X)
                    {
                        ReverseHorizontal(E);
                    }
                    tEdge2 = tEdge2.Prev;
                }
            }
            if (tEdge2.OutIdx == -2)
            {
                E = tEdge2;
                if (IsClockwise)
                {
                    while (E.Top.Y == E.Next.Bot.Y)
                    {
                        E = E.Next;
                    }
                    while (E != tEdge2 && E.Dx == -3.4E+38)
                    {
                        E = E.Prev;
                    }
                }
                else
                {
                    while (E.Top.Y == E.Prev.Bot.Y)
                    {
                        E = E.Prev;
                    }
                    while (E != tEdge2 && E.Dx == -3.4E+38)
                    {
                        E = E.Next;
                    }
                }
                if (E == tEdge2)
                {
                    tEdge2 = ((!IsClockwise) ? E.Prev : E.Next);
                }
                else
                {
                    E = ((!IsClockwise) ? tEdge2.Prev : tEdge2.Next);
                    LocalMinima localMinima = new LocalMinima();
                    localMinima.Next                 = null;
                    localMinima.Y                    = E.Bot.Y;
                    localMinima.LeftBound            = null;
                    localMinima.RightBound           = E;
                    localMinima.RightBound.WindDelta = 0;
                    tEdge2 = ProcessBound(localMinima.RightBound, IsClockwise);
                    InsertLocalMinima(localMinima);
                }
            }
            return(tEdge2);
        }
Пример #15
0
        //------------------------------------------------------------------------------
        internal virtual void Reset()
        {
            m_CurrentLM = m_MinimaList;
            if (m_CurrentLM == null) return; //ie nothing to process

            //reset all edges ...
            m_Scanbeam = null;
            LocalMinima lm = m_MinimaList;
            while (lm != null)
            {
                InsertScanbeam(lm.Y);
                TEdge e = lm.LeftBound;
                if (e != null)
                {
                    e.Curr = e.Bot;
                    e.OutIdx = Unassigned;
                }
                e = lm.RightBound;
                if (e != null)
                {
                    e.Curr = e.Bot;
                    e.OutIdx = Unassigned;
                }
                lm = lm.Next;
            }
            m_ActiveEdges = null;
        }
Пример #16
0
        //------------------------------------------------------------------------------

        public IntRect GetBounds()
        {
            IntRect     result = new IntRect();
            LocalMinima lm     = m_MinimaList;

            if (lm == null)
            {
                return(result);
            }
            result.left   = lm.LeftBound.Bot.X;
            result.top    = lm.LeftBound.Bot.Y;
            result.right  = lm.LeftBound.Bot.X;
            result.bottom = lm.LeftBound.Bot.Y;
            while (lm != null)
            {
                if (lm.LeftBound.Bot.Y > result.bottom)
                {
                    result.bottom = lm.LeftBound.Bot.Y;
                }
                TEdge e = lm.LeftBound;
                for (; ;)
                {
                    TEdge bottomE = e;
                    while (e.NextInLML != null)
                    {
                        if (e.Bot.X < result.left)
                        {
                            result.left = e.Bot.X;
                        }
                        if (e.Bot.X > result.right)
                        {
                            result.right = e.Bot.X;
                        }
                        e = e.NextInLML;
                    }
                    if (e.Bot.X < result.left)
                    {
                        result.left = e.Bot.X;
                    }
                    if (e.Bot.X > result.right)
                    {
                        result.right = e.Bot.X;
                    }
                    if (e.Top.X < result.left)
                    {
                        result.left = e.Top.X;
                    }
                    if (e.Top.X > result.right)
                    {
                        result.right = e.Top.X;
                    }
                    if (e.Top.Y < result.top)
                    {
                        result.top = e.Top.Y;
                    }

                    if (bottomE == lm.LeftBound)
                    {
                        e = lm.RightBound;
                    }
                    else
                    {
                        break;
                    }
                }
                lm = lm.Next;
            }
            return(result);
        }
Пример #17
0
        //------------------------------------------------------------------------------
        public bool AddPath(List<IntPoint> pg, PolyType polyType, bool Closed)
        {
            #if use_lines
              if (!Closed && polyType == PolyType.ptClip)
            throw new ClipperException("AddPath: Open paths must be subject.");
            #else
            if (!Closed)
                throw new ClipperException("AddPath: Open paths have been disabled.");
            #endif

            int highI = (int)pg.Count - 1;
            if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI;
            while (highI > 0 && (pg[highI] == pg[highI - 1])) --highI;
            if ((Closed && highI < 2) || (!Closed && highI < 1)) return false;

            //create a new edge array ...
            List<TEdge> edges = new List<TEdge>(highI + 1);
            for (int i = 0; i <= highI; i++) edges.Add(new TEdge());

            bool IsFlat = true;

            //1. Basic (first) edge initialization ...
            edges[1].Curr = pg[1];
            RangeTest(pg[0], ref m_UseFullRange);
            RangeTest(pg[highI], ref m_UseFullRange);
            InitEdge(edges[0], edges[1], edges[highI], pg[0]);
            InitEdge(edges[highI], edges[0], edges[highI - 1], pg[highI]);
            for (int i = highI - 1; i >= 1; --i)
            {
                RangeTest(pg[i], ref m_UseFullRange);
                InitEdge(edges[i], edges[i + 1], edges[i - 1], pg[i]);
            }
            TEdge eStart = edges[0];

            //2. Remove duplicate vertices, and (when closed) collinear edges ...
            TEdge E = eStart, eLoopStop = eStart;
            for (;;)
            {
                //nb: allows matching start and end points when not Closed ...
                if (E.Curr == E.Next.Curr && (Closed || E.Next != eStart))
                {
                    if (E == E.Next) break;
                    if (E == eStart) eStart = E.Next;
                    E = RemoveEdge(E);
                    eLoopStop = E;
                    continue;
                }
                if (E.Prev == E.Next)
                    break; //only two vertices
                else if (Closed &&
                  SlopesEqual(E.Prev.Curr, E.Curr, E.Next.Curr, m_UseFullRange) &&
                  (!PreserveCollinear ||
                  !Pt2IsBetweenPt1AndPt3(E.Prev.Curr, E.Curr, E.Next.Curr)))
                {
                    //Collinear edges are allowed for open paths but in closed paths
                    //the default is to merge adjacent collinear edges into a single edge.
                    //However, if the PreserveCollinear property is enabled, only overlapping
                    //collinear edges (ie spikes) will be removed from closed paths.
                    if (E == eStart) eStart = E.Next;
                    E = RemoveEdge(E);
                    E = E.Prev;
                    eLoopStop = E;
                    continue;
                }
                E = E.Next;
                if ((E == eLoopStop) || (!Closed && E.Next == eStart)) break;
            }

            if ((!Closed && (E == E.Next)) || (Closed && (E.Prev == E.Next)))
                return false;

            if (!Closed)
            {
                m_HasOpenPaths = true;
                eStart.Prev.OutIdx = Skip;
            }

            //3. Do second stage of edge initialization ...
            E = eStart;
            do
            {
                InitEdge2(E, polyType);
                E = E.Next;
                if (IsFlat && E.Curr.Y != eStart.Curr.Y) IsFlat = false;
            }
            while (E != eStart);

            //4. Finally, add edge bounds to LocalMinima list ...

            //Totally flat paths must be handled differently when adding them
            //to LocalMinima list to avoid endless loops etc ...
            if (IsFlat)
            {
                if (Closed) return false;
                E.Prev.OutIdx = Skip;
                LocalMinima locMin = new LocalMinima();
                locMin.Next = null;
                locMin.Y = E.Bot.Y;
                locMin.LeftBound = null;
                locMin.RightBound = E;
                locMin.RightBound.Side = EdgeSide.esRight;
                locMin.RightBound.WindDelta = 0;
                for (;;)
                {
                    if (E.Bot.X != E.Prev.Top.X) ReverseHorizontal(E);
                    if (E.Next.OutIdx == Skip) break;
                    E.NextInLML = E.Next;
                    E = E.Next;
                }
                InsertLocalMinima(locMin);
                m_edges.Add(edges);
                return true;
            }

            m_edges.Add(edges);
            bool leftBoundIsForward;
            TEdge EMin = null;

            //workaround to avoid an endless loop in the while loop below when
            //open paths have matching start and end points ...
            if (E.Prev.Bot == E.Prev.Top) E = E.Next;

            for (;;)
            {
                E = FindNextLocMin(E);
                if (E == EMin) break;
                else if (EMin == null) EMin = E;

                //E and E.Prev now share a local minima (left aligned if horizontal).
                //Compare their slopes to find which starts which bound ...
                LocalMinima locMin = new LocalMinima();
                locMin.Next = null;
                locMin.Y = E.Bot.Y;
                if (E.Dx < E.Prev.Dx)
                {
                    locMin.LeftBound = E.Prev;
                    locMin.RightBound = E;
                    leftBoundIsForward = false; //Q.nextInLML = Q.prev
                }
                else
                {
                    locMin.LeftBound = E;
                    locMin.RightBound = E.Prev;
                    leftBoundIsForward = true; //Q.nextInLML = Q.next
                }
                locMin.LeftBound.Side = EdgeSide.esLeft;
                locMin.RightBound.Side = EdgeSide.esRight;

                if (!Closed) locMin.LeftBound.WindDelta = 0;
                else if (locMin.LeftBound.Next == locMin.RightBound)
                    locMin.LeftBound.WindDelta = -1;
                else locMin.LeftBound.WindDelta = 1;
                locMin.RightBound.WindDelta = -locMin.LeftBound.WindDelta;

                E = ProcessBound(locMin.LeftBound, leftBoundIsForward);
                if (E.OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward);

                TEdge E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward);
                if (E2.OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward);

                if (locMin.LeftBound.OutIdx == Skip)
                    locMin.LeftBound = null;
                else if (locMin.RightBound.OutIdx == Skip)
                    locMin.RightBound = null;
                InsertLocalMinima(locMin);
                if (!leftBoundIsForward) E = E2;
            }
            return true;
        }
Пример #18
0
        //------------------------------------------------------------------------------
        private TEdge ProcessBound(TEdge E, bool LeftBoundIsForward)
        {
            TEdge EStart, Result = E;
            TEdge Horz;

            if (Result.OutIdx == Skip)
            {
                //check if there are edges beyond the skip edge in the bound and if so
                //create another LocMin and calling ProcessBound once more ...
                E = Result;
                if (LeftBoundIsForward)
                {
                    while (E.Top.Y == E.Next.Bot.Y) E = E.Next;
                    while (E != Result && E.Dx == horizontal) E = E.Prev;
                }
                else
                {
                    while (E.Top.Y == E.Prev.Bot.Y) E = E.Prev;
                    while (E != Result && E.Dx == horizontal) E = E.Next;
                }
                if (E == Result)
                {
                    if (LeftBoundIsForward) Result = E.Next;
                    else Result = E.Prev;
                }
                else
                {
                    //there are more edges in the bound beyond result starting with E
                    if (LeftBoundIsForward)
                        E = Result.Next;
                    else
                        E = Result.Prev;
                    LocalMinima locMin = new LocalMinima();
                    locMin.Next = null;
                    locMin.Y = E.Bot.Y;
                    locMin.LeftBound = null;
                    locMin.RightBound = E;
                    E.WindDelta = 0;
                    Result = ProcessBound(E, LeftBoundIsForward);
                    InsertLocalMinima(locMin);
                }
                return Result;
            }

            if (E.Dx == horizontal)
            {
                //We need to be careful with open paths because this may not be a
                //true local minima (ie E may be following a skip edge).
                //Also, consecutive horz. edges may start heading left before going right.
                if (LeftBoundIsForward) EStart = E.Prev;
                else EStart = E.Next;
                if (EStart.Dx == horizontal) //ie an adjoining horizontal skip edge
                {
                    if (EStart.Bot.X != E.Bot.X && EStart.Top.X != E.Bot.X)
                        ReverseHorizontal(E);
                }
                else if (EStart.Bot.X != E.Bot.X)
                    ReverseHorizontal(E);
            }

            EStart = E;
            if (LeftBoundIsForward)
            {
                while (Result.Top.Y == Result.Next.Bot.Y && Result.Next.OutIdx != Skip)
                    Result = Result.Next;
                if (Result.Dx == horizontal && Result.Next.OutIdx != Skip)
                {
                    //nb: at the top of a bound, horizontals are added to the bound
                    //only when the preceding edge attaches to the horizontal's left vertex
                    //unless a Skip edge is encountered when that becomes the top divide
                    Horz = Result;
                    while (Horz.Prev.Dx == horizontal) Horz = Horz.Prev;
                    if (Horz.Prev.Top.X > Result.Next.Top.X) Result = Horz.Prev;
                }
                while (E != Result)
                {
                    E.NextInLML = E.Next;
                    if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Prev.Top.X)
                        ReverseHorizontal(E);
                    E = E.Next;
                }
                if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Prev.Top.X)
                    ReverseHorizontal(E);
                Result = Result.Next; //move to the edge just beyond current bound
            }
            else
            {
                while (Result.Top.Y == Result.Prev.Bot.Y && Result.Prev.OutIdx != Skip)
                    Result = Result.Prev;
                if (Result.Dx == horizontal && Result.Prev.OutIdx != Skip)
                {
                    Horz = Result;
                    while (Horz.Next.Dx == horizontal) Horz = Horz.Next;
                    if (Horz.Next.Top.X == Result.Prev.Top.X ||
                        Horz.Next.Top.X > Result.Prev.Top.X) Result = Horz.Next;
                }

                while (E != Result)
                {
                    E.NextInLML = E.Prev;
                    if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Next.Top.X)
                        ReverseHorizontal(E);
                    E = E.Prev;
                }
                if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Next.Top.X)
                    ReverseHorizontal(E);
                Result = Result.Prev; //move to the edge just beyond current bound
            }
            return Result;
        }
Пример #19
0
      //---------------------------------------------------------------------------

      void DoMinimaLML(TEdge E1, TEdge E2, bool IsClosed)
      {
        if (E1 == null)
        {
          if (E2 == null) return;
          LocalMinima NewLm = new LocalMinima();
          NewLm.Next = null;
          NewLm.Y = E2.Bot.Y;
          NewLm.LeftBound = null;
          E2.WindDelta = 0;
          NewLm.RightBound = E2;
          InsertLocalMinima(NewLm);
        } else
        {
          //E and E.Prev are now at a local minima ...
          LocalMinima NewLm = new LocalMinima();
          NewLm.Y = E1.Bot.Y;
          NewLm.Next = null;
          if (IsHorizontal(E2)) //Horz. edges never start a Left bound
          {
            if (E2.Bot.X != E1.Bot.X) ReverseHorizontal(E2);
            NewLm.LeftBound = E1;
            NewLm.RightBound = E2;
          } else if (E2.Dx < E1.Dx)
          {
            NewLm.LeftBound = E1;
            NewLm.RightBound = E2;
          } else
          {
            NewLm.LeftBound = E2;
            NewLm.RightBound = E1;
          }
          NewLm.LeftBound.Side = EdgeSide.esLeft;
          NewLm.RightBound.Side = EdgeSide.esRight;
          //set the winding state of the first edge in each bound
          //(it'll be copied to subsequent edges in the bound) ...
          if (!IsClosed) NewLm.LeftBound.WindDelta = 0;
          else if (NewLm.LeftBound.Next == NewLm.RightBound) NewLm.LeftBound.WindDelta = -1;
          else NewLm.LeftBound.WindDelta = 1;
          NewLm.RightBound.WindDelta = -NewLm.LeftBound.WindDelta;
          InsertLocalMinima(NewLm);
        }
      }
Пример #20
0
      //------------------------------------------------------------------------------

      protected virtual void Reset()
      {
        m_CurrentLM = m_MinimaList;
        if (m_CurrentLM == null) return; //ie nothing to process

        //reset all edges ...
        LocalMinima lm = m_MinimaList;
        while (lm != null)
        {
          TEdge e = lm.LeftBound;
          if (e != null)
          {
            e.Curr = e.Bot;
            e.Side = EdgeSide.esLeft;
            if (e.OutIdx != Skip)
              e.OutIdx = Unassigned;
          }
          e = lm.RightBound;
          e.Curr = e.Bot;
          e.Side = EdgeSide.esRight;
          if (e.OutIdx != Skip)
            e.OutIdx = Unassigned;

          lm = lm.Next;
        }
      }
Пример #21
0
        //---------------------------------------------------------------------------

        void DoMinimaLML(TEdge E1, TEdge E2, bool IsClosed)
        {
            if (E1 == null)
            {
                if (E2 == null)
                {
                    return;
                }
                LocalMinima NewLm = new LocalMinima();
                NewLm.Next       = null;
                NewLm.Y          = E2.Bot.Y;
                NewLm.LeftBound  = null;
                E2.WindDelta     = 0;
                NewLm.RightBound = E2;
                InsertLocalMinima(NewLm);
            }
            else
            {
                //E and E.Prev are now at a local minima ...
                LocalMinima NewLm = new LocalMinima();
                NewLm.Y    = E1.Bot.Y;
                NewLm.Next = null;
                if (IsHorizontal(E2)) //Horz. edges never start a Left bound
                {
                    if (E2.Bot.X != E1.Bot.X)
                    {
                        ReverseHorizontal(E2);
                    }
                    NewLm.LeftBound  = E1;
                    NewLm.RightBound = E2;
                }
                else if (E2.Dx < E1.Dx)
                {
                    NewLm.LeftBound  = E1;
                    NewLm.RightBound = E2;
                }
                else
                {
                    NewLm.LeftBound  = E2;
                    NewLm.RightBound = E1;
                }
                NewLm.LeftBound.Side  = EdgeSide.esLeft;
                NewLm.RightBound.Side = EdgeSide.esRight;
                //set the winding state of the first edge in each bound
                //(it'll be copied to subsequent edges in the bound) ...
                if (!IsClosed)
                {
                    NewLm.LeftBound.WindDelta = 0;
                }
                else if (NewLm.LeftBound.Next == NewLm.RightBound)
                {
                    NewLm.LeftBound.WindDelta = -1;
                }
                else
                {
                    NewLm.LeftBound.WindDelta = 1;
                }
                NewLm.RightBound.WindDelta = -NewLm.LeftBound.WindDelta;
                InsertLocalMinima(NewLm);
            }
        }
        private TEdge ProcessBound(TEdge E, bool LeftBoundIsForward)
        {
            TEdge tEdge = E;

            if (tEdge.OutIdx == -2)
            {
                E = tEdge;
                if (!LeftBoundIsForward)
                {
                    while (E.Top.Y == E.Prev.Bot.Y)
                    {
                        E = E.Prev;
                    }
                    while (E != tEdge && E.Dx == -3.4E+38)
                    {
                        E = E.Next;
                    }
                }
                else
                {
                    while (E.Top.Y == E.Next.Bot.Y)
                    {
                        E = E.Next;
                    }
                    while (E != tEdge && E.Dx == -3.4E+38)
                    {
                        E = E.Prev;
                    }
                }
                if (E == tEdge)
                {
                    tEdge = ((!LeftBoundIsForward) ? E.Prev : E.Next);
                }
                else
                {
                    E = ((!LeftBoundIsForward) ? tEdge.Prev : tEdge.Next);
                    LocalMinima localMinima = new LocalMinima();
                    localMinima.Next       = null;
                    localMinima.Y          = E.Bot.Y;
                    localMinima.LeftBound  = null;
                    localMinima.RightBound = E;
                    E.WindDelta            = 0;
                    tEdge = ProcessBound(E, LeftBoundIsForward);
                    InsertLocalMinima(localMinima);
                }
                return(tEdge);
            }
            TEdge tEdge2;

            if (E.Dx == -3.4E+38)
            {
                tEdge2 = ((!LeftBoundIsForward) ? E.Next : E.Prev);
                if (tEdge2.OutIdx != -2)
                {
                    if (tEdge2.Dx == -3.4E+38)
                    {
                        if (tEdge2.Bot.X != E.Bot.X && tEdge2.Top.X != E.Bot.X)
                        {
                            ReverseHorizontal(E);
                        }
                    }
                    else if (tEdge2.Bot.X != E.Bot.X)
                    {
                        ReverseHorizontal(E);
                    }
                }
            }
            tEdge2 = E;
            if (!LeftBoundIsForward)
            {
                while (tEdge.Top.Y == tEdge.Prev.Bot.Y && tEdge.Prev.OutIdx != -2)
                {
                    tEdge = tEdge.Prev;
                }
                if (tEdge.Dx == -3.4E+38 && tEdge.Prev.OutIdx != -2)
                {
                    TEdge tEdge3 = tEdge;
                    while (tEdge3.Next.Dx == -3.4E+38)
                    {
                        tEdge3 = tEdge3.Next;
                    }
                    if (tEdge3.Next.Top.X == tEdge.Prev.Top.X)
                    {
                        if (!LeftBoundIsForward)
                        {
                            tEdge = tEdge3.Next;
                        }
                    }
                    else if (tEdge3.Next.Top.X > tEdge.Prev.Top.X)
                    {
                        tEdge = tEdge3.Next;
                    }
                }
                while (E != tEdge)
                {
                    E.NextInLML = E.Prev;
                    if (E.Dx == -3.4E+38 && E != tEdge2 && E.Bot.X != E.Next.Top.X)
                    {
                        ReverseHorizontal(E);
                    }
                    E = E.Prev;
                }
                if (E.Dx == -3.4E+38 && E != tEdge2 && E.Bot.X != E.Next.Top.X)
                {
                    ReverseHorizontal(E);
                }
                return(tEdge.Prev);
            }
            while (tEdge.Top.Y == tEdge.Next.Bot.Y && tEdge.Next.OutIdx != -2)
            {
                tEdge = tEdge.Next;
            }
            if (tEdge.Dx == -3.4E+38 && tEdge.Next.OutIdx != -2)
            {
                TEdge tEdge3 = tEdge;
                while (tEdge3.Prev.Dx == -3.4E+38)
                {
                    tEdge3 = tEdge3.Prev;
                }
                if (tEdge3.Prev.Top.X == tEdge.Next.Top.X)
                {
                    if (!LeftBoundIsForward)
                    {
                        tEdge = tEdge3.Prev;
                    }
                }
                else if (tEdge3.Prev.Top.X > tEdge.Next.Top.X)
                {
                    tEdge = tEdge3.Prev;
                }
            }
            while (E != tEdge)
            {
                E.NextInLML = E.Next;
                if (E.Dx == -3.4E+38 && E != tEdge2 && E.Bot.X != E.Prev.Top.X)
                {
                    ReverseHorizontal(E);
                }
                E = E.Next;
            }
            if (E.Dx == -3.4E+38 && E != tEdge2 && E.Bot.X != E.Prev.Top.X)
            {
                ReverseHorizontal(E);
            }
            return(tEdge.Next);
        }
Пример #23
0
        //------------------------------------------------------------------------------

        internal ClipperBase() //constructor (nb: no external instantiation)
        {
            m_MinimaList = null;
            m_CurrentLM = null;
            m_UseFullRange = false;
        }
        public bool AddPath(List <IntPoint> pg, PolyType polyType, bool Closed)
        {
            if (!Closed)
            {
                throw new ClipperException("AddPath: Open paths have been disabled.");
            }
            int num = pg.Count - 1;

            if (Closed)
            {
                while (num > 0 && pg[num] == pg[0])
                {
                    num--;
                }
            }
            while (num > 0 && pg[num] == pg[num - 1])
            {
                num--;
            }
            if ((Closed && num < 2) || (!Closed && num < 1))
            {
                return(false);
            }
            List <TEdge> list = new List <TEdge>(num + 1);

            for (int i = 0; i <= num; i++)
            {
                list.Add(new TEdge());
            }
            bool flag = true;

            list[1].Curr = pg[1];
            RangeTest(pg[0], ref m_UseFullRange);
            RangeTest(pg[num], ref m_UseFullRange);
            InitEdge(list[0], list[1], list[num], pg[0]);
            InitEdge(list[num], list[0], list[num - 1], pg[num]);
            for (int num2 = num - 1; num2 >= 1; num2--)
            {
                RangeTest(pg[num2], ref m_UseFullRange);
                InitEdge(list[num2], list[num2 + 1], list[num2 - 1], pg[num2]);
            }
            TEdge tEdge  = list[0];
            TEdge tEdge2 = tEdge;
            TEdge tEdge3 = tEdge;

            while (true)
            {
                if (tEdge2.Curr == tEdge2.Next.Curr && (Closed || tEdge2.Next != tEdge))
                {
                    if (tEdge2 == tEdge2.Next)
                    {
                        break;
                    }
                    if (tEdge2 == tEdge)
                    {
                        tEdge = tEdge2.Next;
                    }
                    tEdge2 = RemoveEdge(tEdge2);
                    tEdge3 = tEdge2;
                }
                else
                {
                    if (tEdge2.Prev == tEdge2.Next)
                    {
                        break;
                    }
                    if (Closed && SlopesEqual(tEdge2.Prev.Curr, tEdge2.Curr, tEdge2.Next.Curr, m_UseFullRange) && (!PreserveCollinear || !Pt2IsBetweenPt1AndPt3(tEdge2.Prev.Curr, tEdge2.Curr, tEdge2.Next.Curr)))
                    {
                        if (tEdge2 == tEdge)
                        {
                            tEdge = tEdge2.Next;
                        }
                        tEdge2 = RemoveEdge(tEdge2);
                        tEdge2 = tEdge2.Prev;
                        tEdge3 = tEdge2;
                    }
                    else
                    {
                        tEdge2 = tEdge2.Next;
                        if (tEdge2 == tEdge3 || (!Closed && tEdge2.Next == tEdge))
                        {
                            break;
                        }
                    }
                }
            }
            if ((!Closed && tEdge2 == tEdge2.Next) || (Closed && tEdge2.Prev == tEdge2.Next))
            {
                return(false);
            }
            if (!Closed)
            {
                m_HasOpenPaths    = true;
                tEdge.Prev.OutIdx = -2;
            }
            tEdge2 = tEdge;
            do
            {
                InitEdge2(tEdge2, polyType);
                tEdge2 = tEdge2.Next;
                if (flag && tEdge2.Curr.Y != tEdge.Curr.Y)
                {
                    flag = false;
                }
            }while (tEdge2 != tEdge);
            if (flag)
            {
                if (Closed)
                {
                    return(false);
                }
                tEdge2.Prev.OutIdx = -2;
                if (tEdge2.Prev.Bot.X < tEdge2.Prev.Top.X)
                {
                    ReverseHorizontal(tEdge2.Prev);
                }
                LocalMinima localMinima = new LocalMinima();
                localMinima.Next                 = null;
                localMinima.Y                    = tEdge2.Bot.Y;
                localMinima.LeftBound            = null;
                localMinima.RightBound           = tEdge2;
                localMinima.RightBound.Side      = EdgeSide.esRight;
                localMinima.RightBound.WindDelta = 0;
                while (tEdge2.Next.OutIdx != -2)
                {
                    tEdge2.NextInLML = tEdge2.Next;
                    if (tEdge2.Bot.X != tEdge2.Prev.Top.X)
                    {
                        ReverseHorizontal(tEdge2);
                    }
                    tEdge2 = tEdge2.Next;
                }
                InsertLocalMinima(localMinima);
                m_edges.Add(list);
                return(true);
            }
            m_edges.Add(list);
            TEdge tEdge4 = null;

            if (tEdge2.Prev.Bot == tEdge2.Prev.Top)
            {
                tEdge2 = tEdge2.Next;
            }
            while (true)
            {
                tEdge2 = FindNextLocMin(tEdge2);
                if (tEdge2 == tEdge4)
                {
                    break;
                }
                if (tEdge4 == null)
                {
                    tEdge4 = tEdge2;
                }
                LocalMinima localMinima2 = new LocalMinima();
                localMinima2.Next = null;
                localMinima2.Y    = tEdge2.Bot.Y;
                bool flag2;
                if (tEdge2.Dx < tEdge2.Prev.Dx)
                {
                    localMinima2.LeftBound  = tEdge2.Prev;
                    localMinima2.RightBound = tEdge2;
                    flag2 = false;
                }
                else
                {
                    localMinima2.LeftBound  = tEdge2;
                    localMinima2.RightBound = tEdge2.Prev;
                    flag2 = true;
                }
                localMinima2.LeftBound.Side  = EdgeSide.esLeft;
                localMinima2.RightBound.Side = EdgeSide.esRight;
                if (!Closed)
                {
                    localMinima2.LeftBound.WindDelta = 0;
                }
                else if (localMinima2.LeftBound.Next == localMinima2.RightBound)
                {
                    localMinima2.LeftBound.WindDelta = -1;
                }
                else
                {
                    localMinima2.LeftBound.WindDelta = 1;
                }
                localMinima2.RightBound.WindDelta = -localMinima2.LeftBound.WindDelta;
                tEdge2 = ProcessBound(localMinima2.LeftBound, flag2);
                if (tEdge2.OutIdx == -2)
                {
                    tEdge2 = ProcessBound(tEdge2, flag2);
                }
                TEdge tEdge5 = ProcessBound(localMinima2.RightBound, !flag2);
                if (tEdge5.OutIdx == -2)
                {
                    tEdge5 = ProcessBound(tEdge5, !flag2);
                }
                if (localMinima2.LeftBound.OutIdx == -2)
                {
                    localMinima2.LeftBound = null;
                }
                else if (localMinima2.RightBound.OutIdx == -2)
                {
                    localMinima2.RightBound = null;
                }
                InsertLocalMinima(localMinima2);
                if (!flag2)
                {
                    tEdge2 = tEdge5;
                }
            }
            return(true);
        }
        //------------------------------------------------------------------------------
        protected virtual void Reset()
        {
            m_CurrentLM = m_MinimaList;

            //reset all edges ...
            LocalMinima lm = m_MinimaList;
            while (lm != null)
            {
                TEdge e = lm.leftBound;
                while (e != null)
                {
                    e.xcurr = e.xbot;
                    e.ycurr = e.ybot;
                    e.side = EdgeSide.esLeft;
                    e.outIdx = -1;
                    e = e.nextInLML;
                }
                e = lm.rightBound;
                while (e != null)
                {
                    e.xcurr = e.xbot;
                    e.ycurr = e.ybot;
                    e.side = EdgeSide.esRight;
                    e.outIdx = -1;
                    e = e.nextInLML;
                }
                lm = lm.next;
            }
            return;
        }
 //------------------------------------------------------------------------------
 private void DisposeLocalMinimaList()
 {
     while( m_MinimaList != null )
     {
         LocalMinima tmpLm = m_MinimaList.next;
         m_MinimaList = null;
         m_MinimaList = tmpLm;
     }
     m_CurrentLM = null;
 }
Пример #27
0
 //------------------------------------------------------------------------------
 internal Boolean PopLocalMinima(int Y, out LocalMinima current)
 {
     current = m_CurrentLM;
     if (m_CurrentLM != null && m_CurrentLM.Y == Y)
     {
         m_CurrentLM = m_CurrentLM.Next;
         return true;
     }
     return false;
 }
 //------------------------------------------------------------------------------
 protected void PopLocalMinima()
 {
     if (m_CurrentLM == null) return;
     m_CurrentLM = m_CurrentLM.next;
 }
Пример #29
0
        //------------------------------------------------------------------------------

        private TEdge ProcessBound(TEdge E, bool LeftBoundIsForward)
        {
            TEdge EStart, Result = E;
            TEdge Horz;

            if (Result.OutIdx == Skip)
            {
                //check if there are edges beyond the skip edge in the bound and if so
                //create another LocMin and calling ProcessBound once more ...
                E = Result;
                if (LeftBoundIsForward)
                {
                    while (E.Top.Y == E.Next.Bot.Y)
                    {
                        E = E.Next;
                    }
                    while (E != Result && E.Dx == horizontal)
                    {
                        E = E.Prev;
                    }
                }
                else
                {
                    while (E.Top.Y == E.Prev.Bot.Y)
                    {
                        E = E.Prev;
                    }
                    while (E != Result && E.Dx == horizontal)
                    {
                        E = E.Next;
                    }
                }
                if (E == Result)
                {
                    if (LeftBoundIsForward)
                    {
                        Result = E.Next;
                    }
                    else
                    {
                        Result = E.Prev;
                    }
                }
                else
                {
                    //there are more edges in the bound beyond result starting with E
                    if (LeftBoundIsForward)
                    {
                        E = Result.Next;
                    }
                    else
                    {
                        E = Result.Prev;
                    }
                    LocalMinima locMin = new LocalMinima();
                    locMin.Next       = null;
                    locMin.Y          = E.Bot.Y;
                    locMin.LeftBound  = null;
                    locMin.RightBound = E;
                    E.WindDelta       = 0;
                    Result            = ProcessBound(E, LeftBoundIsForward);
                    InsertLocalMinima(locMin);
                }
                return(Result);
            }

            if (E.Dx == horizontal)
            {
                //We need to be careful with open paths because this may not be a
                //true local minima (ie E may be following a skip edge).
                //Also, consecutive horz. edges may start heading left before going right.
                if (LeftBoundIsForward)
                {
                    EStart = E.Prev;
                }
                else
                {
                    EStart = E.Next;
                }
                if (EStart.Dx == horizontal) //ie an adjoining horizontal skip edge
                {
                    if (EStart.Bot.X != E.Bot.X && EStart.Top.X != E.Bot.X)
                    {
                        ReverseHorizontal(E);
                    }
                }
                else if (EStart.Bot.X != E.Bot.X)
                {
                    ReverseHorizontal(E);
                }
            }

            EStart = E;
            if (LeftBoundIsForward)
            {
                while (Result.Top.Y == Result.Next.Bot.Y && Result.Next.OutIdx != Skip)
                {
                    Result = Result.Next;
                }
                if (Result.Dx == horizontal && Result.Next.OutIdx != Skip)
                {
                    //nb: at the top of a bound, horizontals are added to the bound
                    //only when the preceding edge attaches to the horizontal's left vertex
                    //unless a Skip edge is encountered when that becomes the top divide
                    Horz = Result;
                    while (Horz.Prev.Dx == horizontal)
                    {
                        Horz = Horz.Prev;
                    }
                    if (Horz.Prev.Top.X > Result.Next.Top.X)
                    {
                        Result = Horz.Prev;
                    }
                }
                while (E != Result)
                {
                    E.NextInLML = E.Next;
                    if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Prev.Top.X)
                    {
                        ReverseHorizontal(E);
                    }
                    E = E.Next;
                }
                if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Prev.Top.X)
                {
                    ReverseHorizontal(E);
                }
                Result = Result.Next; //move to the edge just beyond current bound
            }
            else
            {
                while (Result.Top.Y == Result.Prev.Bot.Y && Result.Prev.OutIdx != Skip)
                {
                    Result = Result.Prev;
                }
                if (Result.Dx == horizontal && Result.Prev.OutIdx != Skip)
                {
                    Horz = Result;
                    while (Horz.Next.Dx == horizontal)
                    {
                        Horz = Horz.Next;
                    }
                    if (Horz.Next.Top.X == Result.Prev.Top.X ||
                        Horz.Next.Top.X > Result.Prev.Top.X)
                    {
                        Result = Horz.Next;
                    }
                }

                while (E != Result)
                {
                    E.NextInLML = E.Prev;
                    if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Next.Top.X)
                    {
                        ReverseHorizontal(E);
                    }
                    E = E.Prev;
                }
                if (E.Dx == horizontal && E != EStart && E.Bot.X != E.Next.Top.X)
                {
                    ReverseHorizontal(E);
                }
                Result = Result.Prev; //move to the edge just beyond current bound
            }
            return(Result);
        }
        //---------------------------------------------------------------------------
        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;
        }
Пример #31
0
        //------------------------------------------------------------------------------


        public bool AddPath(List <IntPoint> pg, PolyType polyType, bool Closed)
        {
#if use_lines
            if (!Closed && polyType == PolyType.ptClip)
            {
                throw new ClipperException("AddPath: Open paths must be subject.");
            }
#else
            if (!Closed)
            {
                throw new ClipperException("AddPath: Open paths have been disabled.");
            }
#endif

            int highI = (int)pg.Count - 1;
            if (Closed)
            {
                while (highI > 0 && (pg[highI] == pg[0]))
                {
                    --highI;
                }
            }
            while (highI > 0 && (pg[highI] == pg[highI - 1]))
            {
                --highI;
            }
            if ((Closed && highI < 2) || (!Closed && highI < 1))
            {
                return(false);
            }

            //create a new edge array ...
            List <TEdge> edges = new List <TEdge>(highI + 1);
            for (int i = 0; i <= highI; i++)
            {
                edges.Add(new TEdge());
            }

            bool IsFlat = true;

            //1. Basic (first) edge initialization ...
            edges[1].Curr = pg[1];
            RangeTest(pg[0], ref m_UseFullRange);
            RangeTest(pg[highI], ref m_UseFullRange);
            InitEdge(edges[0], edges[1], edges[highI], pg[0]);
            InitEdge(edges[highI], edges[0], edges[highI - 1], pg[highI]);
            for (int i = highI - 1; i >= 1; --i)
            {
                RangeTest(pg[i], ref m_UseFullRange);
                InitEdge(edges[i], edges[i + 1], edges[i - 1], pg[i]);
            }
            TEdge eStart = edges[0];

            //2. Remove duplicate vertices, and (when closed) collinear edges ...
            TEdge E = eStart, eLoopStop = eStart;
            for (;;)
            {
                //nb: allows matching start and end points when not Closed ...
                if (E.Curr == E.Next.Curr && (Closed || E.Next != eStart))
                {
                    if (E == E.Next)
                    {
                        break;
                    }
                    if (E == eStart)
                    {
                        eStart = E.Next;
                    }
                    E         = RemoveEdge(E);
                    eLoopStop = E;
                    continue;
                }
                if (E.Prev == E.Next)
                {
                    break; //only two vertices
                }
                else if (Closed &&
                         SlopesEqual(E.Prev.Curr, E.Curr, E.Next.Curr, m_UseFullRange) &&
                         (!PreserveCollinear ||
                          !Pt2IsBetweenPt1AndPt3(E.Prev.Curr, E.Curr, E.Next.Curr)))
                {
                    //Collinear edges are allowed for open paths but in closed paths
                    //the default is to merge adjacent collinear edges into a single edge.
                    //However, if the PreserveCollinear property is enabled, only overlapping
                    //collinear edges (ie spikes) will be removed from closed paths.
                    if (E == eStart)
                    {
                        eStart = E.Next;
                    }
                    E         = RemoveEdge(E);
                    E         = E.Prev;
                    eLoopStop = E;
                    continue;
                }
                E = E.Next;
                if ((E == eLoopStop) || (!Closed && E.Next == eStart))
                {
                    break;
                }
            }

            if ((!Closed && (E == E.Next)) || (Closed && (E.Prev == E.Next)))
            {
                return(false);
            }

            if (!Closed)
            {
                m_HasOpenPaths     = true;
                eStart.Prev.OutIdx = Skip;
            }

            //3. Do second stage of edge initialization ...
            E = eStart;
            do
            {
                InitEdge2(E, polyType);
                E = E.Next;
                if (IsFlat && E.Curr.Y != eStart.Curr.Y)
                {
                    IsFlat = false;
                }
            }while (E != eStart);

            //4. Finally, add edge bounds to LocalMinima list ...

            //Totally flat paths must be handled differently when adding them
            //to LocalMinima list to avoid endless loops etc ...
            if (IsFlat)
            {
                if (Closed)
                {
                    return(false);
                }
                E.Prev.OutIdx = Skip;
                LocalMinima locMin = new LocalMinima();
                locMin.Next                 = null;
                locMin.Y                    = E.Bot.Y;
                locMin.LeftBound            = null;
                locMin.RightBound           = E;
                locMin.RightBound.Side      = EdgeSide.esRight;
                locMin.RightBound.WindDelta = 0;
                for (;;)
                {
                    if (E.Bot.X != E.Prev.Top.X)
                    {
                        ReverseHorizontal(E);
                    }
                    if (E.Next.OutIdx == Skip)
                    {
                        break;
                    }
                    E.NextInLML = E.Next;
                    E           = E.Next;
                }
                InsertLocalMinima(locMin);
                m_edges.Add(edges);
                return(true);
            }

            m_edges.Add(edges);
            bool  leftBoundIsForward;
            TEdge EMin = null;

            //workaround to avoid an endless loop in the while loop below when
            //open paths have matching start and end points ...
            if (E.Prev.Bot == E.Prev.Top)
            {
                E = E.Next;
            }

            for (;;)
            {
                E = FindNextLocMin(E);
                if (E == EMin)
                {
                    break;
                }
                else if (EMin == null)
                {
                    EMin = E;
                }

                //E and E.Prev now share a local minima (left aligned if horizontal).
                //Compare their slopes to find which starts which bound ...
                LocalMinima locMin = new LocalMinima();
                locMin.Next = null;
                locMin.Y    = E.Bot.Y;
                if (E.Dx < E.Prev.Dx)
                {
                    locMin.LeftBound   = E.Prev;
                    locMin.RightBound  = E;
                    leftBoundIsForward = false; //Q.nextInLML = Q.prev
                }
                else
                {
                    locMin.LeftBound   = E;
                    locMin.RightBound  = E.Prev;
                    leftBoundIsForward = true; //Q.nextInLML = Q.next
                }
                locMin.LeftBound.Side  = EdgeSide.esLeft;
                locMin.RightBound.Side = EdgeSide.esRight;

                if (!Closed)
                {
                    locMin.LeftBound.WindDelta = 0;
                }
                else if (locMin.LeftBound.Next == locMin.RightBound)
                {
                    locMin.LeftBound.WindDelta = -1;
                }
                else
                {
                    locMin.LeftBound.WindDelta = 1;
                }
                locMin.RightBound.WindDelta = -locMin.LeftBound.WindDelta;

                E = ProcessBound(locMin.LeftBound, leftBoundIsForward);
                if (E.OutIdx == Skip)
                {
                    E = ProcessBound(E, leftBoundIsForward);
                }

                TEdge E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward);
                if (E2.OutIdx == Skip)
                {
                    E2 = ProcessBound(E2, !leftBoundIsForward);
                }

                if (locMin.LeftBound.OutIdx == Skip)
                {
                    locMin.LeftBound = null;
                }
                else if (locMin.RightBound.OutIdx == Skip)
                {
                    locMin.RightBound = null;
                }
                InsertLocalMinima(locMin);
                if (!leftBoundIsForward)
                {
                    E = E2;
                }
            }
            return(true);
        }
 //------------------------------------------------------------------------------
 private void InsertLocalMinima(LocalMinima newLm)
 {
     if( m_MinimaList == null )
       {
     m_MinimaList = newLm;
       }
       else if( newLm.Y >= m_MinimaList.Y )
       {
     newLm.next = m_MinimaList;
     m_MinimaList = newLm;
       } else
       {
     LocalMinima tmpLm = m_MinimaList;
     while( tmpLm.next != null  && ( newLm.Y < tmpLm.next.Y ) )
       tmpLm = tmpLm.next;
     newLm.next = tmpLm.next;
     tmpLm.next = newLm;
       }
 }
 /// <summary>
 /// Reset all fields to default values in preparation for object recycling
 /// </summary>
 public void PrepareForRecycle()
 {
     Y         = new cInt();
     LeftBound = RightBound = null;
     Next      = null;
 }