public void CanCutMultipatchWithInnerRingThroughInnerRing() { ISpatialReference lv95 = SpatialReferenceUtils.CreateSpatialReference( WellKnownHorizontalCS.LV95); IPolygon originalPoly = GeometryFactory.CreatePolygon( GeometryFactory.CreateEnvelope(2600000, 1200000, 500, 50, 50, lv95)); IPolygon innerRingPoly = GeometryFactory.CreatePolygon( GeometryFactory.CreateEnvelope(2600000, 1200000, 500, 10, 10, lv95)); var innerRing = (IRing)((IGeometryCollection)innerRingPoly).Geometry[0]; innerRing.ReverseOrientation(); IMultiPatch multiPatch = GeometryFactory.CreateMultiPatch(originalPoly); GeometryFactory.AddRingToMultiPatch(innerRing, multiPatch, esriMultiPatchRingType .esriMultiPatchInnerRing); // cut line cuts through the inner ring IPolyline cutLine = GeometryFactory.CreateLine( GeometryFactory.CreatePoint(2600000 - 100, 1200000), GeometryFactory.CreatePoint(2600000 + 100, 1200000)); cutLine.SpatialReference = lv95; IFeature mockFeature = TestUtils.CreateMockFeature(multiPatch); var cutter = new FeatureCutter(new[] { mockFeature }); cutter.ZSourceProvider = new DatasetSpecificSettingProvider <ChangeAlongZSource>( string.Empty, ChangeAlongZSource.SourcePlane); cutter.Cut(cutLine); IList <IGeometry> results = cutter.ResultGeometriesByFeature[mockFeature]; Assert.AreEqual(2, results.Count); double areaSum = 0; var partCount = 0; foreach (IGeometry result in cutter.ResultGeometriesByFeature[mockFeature]) { Assert.IsFalse(GeometryUtils.HasUndefinedZValues(result)); areaSum += GeometryUtils.GetParts((IGeometryCollection)result) .Sum(part => ((IArea)part).Area); partCount += GeometryUtils.GetParts((IGeometryCollection)result).Count(); } Assert.AreEqual(2, partCount); Assert.AreEqual(((IArea)originalPoly).Area + ((IArea)innerRing).Area, areaSum, 0.0001); }
private static void AddToMultipatch(IMultiPatch result, IPolygon poly, bool invert, int?pointId) { IList <IRing> exteriorRings; var innerRings = GeometryUtils.GetRings(poly, out exteriorRings); Assert.AreEqual(1, exteriorRings.Count, "Unexpected ring count"); IRing mainRing = exteriorRings[0]; if (pointId != null) { GeometryUtils.AssignConstantPointID((IPointCollection)mainRing, pointId.Value); } if (invert) { mainRing.ReverseOrientation(); foreach (IRing innerRing in innerRings) { innerRing.ReverseOrientation(); } } GeometryFactory.AddRingToMultiPatch( mainRing, result, esriMultiPatchRingType.esriMultiPatchOuterRing); foreach (IRing innerRing in innerRings) { if (pointId != null) { GeometryUtils.AssignConstantPointID((IPointCollection)innerRing, pointId.Value); } GeometryFactory.AddRingToMultiPatch( innerRing, result, esriMultiPatchRingType.esriMultiPatchInnerRing); } }
private IMultiPatch ReadMultipatch(BinaryReader reader, Ordinates expectedOrdinates, bool groupPartsByPointIDs = false) { IMultiPatch result = new MultiPatchClass(); if (groupPartsByPointIDs) { GeometryUtils.MakePointIDAware(result); } int polyhedraCount = checked ((int)reader.ReadUInt32()); for (int i = 0; i < polyhedraCount; i++) { WkbGeometryType geometryType; Ordinates ordinates; ReadWkbType(reader, false, out geometryType, out ordinates); Assert.AreEqual(WkbGeometryType.PolyhedralSurface, geometryType, "Unexpected geometry type"); Assert.AreEqual(expectedOrdinates, ordinates, "Unexpected ordinates dimension"); int polygonCount = checked ((int)reader.ReadUInt32()); for (int p = 0; p < polygonCount; p++) { ReadWkbType(reader, false, out geometryType, out expectedOrdinates); Assert.AreEqual(WkbGeometryType.Polygon, geometryType, "Unexpected geometry type"); var rings = ReadSingleExteriorRingPolygon(reader, ordinates, false).ToList(); if (rings.Count == 0) { continue; } if (groupPartsByPointIDs) { AssignPointIds(rings, i); } var outerRingType = rings.Count > 1 ? esriMultiPatchRingType.esriMultiPatchOuterRing : p == 0 || groupPartsByPointIDs ? esriMultiPatchRingType.esriMultiPatchFirstRing : esriMultiPatchRingType.esriMultiPatchRing; IRing outerRing = rings[0]; GeometryFactory.AddRingToMultiPatch(outerRing, result, outerRingType); if (rings.Count > 1) { for (int r = 1; r < rings.Count; r++) { IRing innerRing = rings[r]; GeometryFactory.AddRingToMultiPatch( innerRing, result, esriMultiPatchRingType.esriMultiPatchInnerRing); } } } } return(result); }
public void CannotPerformVerticalReshapeOnFlatRing() { // Originally this geometry resulted in an endless loop because // IntersectionUtils.IntersectNonPlanar returned the incorrect result ISpatialReference lv95 = SpatialReferenceUtils.CreateSpatialReference( WellKnownHorizontalCS.LV95, WellKnownVerticalCS.LHN95); // The problem cannot be reproduced with standard resolution var srResolution = (ISpatialReferenceResolution)lv95; srResolution.set_XYResolution(true, 0.001); var srTolerance = (ISpatialReferenceTolerance)lv95; srTolerance.XYTolerance = 0.01; // Vertical triangle, oriented towards the south: var points = new WKSPointZ[6]; points[0] = new WKSPointZ { X = 2578309.3000000007, Y = 1183264.3999999985, Z = 619.14500000000407 }; points[1] = new WKSPointZ { X = 2578295.6829999983, Y = 1183260.568, Z = 619.14500000000407 }; points[2] = new WKSPointZ { X = 2578293.9990000017, Y = 1183266.5500000007, Z = 619.14500000000407 }; points[3] = new WKSPointZ { X = 2578295.9070000015, Y = 1183267.1559999995, Z = 619.14500000000407 }; points[4] = new WKSPointZ { X = 2578307.5989999995, Y = 1183270.4450000003, Z = 619.14500000000407 }; points[5] = new WKSPointZ { X = 2578309.3000000007, Y = 1183264.3999999985, Z = 619.14500000000407 }; IRing ring = new RingClass(); ((IGeometry)ring).SpatialReference = lv95; GeometryUtils.MakeZAware(ring); GeometryUtils.SetWKSPointZs((IPointCollection4)ring, points); IMultiPatch multipatch = new MultiPatchClass(); ((IGeometry)multipatch).SpatialReference = lv95; GeometryUtils.MakeZAware(multipatch); GeometryUtils.MakeMAware(multipatch); GeometryUtils.MakePointIDAware(multipatch); GeometryFactory.AddRingToMultiPatch(ring, multipatch, esriMultiPatchRingType .esriMultiPatchOuterRing); var unReshaped = (IRing)((IGeometryCollection)multipatch).Geometry[0]; IPolyline cutLine = GeometryFactory.CreateLine( GeometryFactory.CreatePoint(2578314.9090000018, 1183246.2400000021), GeometryFactory.CreatePoint(2578307.4299999997, 1183270.4310000017)); cutLine.SpatialReference = lv95; //GeometryUtils.MakeZAware(cutLine); var reshapePath = (IPath)((IGeometryCollection)cutLine).Geometry[0]; Assert.IsTrue(((ICurve3D)unReshaped).IsClosed3D); var reshapeInfo = new ReshapeInfo(multipatch, reshapePath, null); IList <IPath> verticalPaths; Assert.IsFalse(reshapeInfo.IsVerticalRingReshape(0, out verticalPaths)); Assert.AreEqual(0, verticalPaths.Count); Assert.IsTrue(ReshapeUtils.ReshapeGeometry(reshapeInfo, reshapePath)); var reshapedRing = (IRing)((IGeometryCollection)multipatch).Geometry[0]; Assert.AreEqual(6, ((IPointCollection)reshapedRing).PointCount); Assert.IsTrue(((ICurve3D)reshapedRing).IsClosed3D); }
public void CanReshapeVerticalRingWithMutipleReshapeLineCrossings() { ISpatialReference lv95 = SpatialReferenceUtils.CreateSpatialReference( WellKnownHorizontalCS.LV95); // Vertical triangle, oriented towards the south: var points = new WKSPointZ[4]; points[0] = new WKSPointZ { X = 2600000, Y = 1200000, Z = 500 }; points[1] = new WKSPointZ { X = 2600100, Y = 1200000, Z = 500 }; points[2] = new WKSPointZ { X = 2600050, Y = 1200000, Z = 1000 }; points[3] = new WKSPointZ { X = 2600000, Y = 1200000, Z = 500 }; IRing ring = new RingClass(); ((IGeometry)ring).SpatialReference = lv95; GeometryUtils.MakeZAware(ring); GeometryUtils.SetWKSPointZs((IPointCollection4)ring, points); IMultiPatch multipatch = new MultiPatchClass(); ((IGeometry)multipatch).SpatialReference = lv95; GeometryUtils.MakeZAware(multipatch); GeometryUtils.MakeMAware(multipatch); GeometryUtils.MakePointIDAware(multipatch); GeometryFactory.AddRingToMultiPatch(ring, multipatch, esriMultiPatchRingType .esriMultiPatchOuterRing); var unReshaped = (IRing)((IGeometryCollection)multipatch).Geometry[0]; IPolyline cutLine = GeometryFactory.CreateLine( GeometryFactory.CreatePoint(2600075, 1200000 - 100, 222), GeometryFactory.CreatePoint(2600075, 1200000 + 100, 222), GeometryFactory.CreatePoint(2600025, 1200000 + 100, 222), GeometryFactory.CreatePoint(2600025, 1200000 - 100, 222)); cutLine.SpatialReference = lv95; GeometryUtils.MakeZAware(cutLine); var reshapePath = (IPath)((IGeometryCollection)cutLine).Geometry[0]; Assert.IsTrue(((ICurve3D)unReshaped).IsClosed3D); var reshapeInfo = new ReshapeInfo(multipatch, reshapePath, null); IList <IPath> verticalPaths; Assert.IsTrue(reshapeInfo.IsVerticalRingReshape(0, out verticalPaths)); Assert.AreEqual(2, verticalPaths.Count); // Currently it is the caller's responsability to make 2 different reshapes using the desired side... // We want the middle part: // verticalPaths[0] is the one at X=2600025 var reshape1 = new ReshapeInfo(multipatch, verticalPaths[0], null); reshape1.RingReshapeSide = RingReshapeSideOfLine.Right; reshape1.NonPlanar = true; ReshapeUtils.ReshapeGeometry(reshape1, verticalPaths[0]); // verticalPaths[1] is the one at X=2600075 var reshape2 = new ReshapeInfo(multipatch, verticalPaths[1], null); reshape2.RingReshapeSide = RingReshapeSideOfLine.Left; reshape2.NonPlanar = true; ReshapeUtils.ReshapeGeometry(reshape2, verticalPaths[1]); var reshapedRing = (IRing)((IGeometryCollection)multipatch).Geometry[0]; Assert.AreEqual(6, ((IPointCollection)reshapedRing).PointCount); Assert.IsTrue(((ICurve3D)reshapedRing).IsClosed3D); double expectedLength = Math.Sqrt(50 * 50 + 500 * 500) * 1.0 + 50 + 2 * 250; Assert.AreEqual(expectedLength, ((ICurve3D)reshapedRing).Length3D, 0.001); var newPoints = new WKSPointZ[6]; GeometryUtils.QueryWKSPointZs((IPointCollection4)reshapedRing, newPoints); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600025, Y = 1200000, Z = 500 }, newPoints[0], 0, 0)); // the new cut points Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600075, Y = 1200000, Z = 500 }, newPoints[1], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600075, Y = 1200000, Z = 750 }, newPoints[2], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600050, Y = 1200000, Z = 1000 }, newPoints[3], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600025, Y = 1200000, Z = 750 }, newPoints[4], 0, 0)); }
public void CanReshapeVerticalTriangularRingInMultipatch() { ISpatialReference lv95 = SpatialReferenceUtils.CreateSpatialReference( WellKnownHorizontalCS.LV95); //IRing ring = GeometryFactory.CreateRing( // GeometryFactory.CreatePath()) var points = new WKSPointZ[4]; points[0] = new WKSPointZ { X = 2600000, Y = 1200000, Z = 500 }; points[1] = new WKSPointZ { X = 2600100, Y = 1200000, Z = 500 }; points[2] = new WKSPointZ { X = 2600050, Y = 1200000, Z = 1000 }; points[3] = new WKSPointZ { X = 2600000, Y = 1200000, Z = 500 }; IRing ring = new RingClass(); ((IGeometry)ring).SpatialReference = lv95; GeometryUtils.MakeZAware(ring); GeometryUtils.SetWKSPointZs((IPointCollection4)ring, points); IMultiPatch multipatch = new MultiPatchClass(); ((IGeometry)multipatch).SpatialReference = lv95; GeometryUtils.MakeZAware(multipatch); GeometryUtils.MakeMAware(multipatch); GeometryUtils.MakePointIDAware(multipatch); GeometryFactory.AddRingToMultiPatch(ring, multipatch, esriMultiPatchRingType .esriMultiPatchOuterRing); var unReshaped = (IRing)((IGeometryCollection)multipatch).Geometry[0]; int originalPointCount = ((IPointCollection)unReshaped).PointCount; IPolyline cutLine = GeometryFactory.CreateLine( GeometryFactory.CreatePoint(2600075, 1200000 - 100, 222), GeometryFactory.CreatePoint(2600075, 1200000 + 100, 222)); cutLine.SpatialReference = lv95; GeometryUtils.MakeZAware(cutLine); var reshapePath = (IPath)((IGeometryCollection)cutLine).Geometry[0]; Assert.IsTrue(((ICurve3D)unReshaped).IsClosed3D); var reshapeInfo = new ReshapeInfo(multipatch, reshapePath, null) { NonPlanar = true }; IList <ReshapeInfo> singleReshapes; ReshapeUtils.ReshapeAllGeometryParts(reshapeInfo, reshapePath, out singleReshapes); var reshapedRing = (IRing)((IGeometryCollection)multipatch).Geometry[0]; Assert.AreEqual(originalPointCount + 1, ((IPointCollection)reshapedRing).PointCount); Assert.IsTrue(((ICurve3D)reshapedRing).IsClosed3D); double expectedLength = Math.Sqrt(50 * 50 + 500 * 500) * 1.5 + 75 + 250; Assert.AreEqual(expectedLength, ((ICurve3D)reshapedRing).Length3D, 0.001); var newPoints = new WKSPointZ[5]; GeometryUtils.QueryWKSPointZs((IPointCollection4)reshapedRing, newPoints); // first, fourth and last Assert.IsTrue(GeometryUtils.IsSamePoint(points[0], newPoints[0], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(points[2], newPoints[3], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(points[3], newPoints[4], 0, 0)); // the new cut points Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600075, Y = 1200000, Z = 500 }, newPoints[1], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600075, Y = 1200000, Z = 750 }, newPoints[2], 0, 0)); // And now reshape right through the vertex at the top, this time reshape the left cutLine = GeometryFactory.CreateLine( GeometryFactory.CreatePoint(2600050, 1200000 - 100, 222), GeometryFactory.CreatePoint(2600050, 1200000 + 100, 222)); cutLine.SpatialReference = lv95; GeometryUtils.MakeZAware(cutLine); reshapePath = (IPath)((IGeometryCollection)cutLine).Geometry[0]; reshapeInfo = new ReshapeInfo(multipatch, reshapePath, null) { NonPlanar = true }; // keep the right (small part) reshapeInfo.RingReshapeSide = RingReshapeSideOfLine.Right; ReshapeUtils.ReshapeAllGeometryParts(reshapeInfo, reshapePath, out singleReshapes); reshapedRing = (IRing)((IGeometryCollection)multipatch).Geometry[0]; Assert.AreEqual(5, ((IPointCollection)reshapedRing).PointCount); Assert.IsTrue(((ICurve3D)reshapedRing).IsClosed3D); expectedLength = Math.Sqrt(50 * 50 + 500 * 500) * 0.5 + 25 + 500 + 250; Assert.AreEqual(expectedLength, ((ICurve3D)reshapedRing).Length3D, 0.001); newPoints = new WKSPointZ[5]; GeometryUtils.QueryWKSPointZs((IPointCollection4)reshapedRing, newPoints); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600050, Y = 1200000, Z = 500 }, newPoints[0], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600075, Y = 1200000, Z = 500 }, newPoints[1], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600075, Y = 1200000, Z = 750 }, newPoints[2], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600050, Y = 1200000, Z = 1000 }, newPoints[3], 0, 0)); }
public void CanReshapeVerticalSquareRingInMultipatch() { ISpatialReference lv95 = SpatialReferenceUtils.CreateSpatialReference( WellKnownHorizontalCS.LV95); //IRing ring = GeometryFactory.CreateRing( // GeometryFactory.CreatePath()) var points = new WKSPointZ[5]; points[0] = new WKSPointZ { X = 2600000, Y = 1200000, Z = 500 }; points[1] = new WKSPointZ { X = 2600100, Y = 1200000, Z = 500 }; points[2] = new WKSPointZ { X = 2600100, Y = 1200000, Z = 1000 }; points[3] = new WKSPointZ { X = 2600000, Y = 1200000, Z = 1000 }; points[4] = new WKSPointZ { X = 2600000, Y = 1200000, Z = 500 }; IRing ring = new RingClass(); ((IGeometry)ring).SpatialReference = lv95; GeometryUtils.MakeZAware(ring); GeometryUtils.SetWKSPointZs((IPointCollection4)ring, points); IMultiPatch multipatch = new MultiPatchClass(); ((IGeometry)multipatch).SpatialReference = lv95; GeometryUtils.MakeZAware(multipatch); GeometryUtils.MakeMAware(multipatch); GeometryUtils.MakePointIDAware(multipatch); GeometryFactory.AddRingToMultiPatch(ring, multipatch, esriMultiPatchRingType .esriMultiPatchOuterRing); var unReshaped = (IRing)((IGeometryCollection)multipatch).Geometry[0]; int originalPointCount = ((IPointCollection)unReshaped).PointCount; // Left reshape is slightly larger -> vertical reshape side is determined by size only IPolyline cutLine = GeometryFactory.CreateLine( GeometryFactory.CreatePoint(2600051, 1200000 - 100, 222), GeometryFactory.CreatePoint(2600051, 1200000 + 100, 222)); cutLine.SpatialReference = lv95; GeometryUtils.MakeZAware(cutLine); var reshapePath = (IPath)((IGeometryCollection)cutLine).Geometry[0]; Assert.IsTrue(((ICurve3D)unReshaped).IsClosed3D); var reshapeInfo = new ReshapeInfo(multipatch, reshapePath, null) { NonPlanar = true }; IList <ReshapeInfo> singleReshapes; ReshapeUtils.ReshapeAllGeometryParts(reshapeInfo, reshapePath, out singleReshapes); var reshapedRing = (IRing)((IGeometryCollection)multipatch).Geometry[0]; Assert.AreEqual(originalPointCount, ((IPointCollection)reshapedRing).PointCount); Assert.IsTrue(((ICurve3D)reshapedRing).IsClosed3D); Assert.AreEqual(2 * 500 + 2 * 51, ((ICurve3D)reshapedRing).Length3D); var newPoints = new WKSPointZ[5]; GeometryUtils.QueryWKSPointZs((IPointCollection4)reshapedRing, newPoints); // first, fourth and last Assert.IsTrue(GeometryUtils.IsSamePoint(points[0], newPoints[0], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(points[3], newPoints[3], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(points[4], newPoints[4], 0, 0)); // the new cut points Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600051, Y = 1200000, Z = 500 }, newPoints[1], 0, 0)); Assert.IsTrue(GeometryUtils.IsSamePoint(new WKSPointZ { X = 2600051, Y = 1200000, Z = 1000 }, newPoints[2], 0, 0)); }