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
        }
        //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;
                }
            }
        }
        //
        // Which triangle in a triangulation is a point in? Should maybe be a part of the intersection library?
        //
        public static HalfEdgeFace2 FindWhichTriangleAPointIsIn(MyVector2 p, HalfEdgeFace2 startTriangle, HalfEdgeData2 triangulationData)
        {
            //Alternative 1. Search through all triangles and use point-in-triangle
            //HalfEdgeFace2 intersectingTriangle = FindWhichTriangleAPointIsIn_BruteForce(p, triangulationData);

            //Alternative 2.Triangulation walk
            HalfEdgeFace2 intersectingTriangle = FindWhichTriangleAPointIsIn_TriangulationWalk(p, startTriangle, triangulationData);

            return(intersectingTriangle);
        }
        //
        // Split triangle edge
        //
        //Split an edge at a point on the edge to form four new triangles, while removing two old
        //public static void SplitTriangleEdge(HalfEdge e, Vector3 splitPosition)
        //{

        //}



        //
        // Split triangle face
        //
        //Split a face (which we know is a triangle) at a point to create three new triangles while removing the old triangle
        //Could maybe make it more general so we can split a face, which consists of n edges
        public static void SplitTriangleFaceAtPoint(HalfEdgeFace2 f, MyVector2 splitPosition, HalfEdgeData2 data)
        {
            //The edges that belongs to this face
            HalfEdge2 e_1 = f.edge;
            HalfEdge2 e_2 = e_1.nextEdge;
            HalfEdge2 e_3 = e_2.nextEdge;

            //A list with new edges so we can connect the new edges with an edge on the opposite side
            HashSet <HalfEdge2> newEdges = new HashSet <HalfEdge2>();

            CreateNewFace(e_1, splitPosition, data, newEdges);
            CreateNewFace(e_2, splitPosition, data, newEdges);
            CreateNewFace(e_3, splitPosition, data, newEdges);

            //Debug.Log("New edges " + newEdges.Count);

            //Find the opposite connections
            foreach (HalfEdge2 e in newEdges)
            {
                //If we have already found a opposite
                if (e.oppositeEdge != null)
                {
                    continue;
                }

                MyVector2 eGoingTo   = e.v.position;
                MyVector2 eGoingFrom = e.prevEdge.v.position;

                foreach (HalfEdge2 eOpposite in newEdges)
                {
                    if (e == eOpposite || eOpposite.oppositeEdge != null)
                    {
                        continue;
                    }

                    MyVector2 eGoingTo_Other   = eOpposite.v.position;
                    MyVector2 eGoingFrom_Other = eOpposite.prevEdge.v.position;

                    if (eGoingTo.Equals(eGoingFrom_Other) && eGoingFrom.Equals(eGoingTo_Other))
                    {
                        e.oppositeEdge = eOpposite;
                        //Might as well connect it from the other way as well
                        eOpposite.oppositeEdge = e;

                        //Debug.Log("Found opposite");
                    }
                }
            }

            //Delete the old triangle
            DeleteTriangleFace(f, data, false);
        }
        //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;
            }
        }
        //
        // Delete a triangle
        //
        public static void DeleteTriangleFace(HalfEdgeFace2 t, HalfEdgeData2 data, bool shouldSetOppositeToNull)
        {
            //Update the data structure
            //In the half-edge data structure there's an edge going in the opposite direction
            //on the other side of this triangle with a reference to this edge, so we have to set these to null
            HalfEdge2 t_e1 = t.edge;
            HalfEdge2 t_e2 = t_e1.nextEdge;
            HalfEdge2 t_e3 = t_e2.nextEdge;

            //If we want to remove the triangle and create a hole
            //But sometimes we have created a new triangle and then we cant set the opposite to null
            if (shouldSetOppositeToNull)
            {
                if (t_e1.oppositeEdge != null)
                {
                    t_e1.oppositeEdge.oppositeEdge = null;
                }
                if (t_e2.oppositeEdge != null)
                {
                    t_e2.oppositeEdge.oppositeEdge = null;
                }
                if (t_e3.oppositeEdge != null)
                {
                    t_e3.oppositeEdge.oppositeEdge = null;
                }
            }


            //Remove from the data structure

            //Remove from the list of all triangles
            data.faces.Remove(t);

            //Remove the edges from the list of all edges
            data.edges.Remove(t_e1);
            data.edges.Remove(t_e2);
            data.edges.Remove(t_e3);

            //Remove the vertices
            data.vertices.Remove(t_e1.v);
            data.vertices.Remove(t_e2.v);
            data.vertices.Remove(t_e3.v);
        }
        //
        // Alternative 1. Search through all triangles and use point-in-triangle
        //

        //Simple but slow
        public static HalfEdgeFace2 BruteForce(MyVector2 p, HalfEdgeData2 triangulationData)
        {
            HalfEdgeFace2 intersectingTriangle = null;

            foreach (HalfEdgeFace2 f in triangulationData.faces)
            {
                //The corners of this triangle
                MyVector2 v1 = f.edge.v.position;
                MyVector2 v2 = f.edge.nextEdge.v.position;
                MyVector2 v3 = f.edge.nextEdge.nextEdge.v.position;

                Triangle2 t = new Triangle2(v1, v2, v3);

                //Is the point in this triangle?
                if (_Intersections.PointTriangle(t, p, true))
                {
                    intersectingTriangle = f;

                    break;
                }
            }

            return(intersectingTriangle);
        }
        //
        // Triangle to half-edge
        //
        public static HalfEdgeData2 Triangle2ToHalfEdge2(HashSet <Triangle2> triangles, HalfEdgeData2 data)
        {
            //Make sure the triangles have the same orientation, which is clockwise
            triangles = HelpMethods.OrientTrianglesClockwise(triangles);


            //Fill the data structure
            foreach (Triangle2 t in triangles)
            {
                HalfEdgeVertex2 v1 = new HalfEdgeVertex2(t.p1);
                HalfEdgeVertex2 v2 = new HalfEdgeVertex2(t.p2);
                HalfEdgeVertex2 v3 = new HalfEdgeVertex2(t.p3);

                //The vertices the edge points to
                HalfEdge2 he1 = new HalfEdge2(v1);
                HalfEdge2 he2 = new HalfEdge2(v2);
                HalfEdge2 he3 = new HalfEdge2(v3);

                he1.nextEdge = he2;
                he2.nextEdge = he3;
                he3.nextEdge = he1;

                he1.prevEdge = he3;
                he2.prevEdge = he1;
                he3.prevEdge = he2;

                //The vertex needs to know of an edge going from it
                v1.edge = he2;
                v2.edge = he3;
                v3.edge = he1;

                //The face the half-edge is connected to
                HalfEdgeFace2 face = new HalfEdgeFace2(he1);

                //Each edge needs to know of the face connected to this edge
                he1.face = face;
                he2.face = face;
                he3.face = face;


                //Add everything to the lists
                data.edges.Add(he1);
                data.edges.Add(he2);
                data.edges.Add(he3);

                data.faces.Add(face);

                data.vertices.Add(v1);
                data.vertices.Add(v2);
                data.vertices.Add(v3);
            }


            //Step 4. Find the half-edges going in the opposite direction of each edge we have
            //Is there a faster way to do this because this is the bottleneck?
            foreach (HalfEdge2 e in data.edges)
            {
                HalfEdgeVertex2 goingToVertex   = e.v;
                HalfEdgeVertex2 goingFromVertex = e.prevEdge.v;

                foreach (HalfEdge2 eOther in data.edges)
                {
                    //Dont compare with itself
                    if (e == eOther)
                    {
                        continue;
                    }

                    //Is this edge going between the vertices in the opposite direction
                    if (goingFromVertex.position.Equals(eOther.v.position) && goingToVertex.position.Equals(eOther.prevEdge.v.position))
                    {
                        e.oppositeEdge = eOther;

                        break;
                    }
                }
            }


            return(data);
        }
