//Remove the supertriangle
        private static void RemoveSuperTriangle(Triangle2 superTriangle, HalfEdgeData2 triangulationData)
        {
            //The super triangle doesnt exists anymore because we have split it into many new triangles
            //But we can use its vertices to figure out which new triangles (or faces belonging to the triangle)
            //we should delete

            HashSet <HalfEdgeFace2> triangleFacesToDelete = new HashSet <HalfEdgeFace2>();

            //Loop through all vertices belongin to the triangulation
            foreach (HalfEdgeVertex2 v in triangulationData.vertices)
            {
                //If the face attached to this vertex already exists in the list of faces we want to delete
                //Then dont add it again
                if (triangleFacesToDelete.Contains(v.edge.face))
                {
                    continue;
                }

                MyVector2 v1 = v.position;

                //Is this vertex in the triangulation a vertex in the super triangle?
                if (v1.Equals(superTriangle.p1) || v1.Equals(superTriangle.p2) || v1.Equals(superTriangle.p3))
                {
                    triangleFacesToDelete.Add(v.edge.face);
                }
            }

            //Debug.Log("Triangles to delete: " + trianglesToDelete.Count);

            //Delete the new triangles with vertices attached to the super triangle
            foreach (HalfEdgeFace2 f in triangleFacesToDelete)
            {
                HalfEdgeHelpMethods.DeleteTriangleFace(f, triangulationData, shouldSetOppositeToNull: true);
            }
        }
コード例 #2
0
        //Flip edges until we get a delaunay triangulation
        private static void FlipEdges(HalfEdgeData2 triangleData)
        {
            //The edges we want to flip
            HashSet <HalfEdge2> edges = triangleData.edges;

            //To avoid getting stuck in infinite loop
            int safety = 0;

            //Count how many edges we have flipped, which may be interesting to display
            int flippedEdges = 0;

            while (true)
            {
                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Stuck in endless loop when flipping edges to get a Delaunay triangulation");

                    break;
                }

                bool hasFlippedEdge = false;

                //Search through all edges to see if we can flip an edge
                foreach (HalfEdge2 thisEdge in edges)
                {
                    //Is this edge sharing an edge with another triangle, otherwise its a border, and then we cant flip the edge
                    if (thisEdge.oppositeEdge == null)
                    {
                        continue;
                    }

                    //The positions of the vertices belonging to the two triangles that we might flip
                    //a-c should be the edge that we might flip
                    MyVector2 a = thisEdge.v.position;
                    MyVector2 b = thisEdge.nextEdge.v.position;
                    MyVector2 c = thisEdge.nextEdge.nextEdge.v.position;
                    MyVector2 d = thisEdge.oppositeEdge.nextEdge.v.position;

                    //Test if we should flip this edge
                    if (DelaunayMethods.ShouldFlipEdge(a, b, c, d))
                    {
                        flippedEdges += 1;

                        hasFlippedEdge = true;

                        HalfEdgeHelpMethods.FlipTriangleEdge(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 in " + flippedEdges + " flips");

                    break;
                }
            }
        }
        //Insert a new point in the triangulation we already have, so we need at least one triangle
        public static void InsertNewPointInTriangulation(MyVector2 p, HalfEdgeData2 triangulationData, ref int missedPoints, ref int flippedEdges)
        {
            //Step 5. Insert the new point in the triangulation
            //Find the existing triangle the point is in
            HalfEdgeFace2 f = PointTriangulationIntersection.TriangulationWalk(p, null, triangulationData);

            //We couldnt find a triangle maybe because the point is not in the triangulation?
            if (f == null)
            {
                missedPoints += 1;
            }

            //Delete this triangle and form 3 new triangles by connecting p to each of the vertices in the old triangle
            HalfEdgeHelpMethods.SplitTriangleFaceAtPoint(f, p, triangulationData);


            //Step 6. Initialize stack. Place all triangles which are adjacent to the edges opposite p on a LIFO stack
            //The report says we should place triangles, but it's easier to place edges with our data structure
            Stack <HalfEdge2> trianglesToInvestigate = new Stack <HalfEdge2>();

            AddTrianglesOppositePToStack(p, trianglesToInvestigate, triangulationData);


            //Step 7. Restore delaunay triangulation
            //While the stack is not empty
            int safety = 0;

            while (trianglesToInvestigate.Count > 0)
            {
                safety += 1;

                if (safety > 1000000)
                {
                    Debug.Log("Stuck in infinite loop when restoring delaunay in incremental sloan algorithm");

                    break;
                }

                //Step 7.1. Remove a triangle from the stack
                HalfEdge2 edgeToTest = trianglesToInvestigate.Pop();

                //Step 7.2. Do we need to flip this edge?
                //If p is outside or on the circumcircle for this triangle, we have a delaunay triangle and can return to next loop
                MyVector2 a = edgeToTest.v.position;
                MyVector2 b = edgeToTest.prevEdge.v.position;
                MyVector2 c = edgeToTest.nextEdge.v.position;

                //abc are here counter-clockwise
                if (DelaunayMethods.ShouldFlipEdgeStable(a, b, c, p))
                {
                    HalfEdgeHelpMethods.FlipTriangleEdge(edgeToTest);

                    //Step 7.3. Place any triangles which are now opposite p on the stack
                    AddTrianglesOppositePToStack(p, trianglesToInvestigate, triangulationData);

                    flippedEdges += 1;
                }
            }
        }
コード例 #4
0
        //
        // Remove all triangles that are inside the constraint
        //

        //This assumes the vertices in the constraint are ordered clockwise
        private static void RemoveSuperfluousTriangles(HalfEdgeData2 triangleData, List <MyVector2> constraints)
        {
            //This assumes we have at least 3 vertices in the constraint because we cant delete triangles inside a line
            if (constraints.Count < 3)
            {
                return;
            }

            HashSet <HalfEdgeFace2> trianglesToBeDeleted = FindTrianglesWithinConstraint(triangleData, constraints);

            //Delete the triangles
            foreach (HalfEdgeFace2 t in trianglesToBeDeleted)
            {
                HalfEdgeHelpMethods.DeleteTriangleFace(t, triangleData, true);
            }
        }
コード例 #5
0
        //
        // Try to restore the delaunay triangulation by flipping newly created edges
        //

        //This process is similar to when we created the original delaunay triangulation
        //This step can maybe be skipped if you just want a triangulation and Ive noticed its often not flipping any triangles
        private static void RestoreDelaunayTriangulation(MyVector2 c_p1, MyVector2 c_p2, List <HalfEdge2> newEdges)
        {
            int safety = 0;

            int flippedEdges = 0;

            //Repeat 4.1 - 4.3 until no further swaps take place
            while (true)
            {
                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Stuck in endless loop when delaunay after fixing constrained edges");

                    break;
                }

                bool hasFlippedEdge = false;

                //Step 4.1. Loop over each edge in the list of newly created edges
                for (int j = 0; j < newEdges.Count; j++)
                {
                    HalfEdge2 e = newEdges[j];

                    //Step 4.2. Let the newly created edge be defined by the vertices
                    MyVector2 v_k = e.v.position;
                    MyVector2 v_l = e.prevEdge.v.position;

                    //If this edge is equal to the constrained edge, then skip to step 4.1
                    //because we are not allowed to flip the constrained edge
                    if ((v_k.Equals(c_p1) && v_l.Equals(c_p2)) || (v_l.Equals(c_p1) && v_k.Equals(c_p2)))
                    {
                        continue;
                    }

                    //Step 4.3. If the two triangles that share edge v_k and v_l don't satisfy the delaunay criterion,
                    //so that a vertex of one of the triangles is inside the circumcircle of the other triangle, flip the edge
                    //The third vertex of the triangle belonging to this edge
                    MyVector2 v_third_pos = e.nextEdge.v.position;
                    //The vertice belonging to the triangle on the opposite side of the edge and this vertex is not a part of the edge
                    MyVector2 v_opposite_pos = e.oppositeEdge.nextEdge.v.position;

                    //Test if we should flip this edge
                    if (DelaunayMethods.ShouldFlipEdge(v_l, v_k, v_third_pos, v_opposite_pos))
                    {
                        //Flip the edge
                        hasFlippedEdge = true;

                        HalfEdgeHelpMethods.FlipTriangleEdge(e);

                        flippedEdges += 1;
                    }
                }

                //We have searched through all edges and havent found an edge to flip, so we cant improve anymore
                if (!hasFlippedEdge)
                {
                    Debug.Log("Found a constrained delaunay triangulation in " + flippedEdges + " flips");

                    break;
                }
            }
        }
