예제 #1
0
        private static IList <IGeometry> TryCutRingGroups(
            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

            var existingFeature = new List <IPolygon>();
            var newFeatures     = new List <IPolygon>();

            var cutResultsPerConnectedComponent =
                TryCutConnectedComponents(inputPolygon, cutPolyline, zSource);

            foreach (IList <RingGroup> cutRingGroups in cutResultsPerConnectedComponent)
            {
                IRing ringTemplate = GeometryFactory.CreateEmptyRing(inputPolygon);

                var cutResults =
                    cutRingGroups.Select(
                        rg =>
                        GeometryConversionUtils.CreatePolygon(
                            inputPolygon, ringTemplate, rg))
                    .ToList();

                var largest = GeometryUtils.GetLargestGeometry(cutResults);

                foreach (IPolygon cutComponent in cutResults)
                {
                    if (cutComponent == largest)
                    {
                        existingFeature.Add(cutComponent);
                    }
                    else
                    {
                        newFeatures.Add(cutComponent);
                    }
                }
            }

            if (newFeatures.Count == 0)
            {
                // no cut happened:
                return(null);
            }

            var result = new List <IGeometry>
            {
                GeometryUtils.Union(existingFeature)
            };

            result.AddRange(newFeatures.Cast <IGeometry>());

            return(result);
        }
예제 #2
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);
        }
예제 #3
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);
        }