Exemplo n.º 1
0
    //Method 2. Triangulation walk
    //This assumes there are no holes in the mesh
    //And that we have a super-triangle around the triangulation
    private static void FindIntersectingEdges_TriangleWalk(HalfEdgeData2 triangleData, MyVector2 c_p1, MyVector2 c_p2, List <HalfEdge2> intersectingEdges)
    {
        //Step 1. Begin at a triangle connected to the constraint edges's vertex c_p1
        HalfEdgeFace2 f = null;

        foreach (HalfEdgeFace2 testFace in triangleData.faces)
        {
            //The edges the triangle consists of
            HalfEdge2 e1 = testFace.edge;
            HalfEdge2 e2 = e1.nextEdge;
            HalfEdge2 e3 = e2.nextEdge;

            //Does one of these edges include the first vertex in the constraint edge
            if (e1.v.position.Equals(c_p1) || e2.v.position.Equals(c_p1) || e3.v.position.Equals(c_p1))
            {
                f = testFace;

                break;
            }
        }



        //Step2. Walk around p1 until we find a triangle with an edge that intersects with the edge p1-p2


        //Step3. March from one triangle to the next in the general direction of p2
    }
    //Find all triangles opposite of vertex p
    //But we will find all edges opposite to p, and from these edges we can find the triangles
    private static void AddTrianglesOppositePToStack(MyVector2 p, Stack <HalfEdge2> trianglesOppositeP, HalfEdgeData2 triangulationData)
    {
        //Find a vertex at position p and then rotate around it, triangle-by-triangle, to find all opposite edges
        HalfEdgeVertex2 rotateAroundThis = null;

        foreach (HalfEdgeVertex2 v in triangulationData.vertices)
        {
            if (v.position.Equals(p))
            {
                rotateAroundThis = v;
            }
        }

        //Which triangle is this vertex a part of, so we know when we have rotated all the way around
        HalfEdgeFace2 tStart = rotateAroundThis.edge.face;

        HalfEdgeFace2 tCurrent = null;

        int safety = 0;

        while (tCurrent != tStart)
        {
            safety += 1;

            if (safety > 10000)
            {
                Debug.Log("Stuck in endless loop when finding opposite edges in Delaunay Sloan");

                break;
            }

            //The edge opposite to p
            HalfEdge2 edgeOppositeRotateVertex = rotateAroundThis.edge.nextEdge.oppositeEdge;

            //Try to add the edge to the list iof triangles we are interested in
            //Null might happen if we are at the border
            //A stack might include duplicates so we have to check for that as well
            if (edgeOppositeRotateVertex != null && !trianglesOppositeP.Contains(edgeOppositeRotateVertex))
            {
                trianglesOppositeP.Push(edgeOppositeRotateVertex);
            }

            //Rotate left - this assumes we can always rotate left so no holes are allowed
            //and neither can we investigate one of the vertices thats a part of the supertriangle
            //which we dont need to worry about because p is never a part of the supertriangle
            rotateAroundThis = rotateAroundThis.edge.oppositeEdge.v;

            //In which triangle are we now?
            tCurrent = rotateAroundThis.edge.face;
        }
    }
Exemplo n.º 3
0
    //
    // Find which triangles are within a constraint
    //

    public static HashSet <HalfEdgeFace2> FindTrianglesWithinConstraint(HalfEdgeData2 triangleData, List <MyVector2> constraints)
    {
        HashSet <HalfEdgeFace2> trianglesToDelete = new HashSet <HalfEdgeFace2>();

        //Store the triangles we flood fill in this queue
        Queue <HalfEdgeFace2> trianglesToCheck = new Queue <HalfEdgeFace2>();


        //Step 1. Find all half-edges in the current triangulation which are constraint
        //Maybe faster to find all constraintEdges for ALL constraints because we are doing this per hole and hull
        //We have to find ALL because some triangles are not connected and will thus be missed if we find just a single start-triangle
        //Is also needed when flood-filling so we dont jump over a constraint
        HashSet <HalfEdge2> constraintEdges = FindAllConstraintEdges(constraints, triangleData);

        //Each edge is associated with a face which should be deleted
        foreach (HalfEdge2 e in constraintEdges)
        {
            if (!trianglesToCheck.Contains(e.face))
            {
                trianglesToCheck.Enqueue(e.face);
            }
        }


        //Step 2. Find the rest of the triangles within the constraint by using a flood-fill algorithm
        int safety = 0;

        List <HalfEdge2> edgesToCheck = new List <HalfEdge2>();

        while (true)
        {
            safety += 1;

            if (safety > 100000)
            {
                Debug.Log("Stuck in infinite loop when looking for triangles within constraint");

                break;
            }

            //Stop if we are out of neighbors
            if (trianglesToCheck.Count == 0)
            {
                break;
            }

            //Pick the first triangle in the list and investigate its neighbors
            HalfEdgeFace2 t = trianglesToCheck.Dequeue();

            //Add it for deletion
            trianglesToDelete.Add(t);

            //Investigate the triangles on the opposite sides of these edges
            edgesToCheck.Clear();

            edgesToCheck.Add(t.edge);
            edgesToCheck.Add(t.edge.nextEdge);
            edgesToCheck.Add(t.edge.nextEdge.nextEdge);

            //A triangle is a neighbor within the constraint if:
            //- The neighbor is not an outer border meaning no neighbor exists
            //- If we have not already visited the neighbor
            //- If the edge between the neighbor and this triangle is not a constraint
            foreach (HalfEdge2 e in edgesToCheck)
            {
                //No neighbor exists
                if (e.oppositeEdge == null)
                {
                    continue;
                }

                HalfEdgeFace2 neighbor = e.oppositeEdge.face;

                //We have already visited this neighbor
                if (trianglesToDelete.Contains(neighbor) || trianglesToCheck.Contains(neighbor))
                {
                    continue;
                }

                //This edge is a constraint and we can't jump across constraints
                if (constraintEdges.Contains(e))
                {
                    continue;
                }

                trianglesToCheck.Enqueue(neighbor);
            }
        }

        return(trianglesToDelete);
    }
    IEnumerator InsertPoints(HashSet <MyVector2> points, HalfEdgeData2 triangulationData, Triangle2 superTriangle)
    {
        //VISUALZ
        ShowTriangles(triangulationData);

        //VISUALZ - dont show the colored mesh until its finished because its flickering
        controller.shouldDisplayColoredMesh = false;

        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);


            //VISUALZ
            //Display the point as a black circle
            ShowCircle(p);

            yield return(new WaitForSeconds(controller.pauseTime));

            ShowTriangles(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;

                    //VISUALZ
                    controller.flipText.text = "Flipped edges: " + flippedEdges;

                    ShowTriangles(triangulationData);

                    yield return(new WaitForSeconds(controller.pauseTime));
                }
            }
        }


        //Dont show the last point we added
        controller.ResetBlackMeshes();


        //Step 8. Delete the vertices belonging to the supertriangle
        StartCoroutine(RemoveSuperTriangle(superTriangle, triangulationData));

        yield return(null);
    }