示例#1
0
        public void FindFacePolygon()
        {
            var polygon  = new[] { new PointD(0, 0), new PointD(1, 1), new PointD(2, 0) };
            var division = Subdivision.FromPolygons(new PointD[][] { polygon });

            division.Validate();
            var face = division.Faces[1];

            // original sequence, any starting vertex
            Assert.AreSame(face, division.FindFace(new[] { polygon[0], polygon[1], polygon[2] }));
            Assert.AreSame(face, division.FindFace(new[] { polygon[1], polygon[2], polygon[0] }));
            Assert.AreSame(face, division.FindFace(new[] { polygon[2], polygon[0], polygon[1] }));

            // inverted sequence, any starting vertex
            Assert.AreSame(face, division.FindFace(new[] { polygon[2], polygon[1], polygon[0] }));
            Assert.AreSame(face, division.FindFace(new[] { polygon[0], polygon[2], polygon[1] }));
            Assert.AreSame(face, division.FindFace(new[] { polygon[1], polygon[0], polygon[2] }));

            // sequence including nonexistent point
            var point = new PointD(2, 1);

            Assert.IsNull(division.FindFace(new[] { point, polygon[1], polygon[2] }));
            Assert.IsNull(division.FindFace(new[] { polygon[0], point, polygon[2] }));
            Assert.IsNull(division.FindFace(new[] { polygon[0], polygon[1], point }));
        }
示例#2
0
        public void FindFacePoint()
        {
            var division = SubdivisionFromLines.CreateSquareStar(false);
            var faces    = division.Faces.Values;

            Assert.AreEqual(faces[0], division.FindFace(new PointD(-2, 0)));
            Assert.AreEqual(faces[1], division.FindFace(new PointD(-0.5, 0)));
            Assert.AreEqual(faces[2], division.FindFace(new PointD(0, 0.5)));
            Assert.AreEqual(faces[3], division.FindFace(new PointD(0.5, 0)));
            Assert.AreEqual(faces[4], division.FindFace(new PointD(0, -0.5)));

            // four nested triangles
            PointD[][] polygons =
            {
                new[] { new PointD(-8, -8), new PointD(0, 8), new PointD(8, -8) },
                new[] { new PointD(-6, -6), new PointD(0, 6), new PointD(6, -6) },
                new[] { new PointD(-4, -4), new PointD(0, 4), new PointD(4, -4) },
                new[] { new PointD(-2, -2), new PointD(0, 2), new PointD(2, -2) }
            };
            division = Subdivision.FromPolygons(polygons);
            division.Validate();
            faces = division.Faces.Values;

            Assert.AreEqual(faces[0], division.FindFace(new PointD(0, 10)));
            Assert.AreEqual(faces[1], division.FindFace(new PointD(0, 7)));
            Assert.AreEqual(faces[2], division.FindFace(new PointD(0, 5)));
            Assert.AreEqual(faces[3], division.FindFace(new PointD(0, 3)));
            Assert.AreEqual(faces[4], division.FindFace(new PointD(0, 1)));
        }
示例#3
0
        /// <summary>
        /// Converts all <see cref="VoronoiRegions"/> to a planar <see cref="Subdivision"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="SubdivisionMap"/> containing a new <see cref="Subdivision"/> whose bounded
        /// <see cref="Subdivision.Faces"/> correspond to the <see cref="VoronoiRegions"/> of the
        /// <see cref="VoronoiResults"/>.</returns>
        /// <remarks><para>
        /// The returned <see cref="SubdivisionMap"/> also provides a mapping between the zero-based
        /// indices of all <see cref="GeneratorSites"/> and <see cref="VoronoiRegions"/> and the
        /// corresponding <see cref="Subdivision.Faces"/>. This mapping will become invalid as soon
        /// as the created <see cref="Subdivision"/> is changed.
        /// </para><para>
        /// <b>ToVoronoiSubdivision</b> creates all <see cref="VoronoiRegions"/> if they have not
        /// yet been calculated. Call <see cref="ClearVoronoiRegions"/> if you no longer require
        /// this property after <b>ToVoronoiSubdivision</b> has returned.</para></remarks>

        public SubdivisionMap ToVoronoiSubdivision()
        {
            var division = Subdivision.FromPolygons(VoronoiRegions);

            int regionCount = VoronoiRegions.Length;

            Debug.Assert(GeneratorSites.Length == regionCount);
            Debug.Assert(division.Faces.Count == regionCount + 1);

            var faceToSite = new int[regionCount];
            var siteToFace = new SubdivisionFace[regionCount];

            // determine equivalence of faces and VoronoiRegions indices
            // (which are in turn equivalent to GeneratorSites indices)
            for (int i = 0; i < VoronoiRegions.Length; i++)
            {
                PointD[]        polygon = VoronoiRegions[i];
                SubdivisionFace face    = division.FindFace(polygon);

                // bounded faces start at creation index one
                faceToSite[face._key - 1] = i;
                siteToFace[i]             = face;
            }

            return(new SubdivisionMap(division, this, faceToSite, siteToFace));
        }
