/// <summary> /// Gets the Voronoi diagram as raw output data. /// </summary> /// <param name="mesh"></param> /// <returns></returns> /// <remarks> /// The Voronoi diagram is the geometric dual of the Delaunay triangulation. /// Hence, the Voronoi vertices are listed by traversing the Delaunay /// triangles, and the Voronoi edges are listed by traversing the Delaunay /// edges. ///</remarks> private void Generate() { _TriangleNetMesh.Renumber(); _TriangleNetMesh.MakeVertexMap(); // Allocate space for voronoi diagram points = new Point[_TriangleNetMesh.triangles.Count + _TriangleNetMesh.hullsize]; regions = new Dictionary <int, VoronoiRegion>(_TriangleNetMesh.vertices.Count); rayPoints = new Dictionary <int, Point>(); rayIndex = 0; bounds = new Rectangle(); // Compute triangles circumcenters and setup bounding box ComputeCircumCenters(); // Add all Voronoi regions to the map. foreach (var vertex in _TriangleNetMesh.vertices.Values) { regions.Add(vertex.id, new VoronoiRegion(vertex)); } // Loop over the mesh vertices (Voronoi generators). foreach (var region in regions.Values) { //if (item.Boundary == 0) { ConstructCell(region); } } }
/// <summary> /// Computes the bounded voronoi diagram. /// </summary> private void Generate() { _TriangleNetMesh.Renumber(); _TriangleNetMesh.MakeVertexMap(); // Allocate space for voronoi diagram regions = new List <VoronoiRegion>(_TriangleNetMesh.vertices.Count); points = new Point[_TriangleNetMesh.triangles.Count]; segPoints = new List <Point>(_TriangleNetMesh.subsegs.Count * 4); ComputeCircumCenters(); TagBlindTriangles(); foreach (var v in _TriangleNetMesh.vertices.Values) { // TODO: Need a reliable way to check if a vertex is on a segment if (v.type == VertexType.FreeVertex || v.label == 0) { ConstructCell(v); } else if (includeBoundary) { ConstructBoundaryCell(v); } } // Add the new points on segments to the point array. int length = points.Length; Array.Resize <Point>(ref points, length + segPoints.Count); for (int i = 0; i < segPoints.Count; i++) { points[length + i] = segPoints[i]; } segPoints.Clear(); segPoints = null; }
public VertexCirculator(TriangleNetMesh triangleNetMesh) { triangleNetMesh.MakeVertexMap(); }
/// <summary> /// Test the mesh for topological consistency. /// </summary> public static bool IsConsistent(TriangleNetMesh triangleNetMesh) { Otri tri = default(Otri); Otri oppotri = default(Otri), oppooppotri = default(Otri); Vertex org, dest, apex; Vertex oppoorg, oppodest; var logger = Log.Instance; // Temporarily turn on exact arithmetic if it's off. bool saveexact = Behavior.NoExact; Behavior.NoExact = false; int horrors = 0; // Run through the list of triangles, checking each one. foreach (var t in triangleNetMesh.triangles) { tri.tri = t; // Check all three edges of the triangle. for (tri.orient = 0; tri.orient < 3; tri.orient++) { org = tri.Org(); dest = tri.Dest(); if (tri.orient == 0) { // Only test for inversion once. // Test if the triangle is flat or inverted. apex = tri.Apex(); if (predicates.CounterClockwise(org, dest, apex) <= 0.0) { if (Log.Verbose) { logger.Warning(String.Format("Triangle is flat or inverted (ID {0}).", t.id), "MeshValidator.IsConsistent()"); } horrors++; } } // Find the neighboring triangle on this edge. tri.Sym(ref oppotri); if (oppotri.tri.id != TriangleNetMesh.DUMMY) { // Check that the triangle's neighbor knows it's a neighbor. oppotri.Sym(ref oppooppotri); if ((tri.tri != oppooppotri.tri) || (tri.orient != oppooppotri.orient)) { if (tri.tri == oppooppotri.tri && Log.Verbose) { logger.Warning("Asymmetric triangle-triangle bond: (Right triangle, wrong orientation)", "MeshValidator.IsConsistent()"); } horrors++; } // Check that both triangles agree on the identities // of their shared vertices. oppoorg = oppotri.Org(); oppodest = oppotri.Dest(); if ((org != oppodest) || (dest != oppoorg)) { if (Log.Verbose) { logger.Warning("Mismatched edge coordinates between two triangles.", "MeshValidator.IsConsistent()"); } horrors++; } } } } // Check for unconnected vertices triangleNetMesh.MakeVertexMap(); foreach (var v in triangleNetMesh.vertices.Values) { if (v.tri.tri == null && Log.Verbose) { logger.Warning("Vertex (ID " + v.id + ") not connected to mesh (duplicate input vertex?)", "MeshValidator.IsConsistent()"); } } // Restore the status of exact arithmetic. Behavior.NoExact = saveexact; return(horrors == 0); }