//Show points private void ShowPoints(HashSet <MyVector2> points) { //Clear previous points //Remove all old meshes controller.ClearBlackMeshes(); foreach (MyVector2 p in points) { controller.GenerateCircleMesh(p, shouldResetAllMeshes: false); } }
//Flip edges until we get a delaunay triangulation private IEnumerator 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; //If we want to display the test circle //controller.GenerateDelaunayCircleMeshes(a, b, c, d); //yield return new WaitForSeconds(controller.pauseTime); //Test if we should flip this edge if (DelaunayMethods.ShouldFlipEdge(a, b, c, d)) { flippedEdges += 1; hasFlippedEdge = true; HalfEdgeHelpMethods.FlipTriangleEdge(thisEdge); controller.flipText.text = "Flipped edges: " + flippedEdges; controller.GenerateTriangulationMesh(triangleData); yield return(new WaitForSeconds(controller.pauseTime)); } } //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; } } //Remove the circle meshes so we see that we are finished controller.ClearBlackMeshes(); yield return(null); }
IEnumerator InsertPoints(HashSet <MyVector2> points, HalfEdgeData2 triangulationData, Triangle2 superTriangle) { //Visualize the first triangle controller.GenerateTriangulationMesh(triangulationData); yield return(new WaitForSeconds(controller.pauseTime)); //Step 4. Loop over each point we want to insert and do Steps 5-7 //These are for display purposes only int missedPoints = 0; int flippedEdges = 0; foreach (MyVector2 p in points) { //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); //Visualize //Display the point as a black circle controller.GenerateCircleMesh(p, shouldResetAllMeshes: true); yield return(new WaitForSeconds(controller.pauseTime)); controller.GenerateTriangulationMesh(triangulationData); yield return(new WaitForSeconds(controller.pauseTime)); //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; //Visualize controller.flipText.text = "Flipped edges: " + flippedEdges; controller.GenerateTriangulationMesh(triangulationData); yield return(new WaitForSeconds(controller.pauseTime)); } } } controller.ClearBlackMeshes(); //Step 8. Delete the vertices belonging to the supertriangle StartCoroutine(RemoveSuperTriangle(superTriangle, triangulationData)); yield return(null); }