Esempio n. 1
0
        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))));
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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))));
        }
Esempio n. 4
0
        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();
                }
            }
        }
Esempio n. 5
0
        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));
            }
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        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);
            }
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        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);
        }
Esempio n. 13
0
        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))));
        }
Esempio n. 14
0
        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);
        }