private bool TriangleContainsVertexInList(int indexPrev, int indexCurr, int indexNext, NativeLinkedList <int> list)
        {
            for (NativeLinkedList <int> .Enumerator currIndexNode = list.Head; currIndexNode.IsValid; currIndexNode.MoveNext())
            {
                NativeLinkedList <int> .Enumerator prevIndexNode = (currIndexNode.Prev.IsValid) ? currIndexNode.Prev : list.Tail;
                NativeLinkedList <int> .Enumerator nextIndexNode = (currIndexNode.Next.IsValid) ? currIndexNode.Next : list.Head;

                bool isCurrentConvex = Math2DUtils.IsVertexConvex(Polygon[prevIndexNode.Value], Polygon[currIndexNode.Value], Polygon[nextIndexNode.Value], true);
                if (isCurrentConvex)
                {
                    continue;
                }

                int currIndexToCheck = currIndexNode.Value;
                if (currIndexToCheck == indexPrev || currIndexToCheck == indexCurr || currIndexToCheck == indexNext)
                {
                    continue;
                }

                if (Math2DUtils.IsInsideTriangle(Polygon[currIndexToCheck], Polygon[indexPrev], Polygon[indexCurr], Polygon[indexNext]))
                {
                    return(true);
                }
            }
            return(false);
        }
        public void Execute()
        {
            NativeLinkedList <int> hullVertices = StorePolygonContourAsLinkedList();

            #region Removing Holes
            //create the array containing the holes data
            NativeArray <ECHoleData> holes = GetHolesDataSortedByMaxX();
            //remove holes
            for (int hi = 0; hi < holes.Length; ++hi)
            {
                ECHoleData hole = holes[hi];
                var        intersectionEdgeP0 = hullVertices.GetEnumerator();
                var        intersectionEdgeP1 = hullVertices.GetEnumerator();
                float2     intersectionPoint  = new float2(float.MaxValue, hole.BridgePoint.y);

                for (var currentHullVertex = hullVertices.Head; currentHullVertex.IsValid; currentHullVertex.MoveNext())
                {
                    var nextHullVertex = (currentHullVertex.Next.IsValid) ? currentHullVertex.Next : hullVertices.Head;

                    float2 currPoint = Polygon[currentHullVertex.Value];
                    float2 nextPoint = Polygon[nextHullVertex.Value];

                    //M is to the left of the line containing the edge (M is inside the outer polygon)
                    bool isMOnLeftOfEdgeLine = (Math2DUtils.LineSide(hole.BridgePoint, currPoint, nextPoint) < 0f);
                    if (isMOnLeftOfEdgeLine)
                    {
                        continue;
                    }

                    // at least one point must be to right of the hole bridge point for intersection with ray to be possible
                    if (currPoint.x < hole.BridgePoint.x && nextPoint.x < hole.BridgePoint.x)
                    {
                        continue;
                    }

                    if (currPoint.y > hole.BridgePoint.y == nextPoint.y > hole.BridgePoint.y)
                    {
                        continue;
                    }

                    float intersectionX = nextPoint.x; // if line p0,p1 is vertical
                    if (math.abs(currPoint.x - nextPoint.x) > float.Epsilon)
                    {
                        float intersectY = hole.BridgePoint.y;
                        float gradient   = (currPoint.y - nextPoint.y) / (currPoint.x - nextPoint.x);
                        float c          = nextPoint.y - gradient * nextPoint.x;
                        intersectionX = (intersectY - c) / gradient;
                    }

                    if (intersectionX < intersectionPoint.x)
                    {
                        intersectionPoint.x = intersectionX;
                        intersectionEdgeP0  = currentHullVertex;
                        intersectionEdgeP1  = nextHullVertex;
                    }
                }

                var selectedHullBridgePoint = hullVertices.GetEnumerator();
                //If I is a vertex of the outer polygon, then M and I are mutually visible
                if (Math2DUtils.SamePoints(intersectionPoint, Polygon[intersectionEdgeP0.Value]))
                {
                    selectedHullBridgePoint = intersectionEdgeP0;
                }
                else if (Math2DUtils.SamePoints(intersectionPoint, Polygon[intersectionEdgeP1.Value]))
                {
                    selectedHullBridgePoint = intersectionEdgeP1;
                }
                else
                {
                    //Select P to be the endpoint of maximum x-value for this edge
                    var P = (Polygon[intersectionEdgeP0.Value].x > Polygon[intersectionEdgeP1.Value].x) ? intersectionEdgeP0 : intersectionEdgeP1;

                    bool  existReflexVertexInsideMIP = false;
                    float minAngle = float.MaxValue;
                    float minDist  = float.MaxValue;
                    for (var currOuterPolygonVertex = hullVertices.Head; currOuterPolygonVertex.IsValid; currOuterPolygonVertex.MoveNext())
                    {
                        if (currOuterPolygonVertex.Value == P.Value)
                        {
                            continue;
                        }

                        var nextOuterPolygonVertex = (currOuterPolygonVertex.Next.IsValid) ? currOuterPolygonVertex.Next : hullVertices.Head;
                        var prevOuterPolygonVertex = (currOuterPolygonVertex.Prev.IsValid) ? currOuterPolygonVertex.Prev : hullVertices.Tail;

                        if (Math2DUtils.IsVertexReflex(
                                Polygon[prevOuterPolygonVertex.Value],
                                Polygon[currOuterPolygonVertex.Value],
                                Polygon[nextOuterPolygonVertex.Value],
                                true))
                        {
                            bool isInsideMIPTriangle = Math2DUtils.IsInsideTriangle(Polygon[currOuterPolygonVertex.Value],
                                                                                    hole.BridgePoint,
                                                                                    intersectionPoint,
                                                                                    Polygon[P.Value]);
                            existReflexVertexInsideMIP |= isInsideMIPTriangle;

                            if (isInsideMIPTriangle)
                            {
                                //search for the reflex vertex R that minimizes the angle between (1,0) and the line segment M-R
                                float2 MR       = Polygon[currOuterPolygonVertex.Value] - hole.BridgePoint;
                                float  angleMRI = math.atan2(MR.y, MR.x);
                                if (angleMRI < minAngle)
                                {
                                    selectedHullBridgePoint = currOuterPolygonVertex;
                                    minAngle = angleMRI;
                                }
                                else if (math.abs(angleMRI - minAngle) <= float.Epsilon)
                                {
                                    //same angle
                                    float lengthMR = math.length(MR);
                                    if (lengthMR < minDist)
                                    {
                                        selectedHullBridgePoint = currOuterPolygonVertex;
                                        minDist = lengthMR;
                                    }
                                }
                            }
                        }

                        if (!existReflexVertexInsideMIP)
                        {
                            selectedHullBridgePoint = P;
                        }
                    }
                }

                hullVertices.InsertAfter(selectedHullBridgePoint, selectedHullBridgePoint.Value);
                for (int i = hole.BridgePointIndex - hole.HoleFirstIndex, count = 0;
                     count < hole.HoleLength;
                     i = (i + hole.HoleLength - 1) % hole.HoleLength, ++count)
                {
                    hullVertices.InsertAfter(selectedHullBridgePoint, i + hole.HoleFirstIndex);
                }
                hullVertices.InsertAfter(selectedHullBridgePoint, hole.BridgePointIndex);
            }
            holes.Dispose();
            #endregion

            Triangulate(hullVertices);
            hullVertices.Dispose();
        }