示例#4
0
        public void FromPolygonsSquare()
        {
            PointD[][] polygons =
            {
                new[] { new PointD(-1, -2), new PointD(-1, 2), new PointD(1, 2), new PointD(1, -2) }
            };
            var division = Subdivision.FromPolygons(polygons);

            division.Validate();

            var divisionPolygons = division.ToPolygons();

            Assert.AreEqual(polygons.Length, divisionPolygons.Length);
            CollectionAssert.AreEquivalent(polygons[0], divisionPolygons[0]);

            var edges = division.Edges.Values;
            var faces = division.Faces.Values;

            CollectionAssert.AreEqual(new[] {
                new VertexPair(polygons[0][0], edges[0]),
                new VertexPair(polygons[0][3], edges[5]),
                new VertexPair(polygons[0][1], edges[1]),
                new VertexPair(polygons[0][2], edges[3]),
            }, division.Vertices);

            CollectionAssert.AreEqual(new[] {
                new SubdivisionEdge(0, polygons[0][0], edges[1], faces[0], edges[2], edges[6]),
                new SubdivisionEdge(1, polygons[0][1], edges[0], faces[1], edges[7], edges[3]),
                new SubdivisionEdge(2, polygons[0][1], edges[3], faces[0], edges[4], edges[0]),
                new SubdivisionEdge(3, polygons[0][2], edges[2], faces[1], edges[1], edges[5]),
                new SubdivisionEdge(4, polygons[0][2], edges[5], faces[0], edges[6], edges[2]),
                new SubdivisionEdge(5, polygons[0][3], edges[4], faces[1], edges[3], edges[7]),
                new SubdivisionEdge(6, polygons[0][3], edges[7], faces[0], edges[0], edges[4]),
                new SubdivisionEdge(7, polygons[0][0], edges[6], faces[1], edges[5], edges[1]),
            }, edges);

            CollectionAssert.AreEqual(new[] {
                new SubdivisionFace(division, 0, null, new[] { edges[0] }),
                new SubdivisionFace(division, 1, edges[1], null),
            }, faces);

            CheckFace(edges[0], polygons[0], -8, PointD.Empty);
            Array.Reverse(polygons[0]);
            CheckFace(edges[5], polygons[0], +8, PointD.Empty);

            var cycles = division.GetZeroAreaCycles();

            Assert.AreEqual(0, cycles.Count);
        }
示例#5
0
        public void FromPolygonsDiamondEpsilon()
        {
            PointD[][] polygons =
            {
                new[] { new PointD(0,      -4), new PointD(-6,    0), new PointD(0,      4), new PointD(-3, 0) },
                new[] { new PointD(0.1,  -3.9), new PointD(-3,    0), new PointD(-0.1, 4.1), new PointD(3,  0) },
                new[] { new PointD(-0.1, -4.1), new PointD(2.9, 0.1), new PointD(0.1,  3.9), new PointD(6,  0) }
            };
            var division = Subdivision.FromPolygons(polygons, 0.2);

            division.Validate();

            var divisionPolygons = division.ToPolygons();

            Assert.AreEqual(polygons.Length, divisionPolygons.Length);
            CollectionAssert.AreEquivalent(polygons[0], divisionPolygons[0]);
            CollectionAssert.AreNotEquivalent(polygons[1], divisionPolygons[1]);
            CollectionAssert.AreNotEquivalent(polygons[2], divisionPolygons[2]);

            CheckPolygonsDiamond(polygons, division);
        }
