public void CanReadWriteSingleExteriorRingWithIslandsPolygonXy() { ISpatialReference sr = SpatialReferenceUtils.CreateSpatialReference( WellKnownHorizontalCS.LV95, WellKnownVerticalCS.LHN95); IPolygon outerRing = GeometryFactory.CreatePolygon(2600000, 1200000, 2601000, 1201000, sr); IPolygon innerRing = GeometryFactory.CreatePolygon(2600100, 1200100, 2600200, 1200200, sr); IPolygon polyWithHole = (IPolygon)IntersectionUtils.Difference(outerRing, innerRing); WkbGeometryWriter writer = new WkbGeometryWriter(); byte[] wkb = writer.WritePolygon(polyWithHole); // ArcObjects byte[] arcObjectsWkb = GeometryUtils.ToWkb(polyWithHole); Assert.AreEqual(arcObjectsWkb, wkb); // Wkx var ordinates = Ordinates.Xy; IGeometry exteriorRing = GeometryUtils.GetParts(polyWithHole).First(); IGeometry interiorRing = GeometryUtils.GetPaths(polyWithHole).Last(); LinearRing wkxOuterRing = ToWkxLinearRing(exteriorRing, ordinates); LinearRing wkxInnerRing = ToWkxLinearRing(interiorRing, ordinates); byte[] wkx = ToChristianSchwarzWkb(ToWkxPolygon(wkxOuterRing, new[] { wkxInnerRing })); Assert.AreEqual(wkx, wkb); // Bonus test: Geom WkbGeomWriter geomWriter = new WkbGeomWriter(); RingGroup ringGroup = GeometryConversionUtils.CreateRingGroup(polyWithHole); byte[] wkbGeom = geomWriter.WritePolygon(ringGroup, ordinates); Assert.AreEqual(wkb, wkbGeom); WkbGeometryReader reader = new WkbGeometryReader(); IPolygon restored = reader.ReadPolygon(new MemoryStream(wkb)); Assert.IsTrue(GeometryUtils.AreEqual(polyWithHole, restored)); // Geom: WkbGeomReader geomReader = new WkbGeomReader(); Assert.IsTrue( ringGroup.Equals(geomReader.ReadPolygon(new MemoryStream(wkbGeom)))); }
private static Dictionary <RingGroup, List <RingGroup> > PrepareSplitPartsDictionary( IList <IGeometry> cutFootprintParts) { var splitPartsByFootprintPart = new Dictionary <RingGroup, List <RingGroup> >(); foreach (IGeometry cutFootprintPart in cutFootprintParts) { var footprintPartGeom = GeometryConversionUtils.CreateRingGroup((IPolygon)cutFootprintPart); splitPartsByFootprintPart.Add(footprintPartGeom, new List <RingGroup>()); } return(splitPartsByFootprintPart); }
public void CanReadWriteSinglePartPolylineXyz() { var points = new WKSPointZ[4]; points[0] = new WKSPointZ { X = 2600000, Y = 1200000, Z = 456 }; points[1] = new WKSPointZ { X = 2600030, Y = 1200020, Z = 457 }; points[2] = new WKSPointZ { X = 2600020, Y = 1200030, Z = 459 }; points[3] = new WKSPointZ { X = 2600010, Y = 1200010, Z = 416 }; IPolyline polyline = GeometryFactory.CreatePolyline(points, null); WkbGeometryWriter writer = new WkbGeometryWriter(); byte[] wkb = writer.WritePolyline(polyline); // Wkx byte[] wkx = ToChristianSchwarzWkb(ToWkxLineString(points, Ordinates.Xyz)); Assert.AreEqual(wkx, wkb); // Bonus test: Geom WkbGeomWriter geomWriter = new WkbGeomWriter(); MultiPolycurve multiPlycurve = GeometryConversionUtils.CreateMultiPolycurve(polyline); byte[] wkbGeom = geomWriter.WriteMultiLinestring(multiPlycurve); Assert.AreEqual(wkb, wkbGeom); WkbGeometryReader reader = new WkbGeometryReader(); IPolyline restored = reader.ReadPolyline(new MemoryStream(wkb)); Assert.IsTrue(GeometryUtils.AreEqual(polyline, restored)); // Geom WkbGeomReader geomReader = new WkbGeomReader(); Assert.IsTrue( multiPlycurve.Equals(geomReader.ReadMultiPolycurve(new MemoryStream(wkbGeom)))); }
private static void CutAndAssignToFootprintParts( [NotNull] GeometryPart multipatchPart, [NotNull] IPolyline cutLine, [NotNull] IDictionary <RingGroup, List <RingGroup> > splitPartsByFootprintPart, ChangeAlongZSource zSource) { double tolerance = GeometryUtils.GetXyTolerance(multipatchPart.FirstGeometry); double zTolerance = GeometryUtils.GetZTolerance(multipatchPart.FirstGeometry); RingGroup ringGroup = GeometryConversionUtils.CreateRingGroup(multipatchPart); int pointId; if (GeometryUtils.HasUniqueVertexId( Assert.NotNull(multipatchPart.MainOuterRing), out pointId)) { ringGroup.Id = pointId; } bool inverted = ringGroup.ClockwiseOriented == false; if (inverted) { ringGroup.ReverseOrientation(); } IList <RingGroup> cutRingGroups = CutRingGroupPlanar(ringGroup, cutLine, tolerance, zSource, zTolerance); AssignResultsToFootprintParts(cutRingGroups, splitPartsByFootprintPart, tolerance); if (inverted) { foreach (RingGroup cutRingGroup in cutRingGroups) { cutRingGroup.ReverseOrientation(); } } }
public void CanReadWriteSingleRingPolygonXy() { IPolygon poly = GeometryFactory.CreatePolygon(2600000, 1200000, 2601000, 1201000); WkbGeometryWriter writer = new WkbGeometryWriter(); byte[] wkb = writer.WritePolygon(poly); // ArcObjects byte[] arcObjectsWkb = GeometryUtils.ToWkb(poly); Assert.AreEqual(arcObjectsWkb, wkb); // Wkx var ordinates = Ordinates.Xy; LinearRing wkxLinearRing = ToWkxLinearRing(GeometryUtils.GetWKSPointZs(poly), ordinates); byte[] wkx = ToChristianSchwarzWkb(ToWkxPolygon(wkxLinearRing)); Assert.AreEqual(wkx, wkb); // Bonus test: Geom WkbGeomWriter geomWriter = new WkbGeomWriter(); RingGroup ringGroup = GeometryConversionUtils.CreateRingGroup(poly); byte[] wkbGeom = geomWriter.WritePolygon(ringGroup, ordinates); Assert.AreEqual(wkb, wkbGeom); WkbGeometryReader reader = new WkbGeometryReader(); IPolygon restored = reader.ReadPolygon(new MemoryStream(wkb)); Assert.IsTrue(GeometryUtils.AreEqual(poly, restored)); // Geom: WkbGeomReader geomReader = new WkbGeomReader(); Assert.IsTrue( ringGroup.Equals(geomReader.ReadPolygon(new MemoryStream(wkbGeom)))); }
private static IEnumerable <Linestring> GetLineStrings([NotNull] IGeometry shape) { if (shape.GeometryType == esriGeometryType.esriGeometryMultiPatch) { var segments = QaGeometryUtils.GetSegments((IMultiPatch)shape); yield return(GetLineString(segments)); } else if (shape.GeometryType == esriGeometryType.esriGeometryPolygon || shape.GeometryType == esriGeometryType.esriGeometryPolyline) { foreach (var path in GetLinearizedPaths(shape)) { yield return(GeometryConversionUtils.GetLinestring(path)); } } else { throw new ArgumentException( $@"Unexpected geometry type: {shape.GeometryType}", nameof(shape)); } }
private static IList <IList <RingGroup> > TryCutConnectedComponents( IPolygon inputPolygon, IPolyline cutPolyline, ChangeAlongZSource zSource) { double tolerance = GeometryUtils.GetXyTolerance(inputPolygon); double zTolerance = GeometryUtils.GetZTolerance(inputPolygon); var result = new List <IList <RingGroup> >(); foreach (IPolygon connectedComponent in GeometryUtils.GetConnectedComponents( inputPolygon)) { RingGroup ringGroup = GeometryConversionUtils.CreateRingGroup(connectedComponent); IList <RingGroup> cutRingGroups = CutRingGroupPlanar( ringGroup, cutPolyline, tolerance, zSource, zTolerance); result.Add(cutRingGroups); } return(result); }
public void CanCutAlongUsingZSources() { GetOverlappingPolygons(out GdbFeature sourceFeature, out GdbFeature targetFeature); GeometryUtils.MakeZAware(sourceFeature.Shape); GeometryUtils.MakeZAware(targetFeature.Shape); var normal = new Vector(new[] { 0.5, 0.5, 2 }); Pnt3D planePoint = new Pnt3D(2600000, 1200000, 600); Plane3D sourcePlane = new Plane3D(normal, planePoint); ChangeAlongZUtils.AssignZ((IPointCollection)sourceFeature.Shape, sourcePlane); GeometryUtils.ApplyConstantZ(targetFeature.Shape, 500); CalculateCutLinesRequest calculationRequest = CreateCalculateCutLinesRequest(sourceFeature, targetFeature); CalculateCutLinesResponse calculateResponse = ChangeAlongServiceUtils.CalculateCutLines(calculationRequest, null); Assert.AreEqual(ReshapeAlongCurveUsability.CanReshape, (ReshapeAlongCurveUsability)calculateResponse.ReshapeLinesUsability); AssertReshapeLineCount(calculateResponse.CutLines, 1, 1); IPolyline reshapeLine = (IPolyline)ProtobufGeometryUtils.FromShapeMsg(calculateResponse.CutLines[0].Path); Assert.NotNull(reshapeLine); Assert.AreEqual(1000, (reshapeLine).Length); Linestring cutLinestring = GeometryConversionUtils.GetLinestring(GeometryUtils.GetPaths(reshapeLine).Single()); Pnt3D midPoint = (Pnt3D)cutLinestring.GetPointAlong(0.5, true); List <Pnt3D> points = GeometryConversionUtils.GetPntList(reshapeLine); Assert.IsTrue(points.All(p => MathUtils.AreEqual(p.Z, 500.0))); // // Cutting - TargetZ // var applyRequest = new ApplyCutLinesRequest(); applyRequest.CutLines.Add(calculateResponse.CutLines[0]); applyRequest.CalculationRequest = calculationRequest; applyRequest.InsertVerticesInTarget = false; applyRequest.ChangedVerticesZSource = (int)ChangeAlongZSource.Target; ApplyCutLinesResponse applyResponse = ChangeAlongServiceUtils.ApplyCutLines(applyRequest, null); Assert.AreEqual(2, applyResponse.ResultFeatures.Count); List <IGeometry> cutGeometries = applyResponse.ResultFeatures.Select(GetShape).ToList(); Assert.AreEqual(1000 * 1000, cutGeometries.Sum(g => ((IArea)g).Area)); List <MultiPolycurve> multiPolycurves = cutGeometries .Select(g => GeometryConversionUtils.CreateMultiPolycurve((IPolycurve)g)) .ToList(); foreach (MultiPolycurve multiPolycurve in multiPolycurves) { Line3D segment = multiPolycurve.FindSegments(midPoint, 0.001).First().Value; Assert.AreEqual(500, segment.StartPoint.Z); Assert.AreEqual(500, segment.EndPoint.Z); } // // Cutting - Interpolate // applyRequest = new ApplyCutLinesRequest(); applyRequest.CutLines.Add(calculateResponse.CutLines[0]); applyRequest.CalculationRequest = calculationRequest; applyRequest.InsertVerticesInTarget = false; applyRequest.ChangedVerticesZSource = (int)ChangeAlongZSource.InterpolatedSource; applyResponse = ChangeAlongServiceUtils.ApplyCutLines(applyRequest, null); Assert.AreEqual(2, applyResponse.ResultFeatures.Count); cutGeometries = applyResponse.ResultFeatures.Select(GetShape).ToList(); Assert.AreEqual(1000 * 1000, cutGeometries.Sum(g => ((IArea)g).Area)); multiPolycurves = cutGeometries .Select(g => GeometryConversionUtils.CreateMultiPolycurve((IPolycurve)g)) .ToList(); foreach (MultiPolycurve multiPolycurve in multiPolycurves) { List <Line3D> segments = multiPolycurve.FindSegments(midPoint, 0.001) .Select(kvp => kvp.Value).ToList(); Assert.AreEqual(2, segments.Count); // Check if they are properly ordered and same length Assert.AreEqual(segments[0].EndPoint, segments[1].StartPoint); Assert.AreEqual(segments[0].Length2D, segments[1].Length2D); // Check if they are interpolated double average = (segments[0].StartPoint.Z + segments[1].EndPoint.Z) / 2; Assert.AreEqual(average, segments[0].EndPoint.Z); } // // Cutting - Plane // applyRequest = new ApplyCutLinesRequest(); applyRequest.CutLines.Add(calculateResponse.CutLines[0]); applyRequest.CalculationRequest = calculationRequest; applyRequest.InsertVerticesInTarget = false; applyRequest.ChangedVerticesZSource = (int)ChangeAlongZSource.SourcePlane; applyResponse = ChangeAlongServiceUtils.ApplyCutLines(applyRequest, null); Assert.AreEqual(2, applyResponse.ResultFeatures.Count); cutGeometries = applyResponse.ResultFeatures.Select(GetShape).ToList(); Assert.AreEqual(1000 * 1000, cutGeometries.Sum(g => ((IArea)g).Area)); multiPolycurves = cutGeometries .Select(g => GeometryConversionUtils.CreateMultiPolycurve((IPolycurve)g)) .ToList(); foreach (MultiPolycurve multiPolycurve in multiPolycurves) { bool?coplanar = ChangeAlongZUtils.AreCoplanar( multiPolycurve.GetPoints().ToList(), sourcePlane, 0.01, out double _, out string _); Assert.IsTrue(coplanar); } }
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); }
private static List <IGeometry> TryCutArcObjects( [NotNull] IPolygon inputPolygon, [NotNull] IPolyline cutPolyline, ChangeAlongZSource zSource) { cutPolyline = ChangeAlongZUtils.PrepareCutPolylineZs(cutPolyline, zSource); var existingFeature = new List <IPolygon>(); var newFeatures = new List <IPolygon>(); foreach (IPolygon connectedComponent in GeometryUtils.GetConnectedComponents( inputPolygon)) { Plane3D plane = null; if (zSource == ChangeAlongZSource.SourcePlane) { double zTolerance = GeometryUtils.GetZTolerance(inputPolygon); plane = ChangeAlongZUtils.GetSourcePlane( GeometryConversionUtils.GetPntList(connectedComponent), zTolerance); } var cutComponents = TryCut(connectedComponent, cutPolyline); if (cutComponents == null) { existingFeature.Add(connectedComponent); } else { var largest = GeometryUtils.GetLargestGeometry(cutComponents); foreach (IPolygon cutComponent in cutComponents.Cast <IPolygon>()) { if (plane != null) { ChangeAlongZUtils.AssignZ((IPointCollection)cutComponent, plane); } else if (zSource == ChangeAlongZSource.InterpolatedSource && GeometryUtils.IsZAware(cutComponent)) { ((IZ)cutComponent).CalculateNonSimpleZs(); } if (cutComponent == largest) { existingFeature.Add(cutComponent); } else { newFeatures.Add(cutComponent); } } } } if (newFeatures.Count == 0) { return(null); } var result = new List <IGeometry> { GeometryUtils.Union(existingFeature), }; result.AddRange(newFeatures.Cast <IGeometry>()); return(result); }
public void CanReadWriteMultipartPolygonXyz() { ISpatialReference sr = SpatialReferenceUtils.CreateSpatialReference( WellKnownHorizontalCS.LV95, WellKnownVerticalCS.LHN95); IPolygon outerRing = GeometryFactory.CreatePolygon(2600000, 1200000, 2601000, 1201000, 432); outerRing.SpatialReference = sr; IPolygon innerRing = GeometryFactory.CreatePolygon(2600100, 1200100, 2600200, 1200200, 421); innerRing.SpatialReference = sr; IPolygon polyWithHole = (IPolygon)IntersectionUtils.Difference(outerRing, innerRing); IPolygon poly2 = GeometryFactory.CreatePolygon(2610000, 1200000, 2611000, 1201000, 543); poly2.SpatialReference = sr; IPolygon multiPolygon = (IPolygon)GeometryUtils.Union(polyWithHole, poly2); Assert.IsTrue(GeometryUtils.IsZAware(multiPolygon)); GeometryUtils.Simplify(multiPolygon); WkbGeometryWriter writer = new WkbGeometryWriter(); byte[] wkb = writer.WritePolygon(multiPolygon); // Wkx var ordinates = Ordinates.Xyz; IList <IGeometry> parts = GeometryUtils.GetParts(multiPolygon).ToList(); IGeometry exteriorRing = parts[0]; IGeometry interiorRing = parts[1]; IGeometry secondExteriorRing = parts[2]; LinearRing wkxOuterRing = ToWkxLinearRing(exteriorRing, ordinates); LinearRing wkxInnerRing = ToWkxLinearRing(interiorRing, ordinates); Polygon wkxPolygon1 = ToWkxPolygon(wkxOuterRing, new[] { wkxInnerRing }); Polygon wkxPolygon2 = ToWkxPolygon(ToWkxLinearRing(secondExteriorRing, ordinates)); MultiPolygon wkxMultiPolygon = new MultiPolygon(new[] { wkxPolygon1, wkxPolygon2 }); byte[] wkx = ToChristianSchwarzWkb(wkxMultiPolygon); Assert.AreEqual(wkx, wkb); // Bonus test: Geom WkbGeomWriter geomWriter = new WkbGeomWriter(); MultiPolycurve multiPly = GeometryConversionUtils.CreateMultiPolycurve(multiPolygon); byte[] wkbGeom = geomWriter.WriteMultipolygon(multiPly, ordinates); Assert.AreEqual(wkb, wkbGeom); WkbGeometryReader reader = new WkbGeometryReader(); IPolygon restored = reader.ReadPolygon(new MemoryStream(wkb)); Assert.IsTrue(GeometryUtils.AreEqual(multiPolygon, restored)); // Geom: WkbGeomReader geomReader = new WkbGeomReader(); IList <RingGroup> readMultiPolygon = geomReader.ReadMultiPolygon(new MemoryStream(wkbGeom)); var readMultiPolycurve = new MultiPolycurve( readMultiPolygon.SelectMany(g => g.GetLinestrings())); Assert.IsTrue(multiPly.Equals(readMultiPolycurve)); // As multipatch IMultiPatch multipatch = GeometryFactory.CreateMultiPatch(multiPolygon); wkb = writer.WriteMultipatch(multipatch); IMultiPatch readMultipatch = (IMultiPatch)reader.ReadGeometry(new MemoryStream(wkb)); // TODO: Implement AreEqual for multipatch that is more permissive regarding First/Outer ring type AssertEqual(multipatch, readMultipatch); }
public void CanReadWriteMultiPartPolylineXyz() { // The spatial reference is important to avoid small differences in // coordinates (snap to spatial reference!) ISpatialReference sr = SpatialReferenceUtils.CreateSpatialReference( WellKnownHorizontalCS.LV95, WellKnownVerticalCS.LHN95); var points1 = new WKSPointZ[4]; points1[0] = new WKSPointZ { X = 2600000, Y = 1200000, Z = 456 }; points1[1] = new WKSPointZ { X = 2600030, Y = 1200020, Z = 457 }; points1[2] = new WKSPointZ { X = 2600020, Y = 1200030, Z = 459 }; points1[3] = new WKSPointZ { X = 2600040, Y = 1200040, Z = 416 }; IPolyline polyline1 = GeometryFactory.CreatePolyline(points1, sr); var points2 = new WKSPointZ[4]; points2[0] = new WKSPointZ { X = 2610000, Y = 1200000, Z = 656 }; points2[1] = new WKSPointZ { X = 2610030, Y = 1200020, Z = 657 }; points2[2] = new WKSPointZ { X = 2610020, Y = 1200030, Z = 659 }; points2[3] = new WKSPointZ { X = 2610040, Y = 1200040, Z = 616 }; IPolyline polyline2 = GeometryFactory.CreatePolyline(points2, sr); IPolyline polyline = (IPolyline)GeometryUtils.Union(polyline1, polyline2); GeometryUtils.Simplify(polyline); WkbGeometryWriter writer = new WkbGeometryWriter(); byte[] wkb = writer.WritePolyline(polyline); // Wkx var ordinates = Ordinates.Xyz; MultiLineString multiLineString = new MultiLineString( new List <LineString> { ToWkxLineString(points1, ordinates), ToWkxLineString(points2, ordinates) }); byte[] wkx = ToChristianSchwarzWkb(multiLineString); Assert.AreEqual(wkx, wkb); // Bonus test: Geom WkbGeomWriter geomWriter = new WkbGeomWriter(); MultiPolycurve multiPlycurve = GeometryConversionUtils.CreateMultiPolycurve(polyline); byte[] wkbGeom = geomWriter.WriteMultiLinestring(multiPlycurve, ordinates); Assert.AreEqual(wkb, wkbGeom); WkbGeometryReader reader = new WkbGeometryReader(); IPolyline restored = reader.ReadPolyline(new MemoryStream(wkb)); Assert.IsTrue(GeometryUtils.AreEqual(polyline, restored)); // Geom: WkbGeomReader geomReader = new WkbGeomReader(); Assert.IsTrue( multiPlycurve.Equals(geomReader.ReadMultiPolycurve(new MemoryStream(wkbGeom)))); }
private IList <IGeometry> RemoveOverlap( [NotNull] IPolycurve fromGeometry, [NotNull] IPolycurve overlaps, ChangeAlongZSource zSource, out IList <IGeometry> overlappingResults) { Assert.ArgumentNotNull(fromGeometry, nameof(fromGeometry)); Assert.ArgumentNotNull(overlaps, nameof(overlaps)); overlaps = ChangeAlongZUtils.PrepareCutPolylineZs(overlaps, zSource); Plane3D plane = null; if (zSource == ChangeAlongZSource.SourcePlane) { plane = ChangeAlongZUtils.GetSourcePlane( GeometryConversionUtils.GetPntList(fromGeometry), GeometryUtils.GetZTolerance(fromGeometry)); } IGeometry rawResult = GetDifference(fromGeometry, overlaps); if (plane != null) { ChangeAlongZUtils.AssignZ((IPointCollection)rawResult, plane); } int originalPartCount = GetRelevantPartCount(fromGeometry); int resultPartCount = GetRelevantPartCount(rawResult); // TODO: This works for simple cases. To be correct the difference operation and part comparison would have to be // done on a per-part basis, because in the same operation one part could be added and one removed. // Just comparing part counts before and after is misleading in such cases. if (resultPartCount > originalPartCount) { Result.ResultHasMultiparts = true; } IList <IGeometry> result = new List <IGeometry>(); // TODO explode only those input parts that where cut into more than one result part // --> preserve other input parts in original geometry if (rawResult is IPolycurve && _explodeMultipartResult && IsMultipart(rawResult)) { // Exploding all selected multipart geos // to explode geos only if not avoidable, // use GetPositivePartCount and compare counts before and after cut operation foreach (IGeometry geometry in GeometryUtils.Explode(rawResult)) { var part = (IPolycurve)geometry; result.Add(part); } if (((IGeometryCollection)fromGeometry).GeometryCount > 1) { // TODO: Fix this situation by checking which individual parts were split by the overlap and only turn them into a new feature _msg.Warn( "The selection included multi-part geometry. Storing this geometry generated several copies of the feature."); } } else { result.Add(rawResult); } overlappingResults = _storeOverlapsAsNewFeatures ? CalculateOverlappingGeometries(fromGeometry, overlaps) : null; return(result); }