コード例 #6
0
        //
        // Remove the edges that intersects with a constraint by flipping triangles
        //

        //The idea here is that all possible triangulations for a set of points can be found
        //by systematically swapping the diagonal in each convex quadrilateral formed by a pair of triangles
        //So we will test all possible arrangements and will always find a triangulation which includes the constrained edge
        private static List <HalfEdge2> RemoveIntersectingEdges(MyVector2 v_i, MyVector2 v_j, Queue <HalfEdge2> intersectingEdges)
        {
            List <HalfEdge2> newEdges = new List <HalfEdge2>();

            int safety = 0;

            //While some edges still cross the constrained edge, do steps 3.1 and 3.2
            while (intersectingEdges.Count > 0)
            {
                safety += 1;

                if (safety > 100000)
                {
                    Debug.Log("Stuck in infinite loop when fixing constrained edges");

                    break;
                }

                //Step 3.1. Remove an edge from the list of edges that intersects the constrained edge
                HalfEdge2 e = intersectingEdges.Dequeue();

                //The vertices belonging to the two triangles
                MyVector2 v_k   = e.v.position;
                MyVector2 v_l   = e.prevEdge.v.position;
                MyVector2 v_3rd = e.nextEdge.v.position;
                //The vertex belonging to the opposite triangle and isn't shared by the current edge
                MyVector2 v_opposite_pos = e.oppositeEdge.nextEdge.v.position;

                //Step 3.2. If the two triangles don't form a convex quadtrilateral
                //place the edge back on the list of intersecting edges (because this edge cant be flipped)
                //and go to step 3.1
                if (!_Geometry.IsQuadrilateralConvex(v_k, v_l, v_3rd, v_opposite_pos))
                {
                    intersectingEdges.Enqueue(e);

                    continue;
                }
                else
                {
                    //Flip the edge like we did when we created the delaunay triangulation
                    HalfEdgeHelpMethods.FlipTriangleEdge(e);

                    //The new diagonal is defined by the vertices
                    MyVector2 v_m = e.v.position;
                    MyVector2 v_n = e.prevEdge.v.position;

                    //If this new diagonal intersects with the constrained edge, add it to the list of intersecting edges
                    if (IsEdgeCrossingEdge(v_i, v_j, v_m, v_n))
                    {
                        intersectingEdges.Enqueue(e);
                    }
                    //Place it in the list of newly created edges
                    else
                    {
                        newEdges.Add(e);
                    }
                }
            }

            return(newEdges);
        }