/// <summary> /// Generate a set of mesh faces that represent a delaunay triangulation in the XY plane of the /// specified set of vertices. /// Based on the algorithm described here: http://paulbourke.net/papers/triangulate/ /// </summary> /// <param name="vertices">The vertices to mesh between</param> /// <param name="faces">Optional. The face collection to which to add the triangles. /// If null or ommitted, a new MeshFaceCollection will be created.</param> /// <param name="bounds">The bounding box that contains the triangulation. Should encompass all vertices /// and, for later voronoi generation, any bounding geometry. If null, the bounding box of the vertices /// themselves will be used.</param> /// <param name="clean">Clean up construction Super Triangle. If true, any remaining fragments of the /// initial generating supertriangle will be removed from the output face list. Set this to false /// if planning on using this mesh for subsequent voronoi generation so that the edge cells can be extended.</param> /// <param name="outerVerts">Optional. If input and non-null, this collection will be populated with the exterior vertices - those connected /// to the original supertriangle. If 'clean' is false, this will instead return the supertriangle vertices.</param> public static MeshFaceCollection DelaunayTriangulationXY(VertexCollection vertices, MeshFaceCollection faces = null, BoundingBox bounds = null, bool clean = true, VertexCollection outerVerts = null) { List <Vertex> vertexList = vertices.ToList(); vertexList.Sort(); if (faces == null) { faces = new MeshFaceCollection(); } if (bounds == null) { bounds = new BoundingBox(vertexList); } else { bounds = new BoundingBox(bounds); } bounds.Scale(5); //Provide a little wriggle room! // Meshing starts with one 'super triangle' that encloses all vertices. // This will be removed at the end MeshFace superTriangle = DelaunayTriangle.GenerateSuperTriangleXY(bounds); faces.Add(superTriangle); // Include each vertex in the meshing one at a time foreach (Vertex v in vertexList) { //for (int k = 0; k < 8; k++) //{ // Vertex v = vertexList[k]; // if (k == 7) // { // bool bum = true; // } IList <MeshEdge> edges = new List <MeshEdge>(); //The edges of replaced triangles for (int i = faces.Count - 1; i >= 0; i--) { MeshFace face = faces[i]; if (face.XYCircumcircleContainmentQuickCheck(v)) //The vertex lies within the circumcircle of this face { //The edges of the triangle are added to the current edge set... for (int j = 0; j < face.Count; j++) { edges.Add(face.GetEdge(j)); } //...and the triangle is removed. faces.RemoveAt(i); } } //Remove duplicate edges to retain only the convex hull of edges. //edges.RemoveDuplicates(); //Replaced with bespoke version for (int i = edges.Count - 2; i >= 0; i--) { MeshEdge itemA = edges[i]; for (int j = edges.Count - 1; j > i; j--) { if (itemA.Equals(edges[j])) { edges.RemoveAt(j); edges.RemoveAt(i); j--; continue; } } } // Add triangle fan between all remaining edges and the new vertex foreach (MeshEdge edge in edges) { faces.Add(new DelaunayTriangle(edge, v)); } } // Extract outer vertices if (outerVerts != null) { if (clean) { var outerFaces = faces.AllWithVertices(new VertexCollection(superTriangle)); foreach (Vertex v in outerFaces.ExtractVertices()) { outerVerts.Add(v); } } else { foreach (Vertex v in superTriangle) { outerVerts.Add(v); } } } // Remove the super triangle and any triangles still attached to it if (clean) { faces.RemoveAllWithVertices(new VertexCollection(superTriangle)); } return(faces); }
public bool Equals(ref MeshEdge other) { return((Start == other.Start && End == other.End) || (Start == other.End && End == other.Start)); }