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 })); }
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))); }
/// <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)); }
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); }
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); }
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)); }
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); }