示例#6
0
        public void LocateInFaceEpsilon()
        {
            var polygon  = new[] { new PointD(0, 0), new PointD(1, 1), new PointD(2, 0) };
            var division = Subdivision.FromPolygons(new PointD[][] { polygon });

            division.Validate();

            var edge = division.Faces[1].OuterEdge;

            Assert.AreEqual(PolygonLocation.Inside, edge.Locate(new PointD(1.0, 0.5), 0.2));

            Assert.AreEqual(PolygonLocation.Outside, edge.Locate(new PointD(1.0, -0.5), 0.2));
            Assert.AreEqual(PolygonLocation.Outside, edge.Locate(new PointD(0.0, 0.5), 0.2));
            Assert.AreEqual(PolygonLocation.Outside, edge.Locate(new PointD(2.0, 0.5), 0.2));

            Assert.AreEqual(PolygonLocation.Vertex, edge.Locate(new PointD(1.0, 0.9), 0.2));
            Assert.AreEqual(PolygonLocation.Vertex, edge.Locate(new PointD(0.0, 0.1), 0.2));
            Assert.AreEqual(PolygonLocation.Vertex, edge.Locate(new PointD(2.1, 0.0), 0.2));

            Assert.AreEqual(PolygonLocation.Edge, edge.Locate(new PointD(1.0, -0.1), 0.2));
            Assert.AreEqual(PolygonLocation.Edge, edge.Locate(new PointD(0.6, 0.5), 0.2));
            Assert.AreEqual(PolygonLocation.Edge, edge.Locate(new PointD(1.4, 0.5), 0.2));
        }
示例#7
0
        public void FromPolygonsTriforce()
        {
            PointD[][] polygons =
            {
                new[] { new PointD(-5, -4), new PointD(0,  6), new PointD(5, -4) },
                new[] { new PointD(0,   0), new PointD(-1, 2), new PointD(1,  2) }
            };
            var division = Subdivision.FromPolygons(polygons);

            division.Validate();

            var divisionPolygons = division.ToPolygons();

            Assert.AreEqual(polygons.Length, divisionPolygons.Length);
            CollectionAssert.AreEquivalent(polygons[0], divisionPolygons[0]);
            CollectionAssert.AreEquivalent(polygons[1], divisionPolygons[1]);

            var edges = division.Edges.Values;
            var faces = division.Faces.Values;

            CollectionAssert.AreEqual(new[] {
                new VertexPair(polygons[0][0], edges[0]),
                new VertexPair(polygons[0][2], edges[3]),
                new VertexPair(polygons[1][0], edges[6]),
                new VertexPair(polygons[1][1], edges[7]),
                new VertexPair(polygons[1][2], edges[9]),
                new VertexPair(polygons[0][1], edges[1]),
            }, division.Vertices);

            CollectionAssert.AreEqual(new[] {
                new SubdivisionEdge(0, polygons[0][0], edges[1], faces[0], edges[2], edges[4]),
                new SubdivisionEdge(1, polygons[0][1], edges[0], faces[1], edges[5], edges[3]),
                new SubdivisionEdge(2, polygons[0][1], edges[3], faces[0], edges[4], edges[0]),
                new SubdivisionEdge(3, polygons[0][2], edges[2], faces[1], edges[1], edges[5]),
                new SubdivisionEdge(4, polygons[0][2], edges[5], faces[0], edges[0], edges[2]),
                new SubdivisionEdge(5, polygons[0][0], edges[4], faces[1], edges[3], edges[1]),
                new SubdivisionEdge(6, polygons[1][0], edges[7], faces[1], edges[8], edges[10]),
                new SubdivisionEdge(7, polygons[1][1], edges[6], faces[2], edges[11], edges[9]),
                new SubdivisionEdge(8, polygons[1][1], edges[9], faces[1], edges[10], edges[6]),
                new SubdivisionEdge(9, polygons[1][2], edges[8], faces[2], edges[7], edges[11]),
                new SubdivisionEdge(10, polygons[1][2], edges[11], faces[1], edges[6], edges[8]),
                new SubdivisionEdge(11, polygons[1][0], edges[10], faces[2], edges[9], edges[7]),
            }, edges);

            CollectionAssert.AreEqual(new[] {
                new SubdivisionFace(division, 0, null, new[] { edges[0] }),
                new SubdivisionFace(division, 1, edges[1], new[] { edges[6] }),
                new SubdivisionFace(division, 2, edges[7], null),
            }, faces);

            PointD centroid = new PointD(0, -2 / 3.0);

            CheckFace(edges[0], polygons[0], -50, centroid);
            Array.Reverse(polygons[0]);
            CheckFace(edges[3], polygons[0], +50, centroid);

            centroid = new PointD(0, 4 / 3.0);
            CheckFace(edges[6], polygons[1], -2, centroid);
            Array.Reverse(polygons[1]);
            CheckFace(edges[9], polygons[1], +2, centroid);

            var cycles = division.GetZeroAreaCycles();

            Assert.AreEqual(0, cycles.Count);
        }