Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
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);
            }
        }
Ejemplo n.º 3
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);
        }