//Is a point to the left or to the right of a vector going from a to b
    private void PointInRelationToVector(MyVector2 a, MyVector2 b, MyVector2 p)
    {
        //bool isToLeft = Geometry.IsPointLeftOfVector(a, b, p);

        //Debug.Log("Is to left: " + isToLeft);

        LeftOnRight value = _Geometry.IsPoint_Left_On_Right_OfVector(a, b, p);

        if (value == LeftOnRight.Left)
        {
            Debug.Log("Left");
        }
        if (value == LeftOnRight.On)
        {
            Debug.Log("On");
        }
        if (value == LeftOnRight.Right)
        {
            Debug.Log("Right");
        }

        //Display
        Vector3 a_3d = a.ToVector3();
        Vector3 b_3d = b.ToVector3();

        Gizmos.DrawLine(a_3d, b_3d);

        float arrowSize = 0.1f;

        TestAlgorithmsHelpMethods.DisplayArrow(a_3d, b_3d, arrowSize, Color.white);

        Gizmos.DrawWireSphere(p.ToVector3(), 0.1f);
    }
        //Help method to make code smaller
        //Is p to the right or on the line a-b
        private static bool IsPointToTheRightOrOnLine(MyVector2 a, MyVector2 b, MyVector2 p)
        {
            bool isToTheRight = false;

            LeftOnRight pointPos = _Geometry.IsPoint_Left_On_Right_OfVector(a, b, p);

            if (pointPos == LeftOnRight.Right || pointPos == LeftOnRight.On)
            {
                isToTheRight = true;
            }

            return(isToTheRight);
        }
        //Add colinear points to the convex hull
        private static List <MyVector2> AddColinearPoints(List <MyVector2> pointsOnConvexHull, List <MyVector2> points)
        {
            List <MyVector2> pointsOnConvexHull_IncludingColinear = new List <MyVector2>();

            //From the original points we dont have to remove the points that are on the convex hull
            //because they will be added anyway

            //Loop through all edges
            for (int i = 0; i < pointsOnConvexHull.Count; i++)
            {
                MyVector2 p1 = pointsOnConvexHull[i];
                MyVector2 p2 = pointsOnConvexHull[MathUtility.ClampListIndex(i + 1, pointsOnConvexHull.Count)];

                List <MyVector2> colinearPoints = new List <MyVector2>();

                foreach (MyVector2 p in points)
                {
                    LeftOnRight pointRelation = _Geometry.IsPoint_Left_On_Right_OfVector(p1, p2, p);

                    if (pointRelation == LeftOnRight.On)
                    {
                        colinearPoints.Add(p);
                    }
                }

                //Sort the colinear points so the are added on the correct order from p1 to p2
                colinearPoints = colinearPoints.OrderBy(n => MyVector2.SqrMagnitude(n - p1)).ToList();

                //Remove the last colinear point to avoid doubles
                colinearPoints.RemoveAt(colinearPoints.Count - 1);

                pointsOnConvexHull_IncludingColinear.AddRange(colinearPoints);
            }


            return(pointsOnConvexHull_IncludingColinear);
        }
        //Split an edge and create a new sub-convex hull
        private static List <MyVector2> CreateSubConvexHUll(MyVector2 p1, MyVector2 p3, HashSet <MyVector2> pointsToAdd)
        {
            if (pointsToAdd.Count == 0)
            {
                //Never return the last point so we avoid doubles on the convex hull
                return(new List <MyVector2>()
                {
                    p1
                });
            }


            //Find the point which is furthest from an edge
            MyVector2 p2 = FindPointFurthestFromEdge(p1, p3, pointsToAdd);

            //This point is also on the hull
            pointsToAdd.Remove(p2);

            //Remove points within this sub-hull triangle
            RemovePointsWithinTriangle(new Triangle2(p1, p2, p3), pointsToAdd);

            //No more points to add
            if (pointsToAdd.Count == 0)
            {
                //Never return the last point so we avoid doubles on the convex hull
                return(new List <MyVector2>()
                {
                    p1, p2
                });
            }
            //If we still have points to add, we have to split the edges again
            else
            {
                //As before, find the points outside of each edge
                HashSet <MyVector2> edge_p1p2_points = new HashSet <MyVector2>();
                HashSet <MyVector2> edge_p2p3_points = new HashSet <MyVector2>();

                foreach (MyVector2 p in pointsToAdd)
                {
                    //p1 p2
                    LeftOnRight pointRelation1 = _Geometry.IsPoint_Left_On_Right_OfVector(p1, p2, p);

                    if (pointRelation1 == LeftOnRight.On || pointRelation1 == LeftOnRight.Right)
                    {
                        edge_p1p2_points.Add(p);

                        continue;
                    }

                    //p2 p3
                    //If the point hasnt been added yet, we know it belong to this edge
                    edge_p2p3_points.Add(p);
                }


                //Split the edge again
                List <MyVector2> pointsOnHUll_p1p2 = CreateSubConvexHUll(p1, p2, edge_p1p2_points);
                List <MyVector2> pointsOnHUll_p2p3 = CreateSubConvexHUll(p2, p3, edge_p2p3_points);


                //Combine the list
                List <MyVector2> pointsOnHull = pointsOnHUll_p1p2;

                pointsOnHull.AddRange(pointsOnHUll_p2p3);


                return(pointsOnHull);
            }
        }
        //Used for debugging so we can see what's going on
        //public static List<MyVector2> GenerateConvexHull(List<MyVector2> originalPoints, bool includeColinearPoints, AABB normalizingbox, float dMax)


        public static List <MyVector2> GenerateConvexHull(List <MyVector2> originalPoints, bool includeColinearPoints)
        {
            List <MyVector2> pointsOnConvexHull = new List <MyVector2>();


            //Step 1.
            //Find the extreme points along each axis
            //This is similar to AABB but we need both x and y coordinates at each extreme point
            MyVector2 maxX = originalPoints[0];
            MyVector2 minX = originalPoints[0];
            MyVector2 maxY = originalPoints[0];
            MyVector2 minY = originalPoints[0];

            for (int i = 1; i < originalPoints.Count; i++)
            {
                MyVector2 p = originalPoints[i];

                if (p.x > maxX.x)
                {
                    maxX = p;
                }
                if (p.x < minX.x)
                {
                    minX = p;
                }

                if (p.y > maxY.y)
                {
                    maxY = p;
                }
                if (p.y < minY.y)
                {
                    minY = p;
                }
            }


            //Step 2.
            //From the 4 extreme points, choose the pair that's furthest appart
            //These two are the first two points on the hull
            List <MyVector2> extremePoints = new List <MyVector2>()
            {
                maxX, minX, maxY, minY
            };

            //Just pick some points as start value
            MyVector2 p1 = maxX;
            MyVector2 p2 = minX;

            //Can use sqr because we are not interested in the exact distance
            float maxDistanceSqr = -Mathf.Infinity;

            //Loop through all points and compare them
            //TODO is comparing too many times: example maxX with maxY, and then maxY with maxX
            //https://stackoverflow.com/questions/12249051/unique-combinations-of-list
            for (int i = 0; i < extremePoints.Count; i++)
            {
                MyVector2 p1_test = extremePoints[i];

                for (int j = 0; j < extremePoints.Count; j++)
                {
                    //Dont compare the point with itself
                    if (i == j)
                    {
                        continue;
                    }

                    MyVector2 p2_test = extremePoints[j];

                    float distSqr = MyVector2.SqrDistance(p1_test, p2_test);

                    if (distSqr > maxDistanceSqr)
                    {
                        maxDistanceSqr = distSqr;

                        p1 = p1_test;
                        p2 = p2_test;
                    }
                }
            }

            //Convert the list to hashset to easier remove points which are on the hull or are inside of the hull
            HashSet <MyVector2> pointsToAdd = new HashSet <MyVector2>(originalPoints);

            //Remove the first 2 points on the hull
            pointsToAdd.Remove(p1);
            pointsToAdd.Remove(p2);


            //Step 3.
            //Find the third point on the hull, by finding the point which is the furthest
            //from the line between p1 and p2
            MyVector2 p3 = FindPointFurthestFromEdge(p1, p2, pointsToAdd);

            //Remove it from the points we want to add
            pointsToAdd.Remove(p3);


            //Step 4. Form the intitial triangle

            //Make sure the hull is oriented counter-clockwise
            Triangle2 tStart = new Triangle2(p1, p2, p3);

            if (_Geometry.IsTriangleOrientedClockwise(tStart.p1, tStart.p2, tStart.p3))
            {
                tStart.ChangeOrientation();
            }

            //New p1-p3
            p1 = tStart.p1;
            p2 = tStart.p2;
            p3 = tStart.p3;

            //pointsOnConvexHull.Add(p1);
            //pointsOnConvexHull.Add(p2);
            //pointsOnConvexHull.Add(p3);

            //Remove the points that we now know are within the hull triangle
            RemovePointsWithinTriangle(tStart, pointsToAdd);


            //Step 5.
            //Associate the rest of the points to their closest edge
            HashSet <MyVector2> edge_p1p2_points = new HashSet <MyVector2>();
            HashSet <MyVector2> edge_p2p3_points = new HashSet <MyVector2>();
            HashSet <MyVector2> edge_p3p1_points = new HashSet <MyVector2>();

            foreach (MyVector2 p in pointsToAdd)
            {
                //p1 p2
                LeftOnRight pointRelation1 = _Geometry.IsPoint_Left_On_Right_OfVector(p1, p2, p);

                if (pointRelation1 == LeftOnRight.On || pointRelation1 == LeftOnRight.Right)
                {
                    edge_p1p2_points.Add(p);

                    continue;
                }

                //p2 p3
                LeftOnRight pointRelation2 = _Geometry.IsPoint_Left_On_Right_OfVector(p2, p3, p);

                if (pointRelation2 == LeftOnRight.On || pointRelation2 == LeftOnRight.Right)
                {
                    edge_p2p3_points.Add(p);

                    continue;
                }

                //p3 p1
                //If the point hasnt been added yet, we know it belong to this edge
                edge_p3p1_points.Add(p);
            }


            //Step 6
            //For each edge, find the point furthest away and create a new triangle
            //and repeat the above steps by finding which points are inside of the hull
            //and which points are outside and belong to a new edge

            //Will automatically ignore the last point on this sub-hull to avoid doubles
            List <MyVector2> pointsOnHUll_p1p2 = CreateSubConvexHUll(p1, p2, edge_p1p2_points);

            List <MyVector2> pointsOnHUll_p2p3 = CreateSubConvexHUll(p2, p3, edge_p2p3_points);

            List <MyVector2> pointsOnHUll_p3p1 = CreateSubConvexHUll(p3, p1, edge_p3p1_points);


            //Create the final hull by combing the points
            pointsOnConvexHull.Clear();

            pointsOnConvexHull.AddRange(pointsOnHUll_p1p2);
            pointsOnConvexHull.AddRange(pointsOnHUll_p2p3);
            pointsOnConvexHull.AddRange(pointsOnHUll_p3p1);



            //Step 7. Add colinear points
            //I think the easiest way to add colinear points is to add them when the algorithm is finished
            if (includeColinearPoints)
            {
                pointsOnConvexHull = AddColinearPoints(pointsOnConvexHull, originalPoints);
            }


            //Debug.Log("Points on hull: " + pointsOnConvexHull.Count);


            return(pointsOnConvexHull);
        }
        //We assume an edge is visible from a point if the triangle (formed by travering edges in the convex hull
        //of the existing triangulation) form a clockwise triangle with the point
        //https://stackoverflow.com/questions/8898255/check-whether-a-point-is-visible-from-a-face-of-a-2d-convex-hull
        private static HashSet <Triangle2> TriangulatePointsConvexHull(HashSet <MyVector2> points)
        {
            if (points.Count < 3)
            {
                Debug.Log("You need at least 3 points to form a triangle!");

                return(null);
            }


            //Step 0. Init the triangles we will return
            HashSet <Triangle2> triangles = new HashSet <Triangle2>();



            //Step 1. Sort the points
            List <MyVector2> sortedPoints = new List <MyVector2>(points);

            //OrderBy is always soring in ascending order - use OrderByDescending to get in the other order
            //sortedPoints = sortedPoints.OrderBy(n => n.x).ToList();

            //If we have colinear points we have to sort in both x and y
            sortedPoints = sortedPoints.OrderBy(n => n.x).ThenBy(n => n.y).ToList();



            //Step 2. Create the first triangle so we can start the algorithm because we need edges to look at
            //and see if they are visible

            //Pick the first two points in the sorted list - These are always a part of the first triangle
            MyVector2 p1 = sortedPoints[0];
            MyVector2 p2 = sortedPoints[1];

            //Remove them
            sortedPoints.RemoveAt(0);
            sortedPoints.RemoveAt(0);

            //The problem is the third point
            //If we have colinear points, then the third point in the sorted list is not always a valid point
            //to form a triangle because then it will be flat
            //So we have to look for a better point
            for (int i = 0; i < sortedPoints.Count; i++)
            {
                //We have found a non-colinear point
                LeftOnRight pointRelation = _Geometry.IsPoint_Left_On_Right_OfVector(p1, p2, sortedPoints[i]);

                if (pointRelation == LeftOnRight.Left || pointRelation == LeftOnRight.Right)
                {
                    MyVector2 p3 = sortedPoints[i];

                    //Remove this point
                    sortedPoints.RemoveAt(i);

                    //Build the first triangle
                    Triangle2 newTriangle = new Triangle2(p1, p2, p3);

                    triangles.Add(newTriangle);

                    break;
                }
            }

            //If we have finished search and not found a triangle, that means that all points
            //are colinear and we cant form any triangles
            if (triangles.Count == 0)
            {
                Debug.Log("All points you want to triangulate a co-linear");

                return(null);
            }



            //Step 3. Add the other points one-by-one

            //For each point we add we have to calculate a convex hull of the previous points
            //An optimization is to not use all points in the triangulation
            //to calculate the hull because many of them might be inside of the hull
            //So we will use the previous points on the hull and add the point we added last iteration
            //to generate the new convex hull

            //TODO a faster way to test if an edge is visible is to use "plane test" accoding to Quickhull paper???
            //On the other hand its faster to test just edges on the convex hull. The problem with using just planes
            //is that some points planes are "inside" of the convex polygon. Can we remove these points without
            //generating the convex hull?

            //First we need to init the convex hull
            HashSet <MyVector2> triangulatePoints = new HashSet <MyVector2>();

            foreach (Triangle2 t in triangles)
            {
                triangulatePoints.Add(t.p1);
                triangulatePoints.Add(t.p2);
                triangulatePoints.Add(t.p3);
            }

            //Calculate the first convex hull
            List <MyVector2> pointsOnHull = _ConvexHull.JarvisMarch_2D(triangulatePoints);

            //Add the other points one-by-one
            foreach (MyVector2 pointToAdd in sortedPoints)
            {
                bool couldFormTriangle = false;

                //Loop through all edges in the convex hull
                for (int j = 0; j < pointsOnHull.Count; j++)
                {
                    MyVector2 hull_p1 = pointsOnHull[j];
                    MyVector2 hull_p2 = pointsOnHull[MathUtility.ClampListIndex(j + 1, pointsOnHull.Count)];

                    //First we have to check if the points are colinear, then we cant form a triangle
                    LeftOnRight pointRelation = _Geometry.IsPoint_Left_On_Right_OfVector(hull_p1, hull_p2, pointToAdd);

                    if (pointRelation == LeftOnRight.On)
                    {
                        continue;
                    }

                    //If this triangle is clockwise, then we can see the edge
                    //so we should create a new triangle with this edge and the point
                    if (_Geometry.IsTriangleOrientedClockwise(hull_p1, hull_p2, pointToAdd))
                    {
                        triangles.Add(new Triangle2(hull_p1, hull_p2, pointToAdd));

                        couldFormTriangle = true;
                    }
                }

                //Add the point to the list of points on the hull
                //Will re-generate the hull by using these points so dont worry that the
                //list is not valid anymore
                if (couldFormTriangle)
                {
                    pointsOnHull.Add(pointToAdd);

                    //Find the convex hull of the current triangulation
                    //It generates a counter-clockwise convex hull
                    pointsOnHull = _ConvexHull.JarvisMarch_2D(new HashSet <MyVector2>(pointsOnHull));
                }
                else
                {
                    Debug.Log("This point could not form any triangles " + pointToAdd.x + " " + pointToAdd.y);
                }
            }



            return(triangles);
        }
        public static List <MyVector2> GenerateConvexHull(List <MyVector2> points)
        {
            List <MyVector2> pointsOnConvexHull = new List <MyVector2>();


            //Step 0. Normalize the data to range [0, 1] or everything will break at larger sizes :(
            //Make sure the data is already normalized!!!



            //Step 1. Find the vertex with the smallest x coordinate
            //If several points have the same x coordinate, find the one with the smallest y
            MyVector2 startPos = points[0];

            for (int i = 1; i < points.Count; i++)
            {
                MyVector2 testPos = points[i];

                //Because of precision issues, we use a small value to test if they are the same
                if (testPos.x < startPos.x || ((Mathf.Abs(testPos.x - startPos.x) < MathUtility.EPSILON && testPos.y < startPos.y)))
                {
                    startPos = points[i];
                }
            }

            //This vertex is always on the convex hull
            pointsOnConvexHull.Add(startPos);

            //But we can't remove it from the list of all points because we need it to stop the algorithm
            //points.Remove(startPos);



            //Step 2. Loop to find the other points on the hull
            MyVector2 previousPoint = pointsOnConvexHull[0];

            int counter = 0;

            while (true)
            {
                //We might have colinear points, so we need a list to save all points added this iteration
                List <MyVector2> pointsToAddToTheHull = new List <MyVector2>();


                //Pick next point randomly
                MyVector2 nextPoint = points[Random.Range(0, points.Count)];

                //If we are coming from the first point on the convex hull
                //then we are not allowed to pick it as next point, so we have to try again
                if (previousPoint.Equals(pointsOnConvexHull[0]) && nextPoint.Equals(pointsOnConvexHull[0]))
                {
                    counter += 1;

                    continue;
                }

                //This point is assumed to be on the convex hull
                pointsToAddToTheHull.Add(nextPoint);


                //But this randomly selected point might not be the best next point, so we have to see if we can improve
                //by finding a point that is more to the right
                //We also have to check if this point has colinear points if it happens to be on the hull
                for (int i = 0; i < points.Count; i++)
                {
                    MyVector2 testPoint = points[i];

                    //Dont test the point we picked randomly
                    //Or the point we are coming from which might happen when we move from the first point on the hull
                    if (testPoint.Equals(nextPoint) || testPoint.Equals(previousPoint))
                    {
                        continue;
                    }

                    //Where is the test point in relation to the line between the point we are coming from
                    //which we know is on the hull, and the point we think is on the hull
                    LeftOnRight pointRelation = _Geometry.IsPoint_Left_On_Right_OfVector(previousPoint, nextPoint, testPoint);

                    //The test point is on the line, so we have found a colinear point
                    if (pointRelation == LeftOnRight.On)
                    {
                        pointsToAddToTheHull.Add(testPoint);
                    }
                    //To the right = better point, so pick it as next point we want to test if it is on the hull
                    else if (pointRelation == LeftOnRight.Right)
                    {
                        nextPoint = testPoint;

                        //Clear colinear points because they belonged to the old point which was worse
                        pointsToAddToTheHull.Clear();

                        pointsToAddToTheHull.Add(nextPoint);

                        //We dont have to start over because the previous points weve gone through were worse
                    }
                    //To the left = worse point so do nothing
                }



                //Sort this list, so we can add the colinear points in correct order
                pointsToAddToTheHull = pointsToAddToTheHull.OrderBy(n => MyVector2.SqrMagnitude(n - previousPoint)).ToList();

                pointsOnConvexHull.AddRange(pointsToAddToTheHull);

                //Remove the points that are now on the convex hull, which should speed up the algorithm
                //Or will it be slower because it also takes some time to remove points?
                for (int i = 0; i < pointsToAddToTheHull.Count; i++)
                {
                    points.Remove(pointsToAddToTheHull[i]);
                }


                //The point we are coming from in the next iteration
                previousPoint = pointsOnConvexHull[pointsOnConvexHull.Count - 1];


                //Have we found the first point on the hull? If so we have completed the hull
                if (previousPoint.Equals(pointsOnConvexHull[0]))
                {
                    //Then remove it because it is the same as the first point, and we want a convex hull with no duplicates
                    pointsOnConvexHull.RemoveAt(pointsOnConvexHull.Count - 1);

                    //Stop the loop!
                    break;
                }


                //Safety
                if (counter > 100000)
                {
                    Debug.Log("Stuck in endless loop when generating convex hull with jarvis march");

                    break;
                }

                counter += 1;
            }



            //Dont forget to unnormalize the points!



            return(pointsOnConvexHull);
        }
