private IEnumerable <IRing> ReadSingleExteriorRingPolygon( [NotNull] BinaryReader reader, Ordinates ordinates, bool?reverseOrder = null) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } int ringCount = checked ((int)reader.ReadUInt32()); bool zAware = ordinates == Ordinates.Xyz || ordinates == Ordinates.Xyzm; bool mAware = ordinates == Ordinates.Xym || ordinates == Ordinates.Xyzm; // NOTE: Somtimes this takes ca. 250ms (may be when the license is checked?)! IRing ringTemplate = GeometryFactory.CreateEmptyRing(zAware, mAware); if (ringCount > 0) { bool reverse = reverseOrder ?? !AssumeWkbPolygonsClockwise; var geometryBuilder = new WksPointListBuilder(reverse); foreach (WKSPointZ[] wksPoints in ReadLinestringsCore( reader, ordinates, ringCount, geometryBuilder)) { IRing resultRing = GeometryFactory.Clone(ringTemplate); GeometryUtils.SetWKSPointZs(resultRing, wksPoints); yield return(resultRing); } } }
public static void AddRingGroup(IMultiPatch result, RingGroup ringGroup, bool simplify, bool setPointIds) { IRing ringTemplate = GeometryFactory.CreateEmptyRing(result); int?pointId = setPointIds ? ringGroup.Id : null; if (simplify) { IPolygon poly = CreatePolygon(result, ringTemplate, ringGroup); GeometryUtils.Simplify(poly); if (!poly.IsEmpty) { AddToMultipatch(result, poly, false, pointId); return; } } Linestring exteriorRing = ringGroup.ExteriorRing; IList <Linestring> interiorRings = ringGroup.InteriorRings.ToList(); AddToMultipatch(result, ringTemplate, exteriorRing, interiorRings, false, pointId); }
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); }
public static IPolygon CreatePolygon(IGeometry template, IEnumerable <Linestring> rings) { IPolygon poly = GeometryFactory.CreateEmptyPolygon(template); IRing ringTemplate = GeometryFactory.CreateEmptyRing(template); foreach (Linestring closedLinestring in rings) { Assert.True(closedLinestring.IsClosed, "Linestring is not closed."); IRing ring = CreateRing(closedLinestring, ringTemplate); ((IGeometryCollection)poly).AddGeometry(ring); } ((IGeometryCollection)poly).GeometriesChanged(); return(poly); }
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); }