Ejemplo n.º 1
0
        private static IEnumerable <List <IRing> > GetPolygons([NotNull] IMultiPatch multipatch,
                                                               [NotNull] GeometryPart part)
        {
            var result = new Dictionary <IRing, List <IRing> >();

            foreach (IRing ring in part.LowLevelGeometries.Cast <IRing>())
            {
                bool beginning = false;
                esriMultiPatchRingType type = multipatch.GetRingType(ring, ref beginning);

                if (type != esriMultiPatchRingType.esriMultiPatchInnerRing)
                {
                    result.Add(ring, new List <IRing>());
                }
                else
                {
                    IRing outerRing = multipatch.FindBeginningRing(ring);

                    Assert.True(result.ContainsKey(outerRing),
                                "No outer ring found for inner ring.");

                    result[outerRing].Add(ring);
                }
            }

            foreach (KeyValuePair <IRing, List <IRing> > keyValuePair in result)
            {
                List <IRing> polygonRings = keyValuePair.Value;

                polygonRings.Insert(0, keyValuePair.Key);

                yield return(polygonRings);
            }
        }
Ejemplo n.º 2
0
        public static RingGroup CreateRingGroup([NotNull] GeometryPart part)
        {
            RingGroup result = CreateRingGroup(
                Assert.NotNull(part.MainOuterRing),
                part.InnerRings.Cast <IRing>().ToList());

            return(result);
        }
Ejemplo n.º 3
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();
                }
            }
        }
Ejemplo n.º 4
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.º 5
0
        public override int FromBytes(byte[] _FromBytes, int _Head)
        {
            int Head = _Head;

            Head += base.FromBytes(_FromBytes, Head);

            GeometryParts = new List <GeometryPart>();

            Convert.BytesToValue(out ParentID, _FromBytes, ref Head);
            Convert.BytesToValue(out MetadataID, _FromBytes, ref Head);

            Convert.BytesToValue(out int Size, _FromBytes, ref Head);

            for (int i = 0; i < Size; ++i)
            {
                var NewPart = new GeometryPart();
                Convert.BytesToValue(out NewPart.GeometryID, _FromBytes, ref Head);

                NewPart.Location = Vector3D.FromBytes(_FromBytes, ref Head);
                NewPart.Rotation = Vector3D.FromBytes(_FromBytes, ref Head);
                NewPart.Scale    = Vector3D.FromBytes(_FromBytes, ref Head);
                NewPart.Color    = Color.FromBytes(_FromBytes, ref Head);

                GeometryParts.Add(NewPart);
            }

            Convert.BytesToValue(out Size, _FromBytes, ref Head);
            ChildNodes = new List <ulong>();
            for (int i = 0; i < Size; ++i)
            {
                Convert.BytesToValue(out ulong NewChild, _FromBytes, ref Head);
                ChildNodes.Add(NewChild);
            }

            return(Head - _Head);
        }
Ejemplo n.º 6
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);
        }