Example #1
0
        /// <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);
        }
Example #2
0
 public bool Equals(ref MeshEdge other)
 {
     return((Start == other.Start && End == other.End) || (Start == other.End && End == other.Start));
 }