public static Voronoi FromDelaunay(Adjacency adjacency) { Voronoi v = new Voronoi(); int[] triangleRemapping = new int[adjacency.triangles.Count]; for (int i = 0; i < adjacency.triangles.Count; i++) { Adjacency.Triangle t = adjacency.triangles[i]; if (!t.valid) { triangleRemapping[i] = -1; continue; } Vertex c; float r; t.CircumCircle(adjacency.vertices, out c, out r); triangleRemapping[i] = v.vertices.Count; v.vertices.Add(c); } for (int i = 0; i < adjacency.triangles.Count; i++) { Adjacency.Triangle t = adjacency.triangles[i]; if (!t.valid) { continue; } for (int e = 0; e < 3; e++) { int adjT = adjacency.AdjacentTriangle(i, e); if (adjT < 0 || adjacency.triangles[adjT].valid == false) { continue; } if (triangleRemapping[adjT] < 0) { continue; // already processed } int voronoiV0 = triangleRemapping[i]; int voronoiV1 = triangleRemapping[adjT]; Debug.Assert(voronoiV0 >= 0 && voronoiV1 >= 0); // the 2 vertices shared by the adjacent triangles will become // the voronoi cells divided by the edge we're creating int cellA = adjacency.edges[Math.Abs(t.edges[e]) - 1].vertices[0]; int cellB = adjacency.edges[Math.Abs(t.edges[e]) - 1].vertices[1]; v.edges.Add(new Edge(voronoiV0, voronoiV1, cellA, cellB)); } triangleRemapping[i] = -1; } return(v); }
public static Voronoi FromDelaunay(Adjacency adjacency) { Voronoi v = new Voronoi(); int[] triangleRemapping = new int[adjacency.triangles.Count]; for (int i = 0; i < adjacency.triangles.Count; i++) { Adjacency.Triangle t = adjacency.triangles[i]; if (!t.valid) { triangleRemapping[i] = -1; continue; } Vertex c; float r; t.CircumCircle( adjacency.vertices, out c, out r); triangleRemapping[i] = v.vertices.Count; v.vertices.Add(c); } for (int i = 0; i < adjacency.triangles.Count; i++) { Adjacency.Triangle t = adjacency.triangles[i]; if (!t.valid) { continue; } for (int e = 0; e < 3; e++) { int adjT = adjacency.AdjacentTriangle(i, e); if (adjT < 0 || adjacency.triangles[adjT].valid == false) continue; if (triangleRemapping[adjT] < 0) continue; // already processed int voronoiV0 = triangleRemapping[i]; int voronoiV1 = triangleRemapping[adjT]; Debug.Assert(voronoiV0 >= 0 && voronoiV1 >= 0); // the 2 vertices shared by the adjacent triangles will become // the voronoi cells divided by the edge we're creating int cellA = adjacency.edges[Math.Abs(t.edges[e]) - 1].vertices[0]; int cellB = adjacency.edges[Math.Abs(t.edges[e]) - 1].vertices[1]; v.edges.Add(new Edge(voronoiV0, voronoiV1, cellA, cellB)); } triangleRemapping[i] = -1; } return v; }
private static bool Delaunay2DInsertPoints(List<Vertex> vertices, Adjacency adjacency) { // Insert points HashSet<int> toCheck = new HashSet<int>(); for (int i = 0; i < vertices.Count; i++) { // Insert Vi Vertex Vi = vertices[i]; bool skip = false; for (int j = 0; j < adjacency.vertices.Count; j++) { if ((Vi - adjacency.vertices[j]).Length() <= COINCIDENT_POINTS_DISTANCE_EPSILON) { // the point has already been inserted. Skip it skip = true; break; } } if (skip) { continue; } if (OnDelaunayInsertPoint != null) OnDelaunayInsertPoint(adjacency, Vi); int tri = adjacency.PointInTriangle(Vi); if (tri < 0) { Debug.Assert(false); return false; } // check whether the point lies exactly on one edge of the triangle int edgeIdx = adjacency.PointInTriangleEdge(Vi, tri); if (edgeIdx >= 0) { // split the edge by Vi int[] result; adjacency.SplitEdge(edgeIdx, Vi, out result); for (int j = 0; j < 4; j++) { if (result[j] >= 0) { toCheck.Add(result[j]); } } } else { // split the triangle in 3 int[] result; adjacency.SplitTriangle(tri, Vi, out result); for (int j = 0; j < 3; j++) { toCheck.Add(result[j]); } } while (toCheck.Count > 0) { int t = toCheck.Last<int>(); toCheck.Remove(t); Adjacency.Triangle triangle = adjacency.triangles[t]; if (!triangle.valid) { continue; } if (OnDelaunayTriangleCheck != null) OnDelaunayTriangleCheck(adjacency, t); // check Delaunay condition for (int e = 0; e < 3; e++) { if (!adjacency.triangles[t].valid) continue; int adjacentIdx = adjacency.AdjacentTriangle(t, e); if (adjacentIdx < 0) { continue; } int globalEdgeIndex = Math.Abs(triangle.edges[e]) - 1; Adjacency.Triangle adjacent = adjacency.triangles[adjacentIdx]; if (!adjacent.valid) { continue; } Debug.Assert(adjacent.valid); int edgeFromAdjacent = adjacent.LocalEdgeIndex(globalEdgeIndex); Debug.Assert(edgeFromAdjacent >= 0); int v = adjacency.VertexOutOfTriEdge(adjacentIdx, edgeFromAdjacent); Debug.Assert(v >= 0); Debug.Assert(!triangle.Contains(v)); if (triangle.InsideCircumcircle(adjacency.vertices[v], adjacency.vertices) > INSIDE_CIRCUMCIRCLE_EPSILON) { int[] result; if (adjacency.FlipTriangles(t, adjacentIdx, out result)) { toCheck.Add(result[0]); toCheck.Add(result[1]); //break; } } } } if (OnDelaunayStep != null) OnDelaunayStep(adjacency); } return true; }
private static bool Delaunay2DInsertPoints(List <Vertex> vertices, Adjacency adjacency) { // Insert points HashSet <int> toCheck = new HashSet <int>(); for (int i = 0; i < vertices.Count; i++) { // Insert Vi Vertex Vi = vertices[i]; bool skip = false; for (int j = 0; j < adjacency.vertices.Count; j++) { if ((Vi - adjacency.vertices[j]).Length() <= COINCIDENT_POINTS_DISTANCE_EPSILON) { // the point has already been inserted. Skip it skip = true; break; } } if (skip) { continue; } if (OnDelaunayInsertPoint != null) { OnDelaunayInsertPoint(adjacency, Vi); } int tri = adjacency.PointInTriangle(Vi); if (tri < 0) { Debug.Assert(false); return(false); } // check whether the point lies exactly on one edge of the triangle int edgeIdx = adjacency.PointInTriangleEdge(Vi, tri); if (edgeIdx >= 0) { // split the edge by Vi int[] result; adjacency.SplitEdge(edgeIdx, Vi, out result); for (int j = 0; j < 4; j++) { if (result[j] >= 0) { toCheck.Add(result[j]); } } } else { // split the triangle in 3 int[] result; adjacency.SplitTriangle(tri, Vi, out result); for (int j = 0; j < 3; j++) { toCheck.Add(result[j]); } } while (toCheck.Count > 0) { int t = toCheck.Last <int>(); toCheck.Remove(t); Adjacency.Triangle triangle = adjacency.triangles[t]; if (!triangle.valid) { continue; } if (OnDelaunayTriangleCheck != null) { OnDelaunayTriangleCheck(adjacency, t); } // check Delaunay condition for (int e = 0; e < 3; e++) { if (!adjacency.triangles[t].valid) { continue; } int adjacentIdx = adjacency.AdjacentTriangle(t, e); if (adjacentIdx < 0) { continue; } int globalEdgeIndex = Math.Abs(triangle.edges[e]) - 1; Adjacency.Triangle adjacent = adjacency.triangles[adjacentIdx]; if (!adjacent.valid) { continue; } Debug.Assert(adjacent.valid); int edgeFromAdjacent = adjacent.LocalEdgeIndex(globalEdgeIndex); Debug.Assert(edgeFromAdjacent >= 0); int v = adjacency.VertexOutOfTriEdge(adjacentIdx, edgeFromAdjacent); Debug.Assert(v >= 0); Debug.Assert(!triangle.Contains(v)); if (triangle.InsideCircumcircle(adjacency.vertices[v], adjacency.vertices) > INSIDE_CIRCUMCIRCLE_EPSILON) { int[] result; if (adjacency.FlipTriangles(t, adjacentIdx, out result)) { toCheck.Add(result[0]); toCheck.Add(result[1]); //break; } } } } if (OnDelaunayStep != null) { OnDelaunayStep(adjacency); } } return(true); }