/// <summary> /// Generate the Voronoi diagram from given triangle mesh.. /// </summary> /// <param name="mesh"></param> /// <param name="bounded"></param> protected void Generate(Mesh mesh) { mesh.Renumber(); base.edges = new List<HalfEdge>(); this.rays = new List<HalfEdge>(); // Allocate space for Voronoi diagram. var vertices = new Vertex[mesh.triangles.Count + mesh.hullsize]; var faces = new Face[mesh.vertices.Count]; if (factory == null) { factory = new DefaultVoronoiFactory(); } factory.Initialize(vertices.Length, 2 * mesh.NumberOfEdges, faces.Length); // Compute triangles circumcenters. var map = ComputeVertices(mesh, vertices); // Create all Voronoi faces. foreach (var vertex in mesh.vertices.Values) { faces[vertex.id] = factory.CreateFace(vertex); } ComputeEdges(mesh, vertices, faces, map); // At this point all edges are computed, but the (edge.next) pointers aren't set. ConnectEdges(map); base.vertices = new List<Vertex>(vertices); base.faces = new List<Face>(faces); }
public GameObject voronoiFaceToGO(TriangleNet.Topology.DCEL.Face face) { GameObject cell; if (face.Bounded) { cell = new GameObject("FaceID: " + face.ID); MeshFilter mFilter = cell.AddComponent <MeshFilter>(); MeshRenderer mRender = cell.AddComponent <MeshRenderer>(); mRender.material = new Material(Shader.Find("Diffuse")); mRender.material.color = new Color(1f, 1f, 1f); List <Vertex> vertices = new List <Vertex>(); foreach (TriangleNet.Topology.DCEL.HalfEdge he in face.EnumerateEdges()) { Vertex v = new Vertex(he.Origin.X, he.Origin.Y); vertices.Add(v); } SweepLine sl = new SweepLine(); TriangleNet.Configuration conf = new TriangleNet.Configuration(); TriangleNet.Mesh tMeshCell = (TriangleNet.Mesh)sl.Triangulate(vertices, conf); mFilter.mesh = OsgiViz.Helperfunctions.convertTriangleNETMesh(tMeshCell); } else { cell = new GameObject("unbounded cell"); } return(cell); }
/// <summary> /// Compute the edges of the Voronoi diagram. /// </summary> /// <param name="mesh"></param> /// <param name="vertices"></param> /// <param name="faces"></param> /// <param name="map">Empty vertex map.</param> protected void ComputeEdges(Mesh mesh, Vertex[] vertices, Face[] faces, List<HalfEdge>[] map) { Otri tri, neighbor = default(Otri); TriangleNet.Geometry.Vertex org, dest; double px, py; int id, nid, count = mesh.triangles.Count; Face face, neighborFace; HalfEdge edge, twin; Vertex vertex, end; // Count infinte edges (vertex id for their endpoints). int j = 0; // Count half-edges (edge ids). int k = 0; // To loop over the set of edges, loop over all triangles, and look at the // three edges of each triangle. If there isn't another triangle adjacent // to the edge, operate on the edge. If there is another adjacent triangle, // operate on the edge only if the current triangle has a smaller id than // its neighbor. This way, each edge is considered only once. foreach (var t in mesh.triangles) { id = t.id; tri.tri = t; for (int i = 0; i < 3; i++) { tri.orient = i; tri.Sym(ref neighbor); nid = neighbor.tri.id; if (id < nid || nid < 0) { // Get the endpoints of the current triangle edge. org = tri.Org(); dest = tri.Dest(); face = faces[org.id]; neighborFace = faces[dest.id]; vertex = vertices[id]; // For each edge in the triangle mesh, there's a corresponding edge // in the Voronoi diagram, i.e. two half-edges will be created. if (nid < 0) { // Unbounded edge, direction perpendicular to the boundary edge, // pointing outwards. px = dest.y - org.y; py = org.x - dest.x; end = factory.CreateVertex(vertex.x + px, vertex.y + py); end.id = count + j++; vertices[end.id] = end; edge = factory.CreateHalfEdge(end, face); twin = factory.CreateHalfEdge(vertex, neighborFace); // Make (face.edge) always point to an edge that starts at an infinite // vertex. This will allow traversing of unbounded faces. face.edge = edge; face.bounded = false; map[id].Add(twin); rays.Add(twin); } else { end = vertices[nid]; // Create half-edges. edge = factory.CreateHalfEdge(end, face); twin = factory.CreateHalfEdge(vertex, neighborFace); // Add to vertex map. map[nid].Add(edge); map[id].Add(twin); } vertex.leaving = twin; end.leaving = edge; edge.twin = twin; twin.twin = edge; edge.id = k++; twin.id = k++; this.edges.Add(edge); this.edges.Add(twin); } } } }
public static DcelMesh ToDCEL(Mesh mesh) { var dcel = new DcelMesh(); var vertices = new HVertex[mesh.vertices.Count]; var faces = new Face[mesh.triangles.Count]; dcel.HalfEdges.Capacity = 2 * mesh.NumberOfEdges; mesh.Renumber(); HVertex vertex; foreach (var v in mesh.vertices.Values) { vertex = new HVertex(v.x, v.y); vertex.id = v.id; vertex.label = v.label; vertices[v.id] = vertex; } // Maps a triangle to its 3 edges (used to set next pointers). var map = new List<HalfEdge>[mesh.triangles.Count]; Face face; foreach (var t in mesh.triangles) { face = new Face(null); face.id = t.id; faces[t.id] = face; map[t.id] = new List<HalfEdge>(3); } Otri tri = default(Otri), neighbor = default(Otri); TriangleNet.Geometry.Vertex org, dest; int id, nid, count = mesh.triangles.Count; HalfEdge edge, twin, next; var edges = dcel.HalfEdges; // Count half-edges (edge ids). int k = 0; // Maps a vertex to its leaving boundary edge. var boundary = new Dictionary<int, HalfEdge>(); foreach (var t in mesh.triangles) { id = t.id; tri.tri = t; for (int i = 0; i < 3; i++) { tri.orient = i; tri.Sym(ref neighbor); nid = neighbor.tri.id; if (id < nid || nid < 0) { face = faces[id]; // Get the endpoints of the current triangle edge. org = tri.Org(); dest = tri.Dest(); // Create half-edges. edge = new HalfEdge(vertices[org.id], face); twin = new HalfEdge(vertices[dest.id], nid < 0 ? Face.Empty : faces[nid]); map[id].Add(edge); if (nid >= 0) { map[nid].Add(twin); } else { boundary.Add(dest.id, twin); } // Set leaving edges. edge.origin.leaving = edge; twin.origin.leaving = twin; // Set twin edges. edge.twin = twin; twin.twin = edge; edge.id = k++; twin.id = k++; edges.Add(edge); edges.Add(twin); } } } // Set next pointers for each triangle face. foreach (var t in map) { edge = t[0]; next = t[1]; if (edge.twin.origin.id == next.origin.id) { edge.next = next; next.next = t[2]; t[2].next = edge; } else { edge.next = t[2]; next.next = edge; t[2].next = next; } } // Resolve boundary edges. foreach (var e in boundary.Values) { e.next = boundary[e.twin.origin.id]; } dcel.Vertices.AddRange(vertices); dcel.Faces.AddRange(faces); return dcel; }
static Face() { Empty = new Face(null); Empty.id = -1; }
/// <summary> /// Calculate the centroid of a polygon. /// </summary> private void Centroid(Face face, out double x, out double y) { double ai, atmp = 0, xtmp = 0, ytmp = 0; var edge = face.Edge; var first = edge.Next.ID; Point p, q; do { p = edge.Origin; q = edge.Twin.Origin; ai = p.x * q.y - q.x * p.y; atmp += ai; xtmp += (q.x + p.x) * ai; ytmp += (q.y + p.y) * ai; edge = edge.Next; } while (edge.Next.ID != first); x = xtmp / (3 * atmp); y = ytmp / (3 * atmp); //area = atmp / 2; }
static Face() { Empty = new Face(null); Empty.id = -1; }
public HalfEdge CreateHalfEdge(Vertex origin, Face face) { return new HalfEdge(origin, face); }