Example #8
0
        //If you have points on a convex hull, sorted one after each other
        public static HashSet <Triangle2> GetTriangles(List <MyVector2> points)
        {
            List <Triangle2> triangles = new List <Triangle2>();

            //This vertex will be a vertex in all triangles (except for some of those that forms colinear points)
            MyVector2 a = points[0];

            List <MyVector2> colinearPoints = new List <MyVector2>();

            //And then we just loop through the other edges to make all triangles
            for (int i = 2; i < points.Count; i++)
            {
                MyVector2 b = points[i - 1];
                MyVector2 c = points[i];

                //If we hadnt had colinear points this would have been the last line
                //triangles.Add(new Triangle2(a, b, c));

                //But we can always make a triangle if the corners of the triangle are co-linear
                //Then the triangle will be flat. So we have to check if b is one the line between a and c
                LeftOnRight orientation = Geometry.IsPoint_Left_On_Right_OfVector(a, c, b);

                if (orientation == LeftOnRight.On)
                {
                    colinearPoints.Add(b);

                    continue;
                }
                else
                {
                    //First check if we have colinear points that have to be added
                    if (colinearPoints.Count > 0)
                    {
                        //First add the colinear points
                        for (int j = 0; j < colinearPoints.Count; j++)
                        {
                            if (j == 0)
                            {
                                triangles.Add(new Triangle2(a, colinearPoints[j], c));
                            }
                            else
                            {
                                triangles.Add(new Triangle2(colinearPoints[j - 1], colinearPoints[j], c));
                            }
                        }

                        //Add the last triangle
                        triangles.Add(new Triangle2(colinearPoints[colinearPoints.Count - 1], b, c));

                        colinearPoints.Clear();
                    }
                    else
                    {
                        triangles.Add(new Triangle2(a, b, c));
                    }
                }
            }

            //We might still have colinear points to add
            if (colinearPoints.Count > 0)
            {
                //Remove the last triangle because it's not valid anymore
                Triangle2 lastTriangle = triangles[triangles.Count - 1];

                triangles.RemoveAt(triangles.Count - 1);

                //We also have to add the last point on the hull if its colinear
                MyVector2 lastOnHull   = points[points.Count - 1];
                MyVector2 lastColinear = colinearPoints[colinearPoints.Count - 1];

                LeftOnRight orientation = Geometry.IsPoint_Left_On_Right_OfVector(a, lastColinear, lastOnHull);

                if (orientation == LeftOnRight.On)
                {
                    colinearPoints.Add(lastOnHull);
                }

                //Add the colinear points

                //First we have to identify our new a - the point we will anchor all new triangles to
                //This new a is part of the triangle we removed
                MyVector2 newA = lastTriangle.p2;

                //We also add the first point on the hull to colinear points to make it easier to build triangles
                colinearPoints.Add(a);

                for (int i = 1; i < colinearPoints.Count; i++)
                {
                    MyVector2 b = colinearPoints[i - 1];
                    MyVector2 c = colinearPoints[i];

                    triangles.Add(new Triangle2(newA, b, c));

                    //Debug.DrawLine(colinearPoints[i].ToVector3(), Vector3.zero, Color.white, 3f);
                }
            }


            HashSet <Triangle2> finalTriangles = new HashSet <Triangle2>(triangles);

            return(finalTriangles);
        }
