private static IList <IGeometry> TryCutRingGroups( IPolygon inputPolygon, IPolyline cutPolyline, ChangeAlongZSource zSource) { // TODO: // In order to avoid the arbitrary grouping of multipart polygons, try to apply left/right logic // provided by GeomTopoOpUtils var existingFeature = new List <IPolygon>(); var newFeatures = new List <IPolygon>(); var cutResultsPerConnectedComponent = TryCutConnectedComponents(inputPolygon, cutPolyline, zSource); foreach (IList <RingGroup> cutRingGroups in cutResultsPerConnectedComponent) { IRing ringTemplate = GeometryFactory.CreateEmptyRing(inputPolygon); var cutResults = cutRingGroups.Select( rg => GeometryConversionUtils.CreatePolygon( inputPolygon, ringTemplate, rg)) .ToList(); var largest = GeometryUtils.GetLargestGeometry(cutResults); foreach (IPolygon cutComponent in cutResults) { if (cutComponent == largest) { existingFeature.Add(cutComponent); } else { newFeatures.Add(cutComponent); } } } if (newFeatures.Count == 0) { // no cut happened: return(null); } var result = new List <IGeometry> { GeometryUtils.Union(existingFeature) }; result.AddRange(newFeatures.Cast <IGeometry>()); return(result); }
private static Dictionary <IPolygon, IMultiPatch> BuildResultMultipatches( [NotNull] IMultiPatch prototype, [NotNull] IDictionary <RingGroup, List <RingGroup> > splitResultsByFootprintPart, DegenerateMultipatchFootprintAction nonSimpleBoundaryAction) { var result = new Dictionary <IPolygon, IMultiPatch>(); IRing emptyRing = GeometryFactory.CreateEmptyRing(prototype); foreach (var outerRingsByFootprintPart in splitResultsByFootprintPart) { RingGroup footprintPart = outerRingsByFootprintPart.Key; List <RingGroup> resultPolys = outerRingsByFootprintPart.Value; IMultiPatch resultMultipatch = GeometryFactory.CreateEmptyMultiPatch(prototype); foreach (RingGroup poly in resultPolys) { // TODO: Support vertical ring group with inner rings bool simplify = poly.InteriorRings.Any(); GeometryConversionUtils.AddRingGroup( resultMultipatch, poly, simplify, poly.Id != null); } if (resultPolys.Any(p => p.Id != null)) { GeometryUtils.MakePointIDAware(resultMultipatch); } // Guard against multipatches with wrong footprint. They are so broken (IRelationalOps are wrong) that // it's not worth using them any further... if (IsMultipatchWithDegenerateFootprint(resultMultipatch)) { switch (nonSimpleBoundaryAction) { case DegenerateMultipatchFootprintAction.Throw: throw new DegenerateResultGeometryException( "The multipatch cut operation resulted in a multipatch with degenerate footprint."); case DegenerateMultipatchFootprintAction.Discard: _msg.DebugFormat( "Discarding result multipatch with degenerate boundary: {0}", GeometryUtils.ToString(resultMultipatch)); continue; case DegenerateMultipatchFootprintAction.Keep: _msg.DebugFormat( "Detected result multipatch with degenerate boundary (it will be kept): {0}", GeometryUtils.ToString(resultMultipatch)); break; } } IPolygon footprintPoly = GeometryConversionUtils.CreatePolygon(emptyRing, emptyRing, footprintPart); result.Add(footprintPoly, resultMultipatch); } return(result); }
private static IList <IGeometry> TryCutXY( IPolygon inputPolygon, IPolyline cutPolyline, ChangeAlongZSource zSource) { // TODO: // In order to avoid the arbitrary grouping of multipart polygons, try to apply left/right logic // provided by GeomTopoOpUtils double tolerance = GeometryUtils.GetXyTolerance(inputPolygon); double zTolerance = GeometryUtils.GetZTolerance(inputPolygon); MultiPolycurve inputMultipoly = GeometryConversionUtils.CreateMultiPolycurve(inputPolygon); var cutLine = GeometryFactory.Clone(cutPolyline); if (GeometryUtils.IsZAware(cutLine) && zSource != ChangeAlongZSource.Target) { ((IZAware)cutLine).DropZs(); } Plane3D plane = null; if (zSource == ChangeAlongZSource.SourcePlane) { plane = ChangeAlongZUtils.GetSourcePlane( inputMultipoly.GetPoints().ToList(), zTolerance); } GeometryUtils.Simplify(cutLine, true, true); MultiPolycurve cutLinestrings = GeometryConversionUtils.CreateMultiPolycurve(cutLine); bool isMultipart = GeometryUtils.GetExteriorRingCount(inputPolygon) > 1; IList <MultiLinestring> resultGeoms = GeomTopoOpUtils.CutXY(inputMultipoly, cutLinestrings, tolerance, !isMultipart); var result = new List <IGeometry>(); foreach (MultiLinestring resultPoly in resultGeoms) { if (plane != null) { resultPoly.AssignUndefinedZs(plane); } else { resultPoly.InterpolateUndefinedZs(); } result.Add(GeometryConversionUtils.CreatePolygon(inputPolygon, resultPoly.GetLinestrings())); } Marshal.ReleaseComObject(cutLine); return(result.Count == 0 ? null : result); }