예제 #1
0
        /// <summary>
        /// True if it crosses the line. Provides the intersection points.
        /// </summary>
        /// <param name="Line">The other line.</param>
        /// <param name="IntersectionPts">Output. The intersection points.</param>
        public bool Crosses(C2DLineBase Line, List <C2DPoint> IntersectionPts)
        {
            var LineRect = new C2DRect();

            Line.GetBoundingRect(LineRect);

            if (!BoundingRect.Overlaps(LineRect))
            {
                return(false);
            }

            Debug.Assert(Lines.Count == LineRects.Count);

            if (Lines.Count != LineRects.Count)
            {
                return(false);
            }

            var IntersectionTemp = new C2DPointSet();

            var bResult = false;

            for (var i = 0; i < this.Lines.Count; i++)
            {
                if (LineRects[i].Overlaps(LineRect) &&
                    Lines[i].Crosses(Line, IntersectionTemp as List <C2DPoint>))
                {
                    bResult = true;
                }
            }

            IntersectionPts.InsertRange(0, IntersectionTemp);

            return(bResult);
        }
예제 #2
0
        /// <summary>
        /// True if the point is in the shape.
        /// </summary>
        /// <param name="pt">The point to test set.</param>
        public bool Contains(C2DPoint pt)
        {
            if (!BoundingRect.Contains(pt))
            {
                return(false);
            }

            var IntersectedPts = new C2DPointSet();

            var Ray = new C2DLine(pt, new C2DVector(BoundingRect.Width(), 0.000001));     // Make sure to leave

            if (!this.Crosses(Ray, IntersectedPts))
            {
                return(false);
            }
            else
            {
                IntersectedPts.SortByDistance(Ray.point);
                if (IntersectedPts[0].PointEqualTo(pt))
                {
                    // For integers, the pt can start On a line, meaning it's INSIDE, but the ray could cross again
                    // so just return true. Because the equality test is really a test for proximity, this leads to the
                    // possibility that a point could lie just outside the shape but be considered to be inside. This would
                    // only be a problem with very small shapes that are a very long way from the origin. E.g. a 1m2 object
                    // 1 million metres from the origin and a point 0.1mm away from the edge would give rise to a relative
                    // difference of 0.0001 / 1000000 = 0.000000001 which would just be consider to be inside.
                    return(true);
                }
                else
                {
                    // Return true if the ray
                    return((IntersectedPts.Count & (int)1) > 0);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Returns the routes (multiple lines or part polygons) either inside or
        /// outside the polygons provided. These are based on the intersections
        /// of the 2 polygons e.g. the routes / part polygons of one inside or
        /// outside the other.
        /// </summary>
        /// <param name="Poly1">The first polygon.</param>
        /// <param name="bP1RoutesInside">True if routes inside the second polygon are
        /// required for the first polygon.</param>
        /// <param name="Poly2">The second polygon.</param>
        /// <param name="bP2RoutesInside">True if routes inside the first polygon are
        /// required for the second polygon.</param>
        /// <param name="Routes1">Output. Set of lines for the first polygon.</param>
        /// <param name="Routes2">Output. Set of lines for the second polygon.</param>
        public static void GetRoutes(C2DPolyBase Poly1, bool bP1RoutesInside,
                                     C2DPolyBase Poly2, bool bP2RoutesInside,
                                     C2DLineBaseSetSet Routes1, C2DLineBaseSetSet Routes2)
        {
            // Set up a collection of intersected points, and corresponding indexes.
            var IntPoints = new C2DPointSet();
            var Indexes1  = new List <int>();
            var Indexes2  = new List <int>();

            // Use the line collections in each shape to find the intersections between them.
            Poly1.Lines.GetIntersections(Poly2.Lines, IntPoints,
                                         Indexes1, Indexes2,
                                         Poly1.BoundingRect, Poly2.BoundingRect);
            // Make a copy of the point set because this will be sorted by line index in the
            // Get routes function later. We need an unsorted set for each polygon.
            var IntPointsCopy = new C2DPointSet();

            IntPointsCopy.MakeCopy(IntPoints);

            // Find out whether the first poly starts inside the second.
            bool bP1StartInside = Poly2.Contains(Poly1.Lines[0].GetPointFrom());
            // Find out if poly 2 starts inside poly 1.
            bool bP2StartInside = Poly1.Contains(Poly2.Lines[0].GetPointFrom());

            if (IntPoints.Count == 0 && !bP1StartInside && !bP2StartInside)
            {
                return; // No interaction between the 2.
            }
            // Get the routes of poly 1 inside / outside the other, passing the unsorted
            // intersection points and polygon1 intersection indexes.
            Poly1.GetRoutes(IntPoints, Indexes1, Routes1, bP1StartInside, bP1RoutesInside);
            // Do the same for poly 2 but pass it the unsorted copy of the intersection points
            // So that they correspond to the indexes.
            Poly2.GetRoutes(IntPointsCopy, Indexes2, Routes2, bP2StartInside, bP2RoutesInside);
        }
예제 #4
0
        /// <summary>
        /// Returns the lines that make up this defined by the points which are assumed
        /// to be on this line. i.e. splits the line up.
        /// </summary>
        /// <param name="PtsOnLine">The point set defining how this is to be broken up.</param>
        /// <param name="LineSet">Output. The sub lines.</param>
        public override void GetSubLines(List <C2DPoint> PtsOnLine, List <C2DLineBase> LineSet)
        {
            // if there are no points on the line to split on then add a copy of this and return.
            var usPointsCount = PtsOnLine.Count;

            if (usPointsCount == 0)
            {
                LineSet.Add(new C2DLine(this));
            }
            else
            {
                var TempPts = new C2DPointSet();
                TempPts.MakeCopy(PtsOnLine);

                if (usPointsCount > 1)         // They need sorting
                {
                    // Now sort the points according to the order in which they will be encountered
                    TempPts.SortByDistance(point);
                }

                // Add the line from the start of this to the first.
                LineSet.Add(new C2DLine(point, TempPts[0]));

                // Add all the sub lines.
                for (var i = 1; i < usPointsCount; i++)
                {
                    LineSet.Add(new C2DLine(TempPts[i - 1], TempPts[i]));
                }

                // Add the line from the last point on this to the end of this.
                LineSet.Add(new C2DLine(TempPts[TempPts.Count - 1], GetPointTo()));
            }

            Debug.Assert(LineSet.Count == (PtsOnLine.Count + 1));
        }
예제 #5
0
        /// <summary>
        /// True if this crosses the ray, returns the intersection points.
        /// </summary>
        /// <param name="Ray">Ray to test for.</param>
        /// <param name="IntersectionPts">Intersection points.</param>
        public bool CrossesRay(C2DLine Ray, C2DPointSet IntersectionPts)
        {
            var IntPts = new C2DPointSet();

            _Rim.CrossesRay(Ray, IntPts);

            IntersectionPts.ExtractAllOf(IntPts);

            for (var i = 0; i < _Holes.Count; i++)
            {
                if (_Holes[i].CrossesRay(Ray, IntPts))
                {
                    double dDist   = Ray.point.Distance(IntPts[0]);
                    var    nInsert = 0;

                    while (nInsert < IntersectionPts.Count &&
                           Ray.point.Distance(IntersectionPts[nInsert]) < dDist)
                    {
                        nInsert++;
                    }

                    IntersectionPts.InsertRange(nInsert, IntPts);
                }
            }

            return(IntersectionPts.Count > 0);
        }
예제 #6
0
 /// <summary>
 /// Extracts all of the other set.
 /// </summary>
 /// <param name="S2">The other set.</param>
 public void ExtractAllOf(C2DPointSet S2)
 {
     for (int i = 0; i < S2.Count; i++)
     {
         Add(S2[i]);
     }
     S2.Clear();
 }
예제 #7
0
        /// <summary>
        /// Removes the convex hull from the point set given.
        /// Will affect the input set.
        /// </summary>
        /// <param name="Other">The other set.</param>
        public void ExtractConvexHull(C2DPointSet Other)
        {
            Clear();

            if (Other.Count < 4)
            {
                this.ExtractAllOf(Other);
                return;
            }

            C2DPoint ptLeftMost = Other[0];
            int      nLeftMost  = 0;

            // Find left most
            for (int i = 1; i < Other.Count; i++)
            {
                C2DPoint pt = Other[i];
                if (pt.x < ptLeftMost.x)
                {
                    ptLeftMost = pt;
                    nLeftMost  = i;
                }
            }

            Add(Other.ExtractAt(nLeftMost));

            Other.SortByAngleFromNorth(this[0]);

            // Always add the left most and the first of the rest.
            Add(Other.ExtractAt(0));

            // Add others if needed.
            int nIndx = 0;

            C2DPointSet Unused = new C2DPointSet();

            while (nIndx < Other.Count)
            {
                int     nLast    = Count - 1;
                C2DLine LastLine = new C2DLine(this[nLast - 1], this[nLast]);

                C2DVector Test = new C2DVector(this[nLast], Other[nIndx]);

                double dAng = Test.AngleFromNorth();

                if (dAng < LastLine.vector.AngleFromNorth())
                {
                    Unused.Add(ExtractAt(nLast));
                }
                else
                {
                    Add(Other.ExtractAt(nIndx));
                }
            }

            Other.ExtractAllOf(Unused);
        }
예제 #8
0
        /// <summary>
        /// True if it crosses the ray. Provides the intersection points.
        /// </summary>
        /// <param name="Ray">The infinite line.</param>
        /// <param name="IntersectionPts">Output. The intersection points.</param>
        public bool CrossesRay(C2DLine Ray, C2DPointSet IntersectionPts)
        {
            double dDist = Ray.point.Distance(BoundingRect.GetCentre());

            var LineTemp = new C2DLine(Ray);

            LineTemp.vector.SetLength(dDist + BoundingRect.Width() + BoundingRect.Height());

            return(Crosses(LineTemp, IntersectionPts));
        }
예제 #9
0
        /// <summary>
        /// True if it entirely contains the line.
        /// </summary>
        /// <param name="Line">The line to test.</param>
        public bool Contains(C2DLineBase Line)
        {
            if (!Contains(Line.GetPointFrom()))
            {
                return(false);
            }

            var Pts = new C2DPointSet();

            return(!Crosses(Line, Pts));
        }
예제 #10
0
파일: C2DArc.cs 프로젝트: kasznare/DIP1
        /// <summary>
        /// Returns the lines that go to make this up based on the set of points
        /// provided which are assumed to be on the line.
        /// </summary>
        /// <param name="PtsOnLine">The points defining how the line is to be split.</param>
        /// <param name="LineSet">The line set to recieve the result.</param>
        public override void GetSubLines(List <C2DPoint> PtsOnLine, List <C2DLineBase> LineSet)
        {
            // if there are no points on the line to split on then add a copy of this and return.
            int usPointsCount = PtsOnLine.Count;

            if (usPointsCount == 0)
            {
                LineSet.Add(new C2DArc(this));
                return;
            }
            else
            {
                // Make a copy of the points for sorting.
                C2DPointSet TempPts = new C2DPointSet();
                TempPts.MakeCopy(PtsOnLine);

                if (usPointsCount > 1)         // They need sorting
                {
                    // Make a line from the mid point of my line to the start
                    C2DLine CenToStart = new C2DLine(Line.GetMidPoint(), Line.point);
                    // Now sort the points according to the order in which they will be encountered
                    if (ArcOnRight)
                    {
                        TempPts.SortByAngleToLeft(CenToStart);
                    }
                    else
                    {
                        TempPts.SortByAngleToRight(CenToStart);
                    }
                }

                C2DPoint ptCentre = new C2DPoint(GetCircleCentre());

                // Add the line from the start of this to the first.
                C2DLine NewLine = new C2DLine(Line.point, TempPts[0]);
                LineSet.Add(new C2DArc(NewLine, Radius,
                                       NewLine.IsOnRight(ptCentre), ArcOnRight));

                // Add all the sub lines.
                for (int i = 1; i < usPointsCount; i++)
                {
                    NewLine.Set(TempPts[i - 1], TempPts[i]);
                    LineSet.Add(new C2DArc(NewLine, Radius,
                                           NewLine.IsOnRight(ptCentre), ArcOnRight));
                }
                // Add the line from the last point on this to the end of this.
                NewLine.Set(TempPts[TempPts.Count - 1], Line.GetPointTo());
                LineSet.Add(new C2DArc(NewLine, Radius,
                                       NewLine.IsOnRight(ptCentre), ArcOnRight));
            }
        }
예제 #11
0
        /// <summary>
        /// True if this crosses the line.
        /// </summary>
        /// <param name="Line">Line to test for.</param>
        /// <param name="IntersectionPts">Point set to recieve the intersections.</param>
        public bool Crosses(C2DLineBase Line, C2DPointSet IntersectionPts)
        {
            var IntPts = new C2DPointSet();

            _Rim.Crosses(Line, IntPts);

            for (var i = 0; i < _Holes.Count; i++)
            {
                _Holes[i].Crosses(Line, IntPts);
            }
            var bResult = (IntPts.Count != 0);

            IntersectionPts.ExtractAllOf(IntPts);

            return(bResult);
        }
        /// <summary>
        /// Optimises the position of the points
        /// </summary>
        public void Optimize()
        {
            if (Count < 4)
            {
                return;
            }

            // Take out the start.
            var pStart = First.Value;

            this.RemoveFirst();
            //  m_Points->pop_front();

            // Take out the end.
            var pEnd = Last.Value;

            this.RemoveLast();
            //    m_Points->pop_back();

            // Take all the rest out.
            var Points = new C2DPointSet();

            this.ExtractPoints(Points);

            // Put the ends back in.
            this.AddFirst(pStart);
            this.AddLast(pEnd);
            //    m_Points->push_front(pStart);
            //    m_Points->push_back(pEnd);

            // Sort the rest by approx distance from the line in reverse order so we can get them off the end.
            Points.SortByDistance(pStart.GetMidPoint(pEnd));
            Points.Reverse();

            // Add them all in the most sensible place (not gauranteed).
            while (Points.Count > 0)
            {
                this.InsertOptimally(Points[Points.Count - 1]);
                Points.RemoveAt(Points.Count - 1);
            }
        }
예제 #13
0
        /// <summary>
        /// Returns the routes (collection of lines and sublines) either inside or outside another
        /// Given the intersection points.
        /// </summary>
        /// <param name="IntPts">The intersection points of this with the other polygon.</param>
        /// <param name="IntIndexes">The corresponding line indexes.</param>
        /// <param name="Routes">Output. The routes to get the result.</param>
        /// <param name="bStartInside">True if this polygon starts inside the other.</param>
        /// <param name="bRoutesInside">True if we require routes of this polygon inside the other.</param>
        public void GetRoutes(C2DPointSet IntPts, List <int> IntIndexes,
                              C2DLineBaseSetSet Routes, bool bStartInside, bool bRoutesInside)
        {
            // Make sure the intersection indexes and points are the same size.
            if (IntIndexes.Count != IntPts.Count)
            {
                Debug.Assert(false);
                return;
            }
            // Set up a new collection of routes.
            var NewRoutes = new C2DLineBaseSetSet();

            // If the polygon has no points then return.
            if (_Lines.Count < 1)
            {
                return;
            }
            // Sort the intersections by index so we can go through them in order.
            IntPts.SortByIndex(IntIndexes);

            // Set the inside / outside flag to the same as the start inside / outside flag.
            var bInside = bStartInside;

            // If we are inside and want route inside or outside and want routes outside then add a new route.
            if (bInside == bRoutesInside)
            {
                NewRoutes.Add(new C2DLineBaseSet());
            }

            // The current index of the intersects.
            var usCurrentIntIndex = 0;

            // cycle through the lines on the polygon.
            for (var i = 0; i < Lines.Count; i++)
            {
                // Set up a list of intersection points on this line only.
                var IntsOnLine = new C2DPointSet();
                // Cycle through all intersections on this line (leaving the usCurrentIntIndex at the next intersected line).
                while (usCurrentIntIndex < IntIndexes.Count && IntIndexes[usCurrentIntIndex] == i)
                {
                    // Add a copy of the points on this line that are intersections
                    IntsOnLine.AddCopy(IntPts[usCurrentIntIndex]);
                    usCurrentIntIndex++;
                }

                // If the line in question intersects the other poly then we have left / entered.
                if (IntsOnLine.Count > 0)
                {
                    var SubLines = new C2DLineBaseSet();
                    Lines[i].GetSubLines(IntsOnLine, SubLines);

                    while (SubLines.Count > 1)
                    {
                        if (bInside == bRoutesInside)
                        {
                            // We have 1. Left and want route in. OR 2. Entered and want routes out.
                            NewRoutes[NewRoutes.Count - 1].Add(SubLines.ExtractAt(0));
                            bInside = true ^ bRoutesInside;
                        }
                        else
                        {
                            NewRoutes.Add(new C2DLineBaseSet());
                            bInside = false ^ bRoutesInside;
                            SubLines.RemoveAt(0);
                        }
                    }
                    if (bInside == bRoutesInside)
                    {
                        NewRoutes[NewRoutes.Count - 1].Add(SubLines.ExtractAt(SubLines.Count - 1));
                    }
                    else
                    {
                        SubLines.RemoveAt(SubLines.Count - 1);
                    }
                }
                // Otherwise, if we are e.g. inside and want routes in the keep adding the end poitn of the line.
                else if (bInside == bRoutesInside)
                {
                    NewRoutes[NewRoutes.Count - 1].AddCopy(Lines[i]);
                }
            }
            // Put all the new routes into the provided collection.
            Routes.ExtractAllOf(NewRoutes);
        }
예제 #14
0
        /// <summary>
        /// True if part of this line is above the other. Returns the point
        /// on this and on the other.
        /// </summary>
        /// <param name="Other"></param>
        /// <param name="dVerticalDistance"></param>
        /// <param name="ptOnThis"></param>
        /// <param name="ptOnOther"></param>
        /// <returns></returns>
        public bool OverlapsAbove(C2DLine Other, ref double dVerticalDistance,
                                  C2DPoint ptOnThis, C2DPoint ptOnOther)
        {
            // Get the 2 points for both lines
            var OtherTo = new C2DPoint(Other.point.x + Other.vector.i, Other.point.y + Other.vector.j);
            var ThisTo  = new C2DPoint(point.x + vector.i, point.y + vector.j);
            // Make an interval for both in the x plane
            var iThis = new CInterval(point.x, point.x);

            iThis.ExpandToInclude(ThisTo.x);

            var iOther = new CInterval(Other.point.x, Other.point.x);

            iOther.ExpandToInclude(OtherTo.x);
            // This is an interval for the overlap between the 2
            var iOverlap = new CInterval();

            // If there is an overlap...
            if (iThis.Overlaps(iOther, iOverlap))
            {
                double dThisYMin;
                double dThisYMax;

                double dOtherYMin;
                double dOtherYMax;
                // If the line is vertical then y at the x min / max can be set to the ends of the line.
                if (vector.i == 0)
                {
                    dThisYMin = point.y;
                    dThisYMax = ThisTo.y;
                }
                else            // otherwise, caluclate the y values at the interval ends
                {
                    dThisYMin = GetY(iOverlap.dMin);
                    dThisYMax = GetY(iOverlap.dMax);
                }
                // Now do the same for the other line
                if (Other.vector.i == 0)
                {
                    dOtherYMin = Other.point.y;
                    dOtherYMax = OtherTo.y;
                }
                else
                {
                    dOtherYMin = Other.GetY(iOverlap.dMin);
                    dOtherYMax = Other.GetY(iOverlap.dMax);
                }

                // Now find the distance between the 2 at the ends
                var dDistMin = dThisYMin - dOtherYMin;
                var dDistMax = dThisYMax - dOtherYMax;
                // If they are both > 0 then no intersection
                if ((dDistMin > 0) && (dDistMax > 0))
                {
                    dDistMin = Math.Abs(dDistMin);
                    dDistMax = Math.Abs(dDistMax);
                    // find which one is smallest
                    if (dDistMin > dDistMax)
                    {
                        dVerticalDistance = dDistMax;                   // distance at the max is smallest
                        ptOnThis.x        = iOverlap.dMax;
                        ptOnThis.y        = dThisYMax;
                        ptOnOther.x       = iOverlap.dMax;
                        ptOnOther.y       = dOtherYMax;
                    }
                    else
                    {
                        dVerticalDistance = dDistMin;                  // distance at the min is smallest
                        ptOnThis.x        = iOverlap.dMin;
                        ptOnThis.y        = dThisYMin;
                        ptOnOther.x       = iOverlap.dMin;
                        ptOnOther.y       = dOtherYMin;
                    }

                    return(true);
                }
                else if ((dDistMin < 0) && (dDistMax < 0))          // This is below.
                {
                    return(false);
                }
                else
                {
                    // find the intersection.
                    dVerticalDistance = 0;
                    var pts = new C2DPointSet();
                    if (this.Crosses(Other, pts))
                    {
                        ptOnThis  = pts[0];
                        ptOnOther = ptOnThis;
                    }
                    else
                    {
                        Debug.Assert(false);
                    }
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #15
0
        /// <summary>
        /// Returns the routes (multiple lines or part polygons) either inside or
        /// outside the polygons provided. These are based on the intersections
        /// of the 2 polygons e.g. the routes / part polygons of one inside or
        /// outside the other.
        /// </summary>
        /// <param name="Poly1">The first polygon.</param>
        /// <param name="bP1RoutesInside">True if routes inside the second polygon are
        /// required for the first polygon.</param>
        /// <param name="Poly2">The second polygon.</param>
        /// <param name="bP2RoutesInside">True if routes inside the first polygon are
        /// required for the second polygon.</param>
        /// <param name="Routes1">Output. Set of lines for the first polygon.</param>
        /// <param name="Routes2">Output. Set of lines for the second polygon.</param>
        /// <param name="CompleteHoles1">Output. Complete holes for the first polygon.</param>
        /// <param name="CompleteHoles2">Output. Complete holes for the second polygon.</param>
        /// <param name="grid">Contains the degenerate handling settings.</param>
        public static void GetRoutes(C2DHoledPolyBase Poly1, bool bP1RoutesInside,
                                     C2DHoledPolyBase Poly2, bool bP2RoutesInside,
                                     C2DLineBaseSetSet Routes1, C2DLineBaseSetSet Routes2,
                                     List <C2DPolyBase> CompleteHoles1, List <C2DPolyBase> CompleteHoles2,
                                     CGrid grid)
        {
            if (Poly1.Rim.Lines.Count == 0 || Poly2.Rim.Lines.Count == 0)
            {
                Debug.Assert(false, "Polygon with no lines");
                return;
            }

            var IntPointsTemp = new C2DPointSet();
            var IntPointsRim1 = new C2DPointSet();
            var IntPointsRim2 = new C2DPointSet();
            var IndexesRim1   = new List <int>();
            var IndexesRim2   = new List <int>();


            var IntPoints1AllHoles = new List <C2DPointSet>();
            var IntPoints2AllHoles = new List <C2DPointSet>();
            var Indexes1AllHoles   = new List <List <int> >();
            var Indexes2AllHoles   = new List <List <int> >();
            //    std::vector<C2DPointSet* > IntPoints1AllHoles, IntPoints2AllHoles;
            //   std::vector<CIndexSet*> Indexes1AllHoles, Indexes2AllHoles;

            var usP1Holes = Poly1.HoleCount;
            var usP2Holes = Poly2.HoleCount;

            // *** Rim Rim Intersections
            Poly1.Rim.Lines.GetIntersections(Poly2.Rim.Lines,
                                             IntPointsTemp, IndexesRim1, IndexesRim2,
                                             Poly1.Rim.BoundingRect, Poly2.Rim.BoundingRect);

            IntPointsRim1.AddCopy(IntPointsTemp);
            IntPointsRim2.ExtractAllOf(IntPointsTemp);

            // *** Rim Hole Intersections
            for (var i = 0; i < usP2Holes; i++)
            {
                Debug.Assert(IntPointsTemp.Count == 0);

                IntPoints2AllHoles.Add(new C2DPointSet());
                Indexes2AllHoles.Add(new List <int>());

                if (Poly1.Rim.BoundingRect.Overlaps(Poly2.GetHole(i).BoundingRect))
                {
                    Poly1.Rim.Lines.GetIntersections(Poly2.GetHole(i).Lines,
                                                     IntPointsTemp, IndexesRim1, Indexes2AllHoles[i],
                                                     Poly1.Rim.BoundingRect, Poly2.GetHole(i).BoundingRect);

                    IntPointsRim1.AddCopy(IntPointsTemp);
                    IntPoints2AllHoles[i].ExtractAllOf(IntPointsTemp);
                }
            }
            // *** Rim Hole Intersections
            for (var j = 0; j < usP1Holes; j++)
            {
                Debug.Assert(IntPointsTemp.Count == 0);

                IntPoints1AllHoles.Add(new C2DPointSet());
                Indexes1AllHoles.Add(new List <int>());

                if (Poly2.Rim.BoundingRect.Overlaps(Poly1.GetHole(j).BoundingRect))
                {
                    Poly2.Rim.Lines.GetIntersections(Poly1.GetHole(j).Lines,
                                                     IntPointsTemp, IndexesRim2, Indexes1AllHoles[j],
                                                     Poly2.Rim.BoundingRect, Poly1.GetHole(j).BoundingRect);

                    IntPointsRim2.AddCopy(IntPointsTemp);
                    IntPoints1AllHoles[j].ExtractAllOf(IntPointsTemp);
                }
            }

            // *** Quick Escape
            bool bRim1StartInPoly2 = Poly2.Contains(Poly1.Rim.Lines[0].GetPointFrom());
            bool bRim2StartInPoly1 = Poly1.Contains(Poly2.Rim.Lines[0].GetPointFrom());

            if (IntPointsRim1.Count != 0 || IntPointsRim2.Count != 0 ||
                bRim1StartInPoly2 || bRim2StartInPoly1)
            // pos no interaction
            {
                // *** Rim Routes
                Poly1.Rim.GetRoutes(IntPointsRim1, IndexesRim1, Routes1,
                                    bRim1StartInPoly2, bP1RoutesInside);
                Poly2.Rim.GetRoutes(IntPointsRim2, IndexesRim2, Routes2,
                                    bRim2StartInPoly1, bP2RoutesInside);

                if (IntPointsRim1.Count % 2 != 0)               // Must be even
                {
                    grid.LogDegenerateError();
                    //  Debug.Assert(false);
                }

                if (IntPointsRim2.Count % 2 != 0)               // Must be even
                {
                    grid.LogDegenerateError();
                    //   Debug.Assert(false);
                }

                // *** Hole Hole Intersections
                for (var h = 0; h < usP1Holes; h++)
                {
                    for (var k = 0; k < usP2Holes; k++)
                    {
                        Debug.Assert(IntPointsTemp.Count == 0);
                        var pHole1 = Poly1.GetHole(h);
                        var pHole2 = Poly2.GetHole(k);

                        if (pHole1.BoundingRect.Overlaps(pHole2.BoundingRect))
                        {
                            pHole1.Lines.GetIntersections(pHole2.Lines,
                                                          IntPointsTemp, Indexes1AllHoles[h], Indexes2AllHoles[k],
                                                          pHole1.BoundingRect, pHole2.BoundingRect);

                            IntPoints1AllHoles[h].AddCopy(IntPointsTemp);
                            IntPoints2AllHoles[k].ExtractAllOf(IntPointsTemp);
                        }
                    }
                }


                // *** Hole Routes
                for (var a = 0; a < usP1Holes; a++)
                {
                    var pHole = Poly1.GetHole(a);

                    if (IntPoints1AllHoles[a].Count % 2 != 0)                   // Must be even
                    {
                        grid.LogDegenerateError();
                        //   Debug.Assert(false);
                    }

                    if (pHole.Lines.Count != 0)
                    {
                        bool bHole1StartInside = Poly2.Contains(pHole.Lines[0].GetPointFrom());
                        if (IntPoints1AllHoles[a].Count == 0)
                        {
                            if (bHole1StartInside == bP1RoutesInside)
                            {
                                CompleteHoles1.Add(new C2DPolyBase(pHole));
                            }
                        }
                        else
                        {
                            pHole.GetRoutes(IntPoints1AllHoles[a], Indexes1AllHoles[a], Routes1,
                                            bHole1StartInside, bP1RoutesInside);
                        }
                    }
                }
                // *** Hole Routes
                for (var b = 0; b < usP2Holes; b++)
                {
                    var pHole = Poly2.GetHole(b);

                    if (IntPoints2AllHoles[b].Count % 2 != 0)                   // Must be even
                    {
                        grid.LogDegenerateError();
                        //    Debug.Assert(false);
                    }

                    if (pHole.Lines.Count != 0)
                    {
                        bool bHole2StartInside = Poly1.Contains(pHole.Lines[0].GetPointFrom());
                        if (IntPoints2AllHoles[b].Count == 0)
                        {
                            if (bHole2StartInside == bP2RoutesInside)
                            {
                                CompleteHoles2.Add(new C2DPolyBase(pHole));
                            }
                        }
                        else
                        {
                            pHole.GetRoutes(IntPoints2AllHoles[b], Indexes2AllHoles[b], Routes2,
                                            bHole2StartInside, bP2RoutesInside);
                        }
                    }
                }
            }


            //for (unsigned int i = 0 ; i < IntPoints1AllHoles.size(); i++)
            //    delete IntPoints1AllHoles[i];
            //for (unsigned int i = 0 ; i < IntPoints2AllHoles.size(); i++)
            //    delete IntPoints2AllHoles[i];
            //for (unsigned int i = 0 ; i < Indexes1AllHoles.size(); i++)
            //    delete Indexes1AllHoles[i];
            //for (unsigned int i = 0 ; i < Indexes2AllHoles.size(); i++)
            //    delete Indexes2AllHoles[i];
        }