private static List <Linestring> RemoveContainedExistingIslands <T>( [NotNull] T fromPolygon, [NotNull] Linestring cookieCutter, double tolerance) where T : MultiLinestring { List <Linestring> existingInnerRings = fromPolygon .GetLinestrings() .Where(l => l.ClockwiseOriented == false) .ToList(); Assert.NotNull(cookieCutter.ClockwiseOriented); var containedExistingIslands = new List <Linestring>(); foreach (Linestring existingInnerRing in existingInnerRings) { bool?islandWithinCookie = GeomRelationUtils.AreaContainsXY( cookieCutter, existingInnerRing.StartPoint, tolerance, true); // TODO: handle the case where the inner ring touches cutter in StartPoint if (islandWithinCookie == true) { containedExistingIslands.Add(existingInnerRing); fromPolygon.RemoveLinestring(existingInnerRing); } } return(containedExistingIslands); }
/// <summary> /// Returns source rings disjoint from target and target rings disjoint from source. /// </summary> /// <param name="ringPredicate"></param> /// <returns></returns> private IEnumerable <Linestring> GetRingsDisjointFromOtherPoly( Predicate <Linestring> ringPredicate) { var result = new List <Linestring>(); // W.r.t. AreaContainsXY returning null: if the start point is on the boundary there // are duplicate rings which need to be identified elsewhere. ISegmentList target = _subcurveNavigator.Target; foreach (Linestring ring in _subcurveNavigator.GetNonIntersectedSourceRings() .Where(r => ringPredicate(r))) { bool?contains = GeomRelationUtils.AreaContainsXY( target, ring.StartPoint, _subcurveNavigator.Tolerance); if (contains == false) { // disjoint result.Add(ring); } } ISegmentList source = _subcurveNavigator.Source; foreach (Linestring ring in _subcurveNavigator.GetNonIntersectedTargets() .Where(r => ringPredicate(r))) { bool?contains = GeomRelationUtils.AreaContainsXY( source, ring.StartPoint, _subcurveNavigator.Tolerance); if (contains == false) { result.Add(ring); } } return(result); }
private static int GetContainingRingIndex([NotNull] MultiLinestring polygon, [NotNull] Linestring containedRing, double tolerance, out bool ringsAreEqual, out IntersectionPoint3D touchPoint) { IList <IntersectionPoint3D> intersectionPoints = GeomTopoOpUtils.GetIntersectionPoints(polygon, containedRing, tolerance); ringsAreEqual = false; touchPoint = null; // Equal to outer ring -> removes outer ring in original // or equal to inner ring -> ignore cookie cutter if (intersectionPoints.Count == 2 && intersectionPoints[0].SourcePartIndex == intersectionPoints[1].SourcePartIndex && intersectionPoints[0].Point.Equals(intersectionPoints[1].Point) && intersectionPoints[0].Type == IntersectionPointType.LinearIntersectionStart && intersectionPoints[1].Type == IntersectionPointType.LinearIntersectionEnd) { ringsAreEqual = true; return(intersectionPoints[0].SourcePartIndex); } var outerRingIntersections = intersectionPoints .Where(i => polygon.GetLinestring(i.SourcePartIndex).ClockwiseOriented == true) .ToList(); // Touching outer ring in one point -> boundary loop in original if (outerRingIntersections.Count > 0) { Assert.True(outerRingIntersections.Count < 2, "Unexpected number of touching points."); touchPoint = outerRingIntersections[0]; return(touchPoint.SourcePartIndex); } // Inside an inner ring -> ignore cookie cutter for (int i = 0; i < polygon.PartCount; i++) { Linestring ring = polygon.GetLinestring(i); if (ring.ClockwiseOriented == true) { continue; } int currentIdx = i; bool?areaContainsXY = GeomRelationUtils.AreaContainsXY( ring, containedRing, intersectionPoints.Where(ip => ip.SourcePartIndex == currentIdx), tolerance, true); if (areaContainsXY == true) { return(i); } } // Inside an outer ring but not an inner ring: Add as island for (int i = 0; i < polygon.PartCount; i++) { Linestring ring = polygon.GetLinestring(i); if (ring.ClockwiseOriented == false) { continue; } if (GeomRelationUtils.AreaContainsXY(ring, containedRing.StartPoint, tolerance) == true) { return(i); } } return(-1); }