Exemplo n.º 9
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 triangles with an edge that is a constraint
            //We have to find all because they are not always connected, so we cant just find one and flood fill from it
            //for (int i = 0; i < constraints.Count; i++)
            //{
            //    MyVector2 c_p1 = constraints[i];
            //    MyVector2 c_p2 = constraints[MathUtility.ClampListIndex(i + 1, constraints.Count)];

            //    HalfEdgeFace2 borderTriangle = FindTriangleWithEdge(c_p1, c_p2, triangleData);

            //    //Maybe this edge has not triangle, which can happen if it's on the border
            //    if (borderTriangle != null)
            //    {
            //        trianglesToCheck.Enqueue(borderTriangle);
            //    }
            //}

            HashSet <HalfEdgeFace2> borderFaces = FindAllTrianglesBorderingTheConstraint(constraints, triangleData);

            foreach (HalfEdgeFace2 f in borderFaces)
            {
                trianglesToCheck.Enqueue(f);
            }



            //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;
                    }

                    //We have to check if this edge is a constraint because it might be alone on the border without neighbors that are also constraints
                    MyVector2 p1 = e.prevEdge.v.position;
                    MyVector2 p2 = e.v.position;

                    if (IsEdgeAConstraint(p1, p2, constraints))
                    {
                        continue;
                    }

                    trianglesToCheck.Enqueue(neighbor);
                }
            }

            return(trianglesToDelete);
        }
        //
        // Find which triangles are within a constraint
        //

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


            //Step 1. Find a triangle with an edge that shares an edge with the first constraint edge in the list
            //Since both are clockwise we know we are "inside" of the constraint, so this is a triangle we should delete
            HalfEdgeFace2 borderTriangle = null;

            MyVector2 c_p1 = constraints[0];
            MyVector2 c_p2 = constraints[1];

            //Search through all triangles
            foreach (HalfEdgeFace2 t in triangleData.faces)
            {
                //The edges in this triangle
                HalfEdge2 e1 = t.edge;
                HalfEdge2 e2 = e1.nextEdge;
                HalfEdge2 e3 = e2.nextEdge;

                //Is any of these edges a constraint? If so we have find the first triangle
                if (e1.v.position.Equals(c_p2) && e1.prevEdge.v.position.Equals(c_p1))
                {
                    borderTriangle = t;

                    break;
                }
                if (e2.v.position.Equals(c_p2) && e2.prevEdge.v.position.Equals(c_p1))
                {
                    borderTriangle = t;

                    break;
                }
                if (e3.v.position.Equals(c_p2) && e3.prevEdge.v.position.Equals(c_p1))
                {
                    borderTriangle = t;

                    break;
                }
            }

            if (borderTriangle == null)
            {
                return(null);
            }



            //Step 2. Find the rest of the triangles within the constraint by using a flood fill algorithm

            //Maybe better to first find all the other border triangles?

            //We know this triangle should be deleted
            trianglesToDelete.Add(borderTriangle);

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

            //Start at the triangle we know is within the constraints
            trianglesToCheck.Enqueue(borderTriangle);

            int safety = 0;

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

                //Investigate the triangles on the opposite sides of these edges
                HalfEdge2 e1 = t.edge;
                HalfEdge2 e2 = e1.nextEdge;
                HalfEdge2 e3 = e2.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
                if (e1.oppositeEdge != null &&
                    !trianglesToDelete.Contains(e1.oppositeEdge.face) &&
                    !trianglesToCheck.Contains(e1.oppositeEdge.face) &&
                    !IsEdgeAConstraint(e1.v.position, e1.prevEdge.v.position, constraints))
                {
                    trianglesToCheck.Enqueue(e1.oppositeEdge.face);

                    trianglesToDelete.Add(e1.oppositeEdge.face);
                }
                if (e2.oppositeEdge != null &&
                    !trianglesToDelete.Contains(e2.oppositeEdge.face) &&
                    !trianglesToCheck.Contains(e2.oppositeEdge.face) &&
                    !IsEdgeAConstraint(e2.v.position, e2.prevEdge.v.position, constraints))
                {
                    trianglesToCheck.Enqueue(e2.oppositeEdge.face);

                    trianglesToDelete.Add(e2.oppositeEdge.face);
                }
                if (e3.oppositeEdge != null &&
                    !trianglesToDelete.Contains(e3.oppositeEdge.face) &&
                    !trianglesToCheck.Contains(e3.oppositeEdge.face) &&
                    !IsEdgeAConstraint(e3.v.position, e3.prevEdge.v.position, constraints))
                {
                    trianglesToCheck.Enqueue(e3.oppositeEdge.face);

                    trianglesToDelete.Add(e3.oppositeEdge.face);
                }
            }

            return(trianglesToDelete);
        }
