/// <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); }
/// <summary> /// True if this overlaps the other. /// </summary> /// <param name="Other">The other polygon.</param> public bool Overlaps(C2DPolyBase Other) { if (Lines.Count == 0 || Other.Lines.Count == 0) { return(false); } if (Other.Contains(Lines[0].GetPointTo())) { return(true); } if (Crosses(Other)) { return(true); } return(this.Contains(Other.Lines[0].GetPointTo())); }
/// <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. C2DPointSet IntPoints = new C2DPointSet(); List<int> Indexes1 = new List<int>(); List<int> 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. C2DPointSet 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); }
/// <summary> /// True if this overlaps the other. /// </summary> /// <param name="Other">The other polygon.</param> public bool Overlaps(C2DPolyBase Other) { if (Lines.Count == 0 || Other.Lines.Count == 0) return false; if (Other.Contains(Lines[0].GetPointTo())) return true; if (Crosses(Other)) return true; return (this.Contains(Other.Lines[0].GetPointTo())); }
/// <summary> /// Distance of the poly from the shape. /// </summary> /// <param name="Other">The other polygon test.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> /// <param name="ptOnOther">The closest point on the other.</param> public double Distance(C2DPolyBase Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { if (Lines.Count == 0) return 0; if (Other.Lines.Count == 0) return 0; if (Other.LineRects.Count != Other.Lines.Count) return 0; if (Lines.Count != LineRects.Count) return 0; // First we find the closest line rect to the other's bounding rectangle. int usThisClosestLineGuess = 0; C2DRect OtherBoundingRect = Other.BoundingRect; double dClosestDist = LineRects[0].Distance(OtherBoundingRect); for (int i = 1; i < LineRects.Count; i++) { double dDist = LineRects[i].Distance(OtherBoundingRect); if (dDist < dClosestDist) { dClosestDist = dDist; usThisClosestLineGuess = i; } } // Now cycle through all the other poly's line rects to find the closest to the // guessed at closest line on this. int usOtherClosestLineGuess = 0; dClosestDist = Other.LineRects[0].Distance(LineRects[usThisClosestLineGuess]); for (int j = 1; j < Other.LineRects.Count; j++) { double dDist = Other.LineRects[j].Distance(LineRects[usThisClosestLineGuess]); if (dDist < dClosestDist) { dClosestDist = dDist; usOtherClosestLineGuess = j; } } // Now we have a guess at the 2 closest lines. double dMinDistGuess = Lines[usThisClosestLineGuess].Distance( Other.Lines[usOtherClosestLineGuess], ptOnThis, ptOnOther); // If its 0 then return 0. if (dMinDistGuess == 0) return 0; C2DPoint ptOnThisTemp = new C2DPoint(); C2DPoint ptOnOtherTemp = new C2DPoint(); // Now go through all of our line rects and only check further if they are closer // to the other's bounding rect than the min guess. for (int i = 0; i < Lines.Count; i++) { if (LineRects[i].Distance( OtherBoundingRect ) < dMinDistGuess) { for ( int j = 0 ; j < Other.Lines.Count ; j++) { double dDist = Lines[i].Distance(Other.Lines[j], ptOnThisTemp, ptOnOtherTemp); if (dDist < dMinDistGuess) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(ptOnOtherTemp); if (dDist == 0) return 0; dMinDistGuess = dDist; } } } } // if we are here, there is no intersection but the other could be inside this or vice-versa if ( BoundingRect.Contains(Other.BoundingRect) && Contains(ptOnOtherTemp) ) { dMinDistGuess *= -1.0; } else if ( Other.BoundingRect.Contains(BoundingRect) && Other.Contains( ptOnThisTemp )) { dMinDistGuess *= -1.0; } return dMinDistGuess; }
/// <summary> /// Distance of the poly from the shape. /// </summary> /// <param name="Other">The other polygon test.</param> /// <param name="ptOnThis">Output. The closest point on this.</param> /// <param name="ptOnOther">The closest point on the other.</param> public double Distance(C2DPolyBase Other, C2DPoint ptOnThis, C2DPoint ptOnOther) { if (Lines.Count == 0) { return(0); } if (Other.Lines.Count == 0) { return(0); } if (Other.LineRects.Count != Other.Lines.Count) { return(0); } if (Lines.Count != LineRects.Count) { return(0); } // First we find the closest line rect to the other's bounding rectangle. var usThisClosestLineGuess = 0; var OtherBoundingRect = Other.BoundingRect; double dClosestDist = LineRects[0].Distance(OtherBoundingRect); for (var i = 1; i < LineRects.Count; i++) { double dDist = LineRects[i].Distance(OtherBoundingRect); if (dDist < dClosestDist) { dClosestDist = dDist; usThisClosestLineGuess = i; } } // Now cycle through all the other poly's line rects to find the closest to the // guessed at closest line on this. var usOtherClosestLineGuess = 0; dClosestDist = Other.LineRects[0].Distance(LineRects[usThisClosestLineGuess]); for (var j = 1; j < Other.LineRects.Count; j++) { double dDist = Other.LineRects[j].Distance(LineRects[usThisClosestLineGuess]); if (dDist < dClosestDist) { dClosestDist = dDist; usOtherClosestLineGuess = j; } } // Now we have a guess at the 2 closest lines. double dMinDistGuess = Lines[usThisClosestLineGuess].Distance( Other.Lines[usOtherClosestLineGuess], ptOnThis, ptOnOther); // If its 0 then return 0. if (dMinDistGuess == 0) { return(0); } var ptOnThisTemp = new C2DPoint(); var ptOnOtherTemp = new C2DPoint(); // Now go through all of our line rects and only check further if they are closer // to the other's bounding rect than the min guess. for (var i = 0; i < Lines.Count; i++) { if (LineRects[i].Distance(OtherBoundingRect) < dMinDistGuess) { for (var j = 0; j < Other.Lines.Count; j++) { double dDist = Lines[i].Distance(Other.Lines[j], ptOnThisTemp, ptOnOtherTemp); if (dDist < dMinDistGuess) { ptOnThis.Set(ptOnThisTemp); ptOnOther.Set(ptOnOtherTemp); if (dDist == 0) { return(0); } dMinDistGuess = dDist; } } } } // if we are here, there is no intersection but the other could be inside this or vice-versa if (BoundingRect.Contains(Other.BoundingRect) && Contains(ptOnOtherTemp)) { dMinDistGuess *= -1.0; } else if (Other.BoundingRect.Contains(BoundingRect) && Other.Contains(ptOnThisTemp)) { dMinDistGuess *= -1.0; } return(dMinDistGuess); }
/// <summary> /// Function to convert polygons to complex polygons. Assigning holes to those that are contained. /// The set of holed polygons will be filled from the set of simple polygons. /// </summary> /// <param name="HoledPolys">Holed polygon set.</param> /// <param name="Polygons">Simple polygon set.</param> public static void PolygonsToHoledPolygons(List <C2DHoledPolyBase> HoledPolys, List <C2DPolyBase> Polygons) { List <C2DPolyBase> Unmatched = new List <C2DPolyBase>(); List <C2DHoledPolyBase> NewHoledPolys = new List <C2DHoledPolyBase>(); for (int i = Polygons.Count - 1; i >= 0; i--) { bool bMatched = false; C2DPolyBase pPoly = Polygons[i]; Polygons.RemoveAt(i); // Cycle through the newly created polygons to see if it's a hole. for (int p = 0; p < NewHoledPolys.Count; p++) { if (NewHoledPolys[p].Rim.Contains(pPoly.Lines[0].GetPointFrom())) { NewHoledPolys[p].AddHole(pPoly); bMatched = true; break; } } // If its not then compare it to all the other unknowns. if (!bMatched) { int u = 0; bool bKnownRim = false; while (u < Unmatched.Count) { if (!bKnownRim && Unmatched[u].Contains(pPoly.Lines[0].GetPointFrom())) { // This is a hole. NewHoledPolys.Add(new C2DHoledPolyBase()); NewHoledPolys[NewHoledPolys.Count - 1].Rim = Unmatched[u]; Unmatched.RemoveAt(u); NewHoledPolys[NewHoledPolys.Count - 1].AddHole(pPoly); bMatched = true; break; } else if (pPoly.Contains(Unmatched[u].Lines[0].GetPointFrom())) { // int nCount = OverlapPolygons->GetCount(); // This is a rim. if (!bKnownRim) { // If we haven't alreay worked this out then record that its a rim // and set up the new polygon. bKnownRim = true; NewHoledPolys.Add(new C2DHoledPolyBase()); NewHoledPolys[NewHoledPolys.Count - 1].Rim = pPoly; NewHoledPolys[NewHoledPolys.Count - 1].AddHole(Unmatched[u]); Unmatched.RemoveAt(u); } else { // We already worked out this was a rim so it must be the last polygon. NewHoledPolys[NewHoledPolys.Count - 1].AddHole(Unmatched[u]); Unmatched.RemoveAt(u); } // Record that its been matched. bMatched = true; } else { // Only if there was no match do we increment the counter. u++; } } } if (!bMatched) { Unmatched.Add(pPoly); } } for (int i = 0; i < Unmatched.Count; i++) { C2DHoledPolyBase NewHoled = new C2DHoledPolyBase(); NewHoled.Rim = Unmatched[i]; HoledPolys.Add(NewHoled); } HoledPolys.AddRange(NewHoledPolys); }