Ejemplo n.º 1
0
        public byte[] WriteMultipatch([NotNull] IMultiPatch multipatch,
                                      bool groupPartsByPointIDs = false)
        {
            Assert.True(GeometryUtils.IsRingBasedMultipatch(multipatch),
                        "Unsupported (non-ring-based) multipatch.");

            // TODO: Initialize with the proper size or allow providing the actual byte[]
            MemoryStream memoryStream = InitializeWriter();

            Ordinates ordinates = GetOrdinatesDimension(multipatch);

            WriteWkbType(WkbGeometryType.MultiSurface, ordinates);

            var geometryParts =
                GeometryPart.FromGeometry(multipatch, groupPartsByPointIDs).ToList();

            Writer.Write(geometryParts.Count);

            foreach (GeometryPart part in geometryParts)
            {
                WriteWkbType(WkbGeometryType.PolyhedralSurface, ordinates);

                List <List <IRing> > polygonGroup = GetPolygons(multipatch, part).ToList();

                Writer.Write(polygonGroup.Count);

                foreach (List <IRing> rings in polygonGroup)
                {
                    WriteWkbType(WkbGeometryType.Polygon, ordinates);

                    WriteLineStringsCore(GetAsPointList(rings).ToList(), ordinates);
                }
            }

            return(memoryStream.ToArray());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Cuts the provided multipatch along the specified cutLine.
        /// </summary>
        /// <param name="multipatch"></param>
        /// <param name="cutLine"></param>
        /// <param name="zSource">The source of the Z values to be used for the new vertices of the result features.</param>
        /// <param name="usedCutLine">The cut result containing information about the cut operation.</param>
        /// <param name="nonSimpleFootprintAction">The action to be performed if one of the result multipatches
        /// has a degenerate footprint (because it is a sliver polygon with sub-tolerance self intersections).</param>
        /// <returns></returns>
        public static IDictionary <IPolygon, IMultiPatch> TryCut(
            [NotNull] IMultiPatch multipatch,
            [NotNull] IPolyline cutLine,
            ChangeAlongZSource zSource,
            [CanBeNull] CutPolyline usedCutLine = null,
            DegenerateMultipatchFootprintAction nonSimpleFootprintAction =
            DegenerateMultipatchFootprintAction.Throw)
        {
            Assert.ArgumentNotNull(multipatch, nameof(multipatch));
            Assert.ArgumentNotNull(cutLine, nameof(cutLine));

            bool allRings = GeometryUtils.IsRingBasedMultipatch(multipatch);

            Assert.True(allRings,
                        "The multipatch geometry contains triangles, triangle fans or triangle strips, which are currently not supported");

            // NOTE: ITopologicalOperator4 is not supported by multipatch, ITopologicalOperator3.Cut returns non-Z-aware polygons
            // -> Use GeomUtils.Cut implementation which could eventually classify the left/right parts and avoid footprint-cutting
            //    only to find the correct assignment to result features.

            // TODO: Create footprint as RingGroups directly from multipatch rings
            IPolygon footprint = GeometryFactory.CreatePolygon(multipatch);

            IList <IGeometry> cutFootprintParts =
                TryCutRingGroups(footprint, cutLine, ChangeAlongZSource.Target);

            if (cutFootprintParts == null || cutFootprintParts.Count == 0)
            {
                _msg.DebugFormat(
                    "Not even the footprint could be cut. No multipatch cutting performed.");
                if (usedCutLine != null)
                {
                    usedCutLine.Polyline      = cutLine;
                    usedCutLine.SuccessfulCut = false;
                }

                return(new Dictionary <IPolygon, IMultiPatch>(0));
            }

            // Get the 'connected components', i.e. outer ring with respective inner rings.
            IList <GeometryPart> multipatchParts =
                GeometryPart.FromGeometry(multipatch).ToList();

            Dictionary <RingGroup, List <RingGroup> > splitPartsByFootprintPart =
                PrepareSplitPartsDictionary(cutFootprintParts);

            foreach (GeometryPart part in multipatchParts)
            {
                CutAndAssignToFootprintParts(part, cutLine, splitPartsByFootprintPart,
                                             zSource);
            }

            // make a separate multipatch per footprint-part with all respective ring-groups
            Dictionary <IPolygon, IMultiPatch> result = BuildResultMultipatches(
                multipatch, splitPartsByFootprintPart, nonSimpleFootprintAction);

            if (usedCutLine != null && splitPartsByFootprintPart.Values.Count > 1)
            {
                // TODO: Extract actual cutLine from inBound/outBound intersections
                usedCutLine.Polyline      = cutLine;
                usedCutLine.SuccessfulCut = false;
            }

            return(result);
        }