Exemplo n.º 11
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);
        }
        //
        // Alternative 2. Triangulation walk
        //

        //Fast but a little more complicated to understand
        //We can also give it a list, which should be empty so we can display the triangulation walk
        public static HalfEdgeFace2 TriangulationWalk(MyVector2 p, HalfEdgeFace2 startTriangle, HalfEdgeData2 triangulationData, List <HalfEdgeFace2> visitedTriangles = null)
        {
            HalfEdgeFace2 intersectingTriangle = null;


            //If we have a triangle to start in which may speed up the algorithm
            HalfEdgeFace2 currentTriangle = null;

            //We can feed it a start triangle to sometimes make the algorithm faster
            if (startTriangle != null)
            {
                currentTriangle = startTriangle;
            }
            //Find a random start triangle which is faster than starting at the first triangle?
            else
            {
                int randomPos = Random.Range(0, triangulationData.faces.Count);

                int i = 0;

                //faces are stored in a hashset so we have to loop through them while counting
                //to find the start triangle
                foreach (HalfEdgeFace2 f in triangulationData.faces)
                {
                    if (i == randomPos)
                    {
                        currentTriangle = f;

                        break;
                    }

                    i += 1;
                }
            }

            if (currentTriangle == null)
            {
                Debug.Log("Couldnt find start triangle when walking in triangulation");

                return(null);
            }

            if (visitedTriangles != null)
            {
                visitedTriangles.Add(currentTriangle);
            }



            //Start the triangulation walk to find the intersecting triangle
            int safety = 0;

            while (true)
            {
                safety += 1;

                if (safety > 1000000)
                {
                    Debug.Log("Stuck in endless loop when walking in triangulation");

                    break;
                }

                //Is the point intersecting with the current triangle?
                //We need to do 3 tests where each test is using the triangles edges
                //If the point is to the right of all edges, then it's inside the triangle
                //If the point is to the left we jump to that triangle instead
                HalfEdge2 e1 = currentTriangle.edge;
                HalfEdge2 e2 = e1.nextEdge;
                HalfEdge2 e3 = e2.nextEdge;


                //Test 1
                if (IsPointToTheRightOrOnLine(e1.prevEdge.v.position, e1.v.position, p))
                {
                    //Test 2
                    if (IsPointToTheRightOrOnLine(e2.prevEdge.v.position, e2.v.position, p))
                    {
                        //Test 3
                        if (IsPointToTheRightOrOnLine(e3.prevEdge.v.position, e3.v.position, p))
                        {
                            //We have found the triangle the point is in
                            intersectingTriangle = currentTriangle;

                            break;
                        }
                        //If to the left, move to this triangle
                        else
                        {
                            currentTriangle = e3.oppositeEdge.face;
                        }
                    }
                    //If to the left, move to this triangle
                    else
                    {
                        currentTriangle = e2.oppositeEdge.face;
                    }
                }
                //If to the left, move to this triangle
                else
                {
                    currentTriangle = e1.oppositeEdge.face;
                }


                if (visitedTriangles != null)
                {
                    visitedTriangles.Add(currentTriangle);
                }
            }


            //Add the last triangle if we found it
            if (visitedTriangles != null && intersectingTriangle != null)
            {
                visitedTriangles.Add(intersectingTriangle);
            }

            return(intersectingTriangle);
        }
        //Create a new triangle face when splitting triangle face
        private static void CreateNewFace(HalfEdge2 e_old, MyVector2 splitPosition, HalfEdgeData2 data, HashSet <HalfEdge2> newEdges)
        {
            //This triangle has the following positons
            MyVector2 p_split = splitPosition;
            MyVector2 p_next  = e_old.prevEdge.v.position;
            MyVector2 p_prev  = e_old.v.position;

            //Create the new stuff
            HalfEdgeVertex2 v_split = new HalfEdgeVertex2(p_split);
            HalfEdgeVertex2 v_next  = new HalfEdgeVertex2(p_next);
            HalfEdgeVertex2 v_prev  = new HalfEdgeVertex2(p_prev);

            //This is the edge that has the same position as the old edge
            HalfEdge2 e_1 = new HalfEdge2(v_prev);
            HalfEdge2 e_2 = new HalfEdge2(v_split);
            HalfEdge2 e_3 = new HalfEdge2(v_next);

            //The new face
            HalfEdgeFace2 f = new HalfEdgeFace2(e_1);


            //Create the connections
            //The new edge e has the same opposite as the old edge
            e_1.oppositeEdge = e_old.oppositeEdge;
            //But the opposite edge needs a new reference to this edge if its not a border
            if (e_1.oppositeEdge != null)
            {
                e_old.oppositeEdge.oppositeEdge = e_1;
            }

            //The other new edges will find the opposite in a loop when we have created all new edges
            newEdges.Add(e_2);
            newEdges.Add(e_3);

            //Create the connections between the edges
            e_1.nextEdge = e_2;
            e_1.prevEdge = e_3;

            e_2.nextEdge = e_3;
            e_2.prevEdge = e_1;

            e_3.nextEdge = e_1;
            e_3.prevEdge = e_2;

            //Each edge needs to connect to a face
            e_1.face = f;
            e_2.face = f;
            e_3.face = f;

            //The vertices need an edge that starts at that point
            v_split.edge = e_3;
            v_next.edge  = e_1;
            v_prev.edge  = e_2;

            //Add them to the lists
            data.faces.Add(f);

            data.edges.Add(e_1);
            data.edges.Add(e_2);
            data.edges.Add(e_3);

            data.vertices.Add(v_split);
            data.vertices.Add(v_next);
            data.vertices.Add(v_prev);
        }
        //
        // Flip triangle edge
        //
        //So the edge shared by two triangles is going between the two other vertices originally not part of the edge
        public static void FlipTriangleEdge(HalfEdge2 e)
        {
            //The data we need
            //This edge's triangle edges
            HalfEdge2 e_1 = e;
            HalfEdge2 e_2 = e_1.nextEdge;
            HalfEdge2 e_3 = e_1.prevEdge;
            //The opposite edge's triangle edges
            HalfEdge2 e_4 = e_1.oppositeEdge;
            HalfEdge2 e_5 = e_4.nextEdge;
            HalfEdge2 e_6 = e_4.prevEdge;
            //The 4 vertex positions
            MyVector2 aPos = e_1.v.position;
            MyVector2 bPos = e_2.v.position;
            MyVector2 cPos = e_3.v.position;
            MyVector2 dPos = e_5.v.position;

            //The 6 old vertices, we can use
            HalfEdgeVertex2 a_old          = e_1.v;
            HalfEdgeVertex2 b_old          = e_1.nextEdge.v;
            HalfEdgeVertex2 c_old          = e_1.prevEdge.v;
            HalfEdgeVertex2 a_opposite_old = e_4.prevEdge.v;
            HalfEdgeVertex2 c_opposite_old = e_4.v;
            HalfEdgeVertex2 d_old          = e_4.nextEdge.v;

            //Flip

            //Vertices
            //Triangle 1: b-c-d
            HalfEdgeVertex2 b = b_old;
            HalfEdgeVertex2 c = c_old;
            HalfEdgeVertex2 d = d_old;
            //Triangle 1: b-d-a
            HalfEdgeVertex2 b_opposite = a_opposite_old;

            b_opposite.position = bPos;
            HalfEdgeVertex2 d_opposite = c_opposite_old;

            d_opposite.position = dPos;
            HalfEdgeVertex2 a = a_old;


            //Change half-edge - half-edge connections
            e_1.nextEdge = e_3;
            e_1.prevEdge = e_5;

            e_2.nextEdge = e_4;
            e_2.prevEdge = e_6;

            e_3.nextEdge = e_5;
            e_3.prevEdge = e_1;

            e_4.nextEdge = e_6;
            e_4.prevEdge = e_2;

            e_5.nextEdge = e_1;
            e_5.prevEdge = e_3;

            e_6.nextEdge = e_2;
            e_6.prevEdge = e_4;

            //Half-edge - vertex connection
            e_1.v = b;
            e_2.v = b_opposite;
            e_3.v = c;
            e_4.v = d_opposite;
            e_5.v = d;
            e_6.v = a;

            //Half-edge - face connection
            HalfEdgeFace2 f1 = e_1.face;
            HalfEdgeFace2 f2 = e_4.face;

            e_1.face = f1;
            e_3.face = f1;
            e_5.face = f1;

            e_2.face = f2;
            e_4.face = f2;
            e_6.face = f2;

            //Face - half-edge connection
            f1.edge = e_3;
            f2.edge = e_4;

            //Vertices connection, which should have a reference to a half-edge going away from the vertex
            //Triangle 1: b-c-d
            b.edge = e_3;
            c.edge = e_5;
            d.edge = e_1;
            //Triangle 1: b-d-a
            b_opposite.edge = e_4;
            d_opposite.edge = e_6;
            a.edge          = e_2;

            //Opposite-edges are not changing!
            //And neither are we adding, removing data so we dont need to update the lists with all data
        }