public void CanReadWriteSingleExteriorRingWithIslandsPolygonXyz() { 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, 321); innerRing.SpatialReference = sr; IPolygon polyWithHole = (IPolygon)IntersectionUtils.Difference(outerRing, innerRing); WkbGeometryWriter writer = new WkbGeometryWriter(); byte[] wkb = writer.WritePolygon(polyWithHole); // Wkx var ordinates = Ordinates.Xyz; 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 IPolyline GetOutermostBoundary(IPolygon fullUnionPolygon, out List <IRing> innerRings) { var resultRings = new List <IPath>(); innerRings = new List <IRing>(); foreach (IRing ring in GeometryUtils.GetRings(fullUnionPolygon)) { if (ring.IsExterior) { resultRings.Add(ring); } else { innerRings.Add(ring); } } IPolyline fullUnionOuterRings = GeometryFactory.CreatePolyline(resultRings); // TOP-4915: Must also handle boundary loops between source and target foreach (IPolygon boundaryLoop in BoundaryLoopUtils.GetBoundaryLoops( fullUnionPolygon, GeometryUtils.GetXyTolerance(fullUnionPolygon))) { // remove from result, add to rings IPolyline boundaryLoopLine = GeometryFactory.CreatePolyline(boundaryLoop); fullUnionOuterRings = (IPolyline)IntersectionUtils.Difference( fullUnionOuterRings, boundaryLoopLine); innerRings.AddRange(GeometryUtils.GetRings(boundaryLoop)); } return(fullUnionOuterRings); }
private static IPolyline GetCutLine(IMultiPatch sourceMultipatch, IPolygon overlappingPolygon) { IPolygon sourceFootprint = GeometryFactory.CreatePolygon(sourceMultipatch); IPolyline sourceFootprintBoundary = GeometryFactory.CreatePolyline(sourceFootprint); IPolyline overlappingPolygonBoundary = GeometryFactory.CreatePolyline(overlappingPolygon); const bool assumeIntersecting = true; const bool allowRandomStartPointsForClosedIntersections = true; IPolyline intersectionLines = IntersectionUtils.GetIntersectionLines( sourceFootprint, overlappingPolygonBoundary, assumeIntersecting, allowRandomStartPointsForClosedIntersections); // the intersectionLines also run along the boundary, but we only want the interior intersections var interiorIntersection = (IPolyline)IntersectionUtils.Difference( intersectionLines, sourceFootprintBoundary); return(interiorIntersection); }
public static IPolyline GetDifference([NotNull] IPolyline polyline, [NotNull] IPolyline otherLine, double?xyTolerance = null) { // The lines are often very short and close to each other --> xy cluster tolerance workaround is used far too often // --> test for IRelationalOperator.Equals at least if lines are very short? // --> if equal, return empty geometry? or null? if (xyTolerance != null) { double maxLengthWorkaround = xyTolerance.Value * 6; if (polyline.Length <= maxLengthWorkaround && otherLine.Length < maxLengthWorkaround) { if (((IRelationalOperator)polyline).Equals(otherLine)) { return(GeometryFactory.CreateEmptyPolyline(polyline)); } } } return((IPolyline)IntersectionUtils.Difference(polyline, otherLine)); }
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); }