Ejemplo n.º 1
0
        //Alternative 1. Triangulate with some algorithm - then flip edges until we have a delaunay triangulation
        public static List <Triangle> TriangulateByFlippingEdges(List <Vector3> sites)
        {
            //Step 1. Triangulate the points with some algorithm
            //Vector3 to vertex
            List <Vertex> vertices = new List <Vertex>();

            for (int i = 0; i < sites.Count; i++)
            {
                vertices.Add(new Vertex(sites[i]));
            }

            //Triangulate the convex hull of the sites
            List <Triangle> triangles = IncrementalTriangulationAlgorithm.TriangulatePoints(vertices);
            //List triangles = TriangulatePoints.TriangleSplitting(vertices);

            //Step 2. Change the structure from triangle to half-edge to make it faster to flip edges
            List <HalfEdge> halfEdges = Delaunay.TransformFromTriangleToHalfEdge(triangles);

            //Step 3. Flip edges until we have a delaunay triangulation
            int safety = 0;

            int flippedEdges = 0;

            while (true)
            {
                safety += 1;

                if (safety > 100000)
                {
                    Debug.WriteLine("Stuck in endless loop");

                    break;
                }

                bool hasFlippedEdge = false;

                //Search through all edges to see if we can flip an edge
                for (int i = 0; i < halfEdges.Count; i++)
                {
                    HalfEdge thisEdge = halfEdges[i];

                    //Is this edge sharing an edge, otherwise its a border, and then we cant flip the edge
                    if (thisEdge.oppositeEdge == null)
                    {
                        continue;
                    }

                    //The vertices belonging to the two triangles, c-a are the edge vertices, b belongs to this triangle
                    Vertex a = thisEdge.v;
                    Vertex b = thisEdge.nextEdge.v;
                    Vertex c = thisEdge.prevEdge.v;
                    Vertex d = thisEdge.oppositeEdge.nextEdge.v;

                    Vector2 aPos = a.GetPos2D_XZ();
                    Vector2 bPos = b.GetPos2D_XZ();
                    Vector2 cPos = c.GetPos2D_XZ();
                    Vector2 dPos = d.GetPos2D_XZ();

                    //Use the circle test to test if we need to flip this edge
                    if (Delaunay.IsPointInsideOutsideOrOnCircle(aPos, bPos, cPos, dPos) < 0f)
                    {
                        //Are these the two triangles that share this edge forming a convex quadrilateral?
                        //Otherwise the edge cant be flipped
                        if (Delaunay.IsQuadrilateralConvex(aPos, bPos, cPos, dPos))
                        {
                            //If the new triangle after a flip is not better, then dont flip
                            //This will also stop the algoritm from ending up in an endless loop
                            if (Delaunay.IsPointInsideOutsideOrOnCircle(bPos, cPos, dPos, aPos) < 0f)
                            {
                                continue;
                            }

                            //Flip the edge
                            flippedEdges += 1;

                            hasFlippedEdge = true;

                            FlipEdge(thisEdge);
                        }
                    }
                }

                //We have searched through all edges and havent found an edge to flip, so we have a Delaunay triangulation!
                if (!hasFlippedEdge)
                {
                    //Debug.Log("Found a delaunay triangulation");

                    break;
                }
            }

            //Debug.Log("Flipped edges: " + flippedEdges);

            //Dont have to convert from half edge to triangle because the algorithm will modify the objects, which belongs to the
            //original triangles, so the triangles have the data we need

            return(triangles);
        }