Exemplo n.º 1
0
        public void CreateLinkedGeo()
        {
            var polygon = new LinkedGeoPolygon();

            var loop = polygon.AddNewLinkedLoop();

            Assert.IsNotNull(loop);
            var coord = loop.AddLinkedCoord(Vertex1);

            Assert.IsNotNull(coord);
            coord = loop.AddLinkedCoord(Vertex2);
            Assert.IsNotNull(coord);
            coord = loop.AddLinkedCoord(Vertex3);
            Assert.IsNotNull(coord);

            loop = polygon.AddNewLinkedLoop();
            Assert.IsNotNull(loop);
            coord = loop.AddLinkedCoord(Vertex2);
            Assert.IsNotNull(coord);
            coord = loop.AddLinkedCoord(Vertex4);
            Assert.IsNotNull(coord);

            Assert.AreEqual(1, polygon.CountPolygons);
            Assert.AreEqual(2, polygon.CountLoops);
            Assert.AreEqual(3, polygon.First.Count);
            Assert.AreEqual(2, polygon.Last.Count);

            var nextPolygon = polygon.AddNewLinkedGeoPolygon();

            Assert.IsNotNull(nextPolygon);
            Assert.AreEqual(2, polygon.CountPolygons);

            polygon.Clear();
        }
Exemplo n.º 2
0
        public void NormalizeMultiPolygonAlreadyNormalized()
        {
            var verts1 = MakeGeoCoordArray(new  decimal[, ] {
                { 0, 0 }, { 0, 1 }, { 1, 1 }
            });
            var outer1 = CreateLinkedLoop(verts1);

            var verts2 = MakeGeoCoordArray(new  decimal[, ] {
                { 2, 2 }, { 2, 3 }, { 3, 3 }
            });
            var outer2 = CreateLinkedLoop(verts2);

            var polygon = new LinkedGeoPolygon();

            polygon.AddLinkedLoop(outer1);
            var next = polygon.AddNewLinkedGeoPolygon();

            next.AddLinkedLoop(outer2);

            // Should be a no-op
            int result;

            (result, polygon) = polygon.NormalizeMultiPolygon();

            Assert.AreEqual(H3Lib.Constants.LinkedGeo.NormalizationErrMultiplePolygons, result);

            Assert.AreEqual(2, polygon.CountPolygons);
            Assert.AreEqual(1, polygon.CountLoops);

            Assert.IsNotNull(polygon.Loops.First());
            Assert.AreEqual(outer1, polygon.Loops.First());

            Assert.AreEqual(1, polygon.Next.CountLoops);
            Assert.IsNotNull(polygon.Next.Loops.First());
            Assert.AreEqual(outer2, polygon.Next.Loops.First());

            polygon.Clear();
        }
        /// <summary>
        /// Normalize a LinkedGeoPolygon in-place into a structure following GeoJSON
        /// MultiPolygon rules: Each polygon must have exactly one outer loop, which
        /// must be first in the list, followed by any holes. Holes in this algorithm
        /// are identified by winding order (holes are clockwise), which is guaranteed
        /// by the h3SetToVertexGraph algorithm.
        ///
        /// Input to this function is assumed to be a single polygon including all
        /// loops to normalize. It's assumed that a valid arrangement is possible.
        /// </summary>
        /// <param name="root">Root polygon including all loops</param>
        /// <returns>
        /// Tuple
        /// Item1 - 0 on success, or an error code > 0 for invalid input
        /// Item2 - Normalized LinkedGeoPolygon
        /// </returns>
        /// <!--
        /// linkedGeo.c
        /// int normalizeMultiPolygon
        /// -->
        public static (int, LinkedGeoPolygon) NormalizeMultiPolygon(this LinkedGeoPolygon root)
        {
            // We assume that the input is a single polygon with loops;
            // if it has multiple polygons, don't touch it
            if (root.Next != null)
            {
                //  TODO: Check the constant location and update
                return(Constants.LinkedGeo.NormalizationErrMultiplePolygons, root);
            }

            // Count loops, exiting early if there's only one
            int loopCount = root.CountLoops;

            if (loopCount <= 1)
            {
                return(Constants.LinkedGeo.NormalizationSuccess, root);
            }

            int resultCode           = Constants.LinkedGeo.NormalizationSuccess;
            LinkedGeoPolygon polygon = null;
            var innerCount           = 0;
            var outerCount           = 0;


            // Create an array to hold all of the inner loops. Note that
            // this array will never be full, as there will always be fewer
            // inner loops than outer loops.
            var innerLoops = new List <LinkedGeoLoop>();
            // Create an array to hold the bounding boxes for the outer loops
            var bboxes = new List <BBox>();

            // Get the first loop and unlink it from root
            var testLoops = root.Loops;//.GeoLoopList.First;

            root = new LinkedGeoPolygon();

            foreach (var geoLoop in testLoops)
            {
                if (geoLoop.IsClockwise())
                {
                    innerLoops.Add(geoLoop);
                    innerCount++;
                }
                else
                {
                    polygon = polygon == null
                                  ? root
                                  : polygon.AddNewLinkedGeoPolygon();
                    polygon.AddLinkedLoop(geoLoop);
                    bboxes.Add(geoLoop.ToBBox());
                    outerCount++;
                }
            }

            // Find polygon for each inner loop and assign the hole to it
            for (var i = 0; i < innerCount; i++)
            {
                polygon = innerLoops[i].FindPolygonForHole(root, bboxes, outerCount);
                if (polygon != null)
                {
                    polygon.AddLinkedLoop(innerLoops[i]);
                }
                else
                {
                    // If we can't find a polygon (possible with invalid input), then
                    // we need to release the memory for the hole, because the loop has
                    // been unlinked from the root and the caller will no longer have
                    // a way to destroy it with destroyLinkedPolygon.
                    innerLoops[i].Clear();
                    resultCode = Constants.LinkedGeo.NormalizationErrUnassignedHoles;
                }
            }
            // Free allocated memory
            innerLoops.Clear();
            bboxes.Clear();

            return(resultCode, root);
        }