Example #9
0
        //
        // Algorithm 1
        //

        //If you have points on a convex hull, sorted one after each other
        //If you have colinear points, it will ignore some of them but still triangulate the entire area
        //Colinear points are not changing the shape
        public static HashSet <Triangle2> GetTriangles(List <MyVector2> pointsOnHull, bool addColinearPoints)
        {
            //If we hadnt have to deal with colinear points, this algorithm would be really simple:
            HashSet <Triangle2> triangles = new HashSet <Triangle2>();

            //This vertex will be a vertex in all triangles
            MyVector2 a = pointsOnHull[0];

            //And then we just loop through the other edges to make all triangles
            for (int i = 1; i < pointsOnHull.Count; i++)
            {
                MyVector2 b = pointsOnHull[i];
                MyVector2 c = pointsOnHull[MathUtility.ClampListIndex(i + 1, pointsOnHull.Count)];

                //Is this a valid triangle?
                //If a, b, c are on the same line, the triangle has no area and we can't add it
                LeftOnRight pointRelation = Geometry.IsPoint_Left_On_Right_OfVector(a, b, c);

                if (pointRelation == LeftOnRight.On)
                {
                    continue;
                }

                triangles.Add(new Triangle2(a, b, c));
            }


            //Add the missing colinear points by splitting triangles
            //Step 2.1. We have now triangulated the entire convex polygon, but if we have colinear points
            //some of those points were not added
            //We can add them by splitting triangles

            //Find colinear points
            if (addColinearPoints)
            {
                HashSet <MyVector2> colinearPoints = new HashSet <MyVector2>(pointsOnHull);

                //Remove points that are in the triangulation from the points on the convex hull
                //and we can see which where not added = the colinear points
                foreach (Triangle2 t in triangles)
                {
                    colinearPoints.Remove(t.p1);
                    colinearPoints.Remove(t.p2);
                    colinearPoints.Remove(t.p3);
                }

                //Debug.Log("Colinear points: " + colinearPoints.Count);

                //Go through all colinear points and find which edge they should split
                //On the border we only need to split one edge because this edge has no neighbors
                foreach (MyVector2 p in colinearPoints)
                {
                    foreach (Triangle2 t in triangles)
                    {
                        //Is this point in the triangle
                        if (Intersections.PointTriangle(t, p, includeBorder: true))
                        {
                            SplitTriangleEdge(t, p, triangles);

                            break;
                        }
                    }
                }
            }


            return(triangles);
        }