/// <summary>
        /// Split up a Polygon with the Diagonals.
        /// This function splits the Polygon into two SubPolygons using the first Diagonal
        /// and then calls itself recursively.
        /// </summary>
        /// <param name="poly">The Polygon to split</param>
        /// <param name="diagonals">The Diagonals inside the Polygon, that are used to split it</param>
        /// <returns>The SubPolygons that were created by splitting the input Polygon</returns>
        private static PolygonData[] SplitPolygonWithDiagonals(PolygonData poly, List <Tuple <int, int> > diagonals)
        {
            // Count of the SubPolygons to create
            var subPolygonCount = diagonals.Count + 1;

            if (subPolygonCount == 1)
            {
                return new PolygonData[] { poly }
            }
            ;
            var subPolygons = new List <PolygonData>();
            // Subdivide with with first Diagonal
            var diagonal = diagonals[0];
            // Create the first SubPolygon
            var firstSubPolygonPoints = poly.Points.TakeWhile(p => p.Index != diagonal.Item1).ToList();

            firstSubPolygonPoints.Add(poly.Points.First(p => p.Index == diagonal.Item1));
            firstSubPolygonPoints.AddRange(poly.Points.SkipWhile(p => p.Index != diagonal.Item2).ToList());
            // HashSet of the Indices of the first SubPolygon
            // Used to split the remaining Diagonals
            var firstSubPolygonIndices = new HashSet <int>(firstSubPolygonPoints.Select(p => p.Index));
            // Create the second SubPolygon
            var secondSubPolygonPoints = poly.Points.SkipWhile(p => p.Index != diagonal.Item1).ToList();

            secondSubPolygonPoints = secondSubPolygonPoints.TakeWhile(p => p.Index != diagonal.Item2).ToList();
            secondSubPolygonPoints.Add(poly.Points.First(p => p.Index == diagonal.Item2));
            // We don't need this Diagonal any more
            diagonals.Remove(diagonal);
            // Split the Diagonals into two sets of Diagonals
            // Depending on in which SupPolygon it is located
            var diagsFirst  = new List <Tuple <int, int> >();
            var diagsSecond = new List <Tuple <int, int> >();

            foreach (var diag in diagonals)
            {
                if (firstSubPolygonIndices.Contains(diag.Item1) && firstSubPolygonIndices.Contains(diag.Item2))
                {
                    diagsFirst.Add(diag);
                }
                else
                {
                    diagsSecond.Add(diag);
                }
            }

            // Calculate the Diagonals that are positioned in first and second Subpolygon
            subPolygons.AddRange(SplitPolygonWithDiagonals(new PolygonData(firstSubPolygonPoints), diagsFirst).ToList());

            // Recursively call Function for first Subpolygon and second Subpolygon
            subPolygons.AddRange(SplitPolygonWithDiagonals(new PolygonData(secondSubPolygonPoints), diagsSecond).ToList());

            // Return the split-up Polygons
            return(subPolygons.ToArray());
        }
        /// <summary>
        /// Perform the Triangulation of the Input.
        /// </summary>
        /// <param name="polygon">The Input Polygon</param>
        /// <param name="holes">The Input Polygon</param>
        /// <returns>List of Indices representing the Triangulation of the Polygon</returns>
        public static Int32Collection Triangulate(IList <Point> polygon, List <List <Point> > holes = null)
        {
            // Allocate and initialize List of Indices in Polygon
            var result = new Int32Collection();

            // Point-List from Input
            // (we don't want the first and last Point to be present two times)
            var points = polygon.ToList();

            if (points[0] == points[points.Count - 1])
            {
                points.RemoveAt(points.Count - 1);
            }
            var count = points.Count;

            // Sort the Input and create the Datastructures
            // Make the Polygon CounterClockWise
            var didReverse = false;

            if (!isCCW(polygon))
            {
                points.Reverse();
                didReverse = true;
            }

            // Skip Polygons that don't need Triangulation
            if (count < 3)
            {
                return(null);
            }
            else if (count == 3)
            {
                if (!didReverse)
                {
                    return(new Int32Collection {
                        0, 1, 2
                    });
                }
                else
                {
                    return(new Int32Collection {
                        2, 1, 1
                    });
                }
            }

            // Create Polygon Data Structure
            var poly = new PolygonData(points);

            // Sort Points from highest y to lowest y
            // and if two or more Points have the same y Value from lowest x to highest x Value
            var events = new List <PolygonPoint>(poly.Points);

            events.Sort();

            // Mapping from the main Polygon to the current Polygon
            var mainMapping = new Dictionary <int, int>();

            for (int i = 0; i < count; i++)
            {
                mainMapping[i] = i;
            }

            // Calculate the Diagonals in the Down Sweep
            var diagonals = CalculateDiagonals(events, mainMapping);

            // Split the Polygon
            var subPolygons = SplitPolygonWithDiagonals(poly, diagonals);

            var monotonePolygons = new List <PolygonData>();

            // Up Sweep for all Sub-Polygons
            foreach (var subPoly in subPolygons)
            {
                // Sort the Events from Bottom to Top
                events = new List <PolygonPoint>(subPoly.Points);
                events.Sort();
                events.Reverse();

                // Mapping from the main Polygon to the current Polygon
                var polyMapping = new Dictionary <int, int>();
                for (int i = 0; i < subPoly.Points.Count; i++)
                {
                    polyMapping[subPoly.Points[i].Index] = i;
                }
                // Calculate the Diagonals in the Up Sweep
                diagonals = CalculateDiagonals(events, polyMapping, false);

                // Split the Polygon
                var monotoneSubPolygons = SplitPolygonWithDiagonals(subPoly, diagonals);
                // Add to List of monotone Polygons
                monotonePolygons.AddRange(monotoneSubPolygons);
            }

            // y-Monotone Polygons
            // Triangulate
            foreach (var monoton in monotonePolygons)
            {
                result.AddRange(TriangulateMonotone(monoton));
            }

            // If we reversed the Polygon,
            // we need to reverse the result also to get a correct Triangulation
            if (didReverse)
            {
                // Transform back every calculated Index
                for (int i = 0; i < result.Count; i++)
                {
                    result[i] = count - result[i] - 1;
                }
            }

            // Return all calculated Triangleindices
            return(result);
        }
        /// <summary>
        /// Triangulate the y-Monotone Polygons.
        /// </summary>
        /// <param name="monoton">The y-Monotone Polygon to triangle</param>
        /// <returns>Index-List of Polygon Points (Indices from the original Polygon)</returns>
        private static Int32Collection TriangulateMonotone(PolygonData monoton)
        {
            // Collection to return
            Int32Collection result = new Int32Collection();

            // Sort the Events
            var events = new List <PolygonPoint>(monoton.Points);

            events.Sort();

            // Stack of Events to push to and pop from
            var pointStack = new Stack <PolygonPoint>();

            // Push the first two Events
            pointStack.Push(events[0]);
            pointStack.Push(events[1]);

            // Left- and right Chain for Triangulation
            var left  = (events[0].Next == events[1]) ? events[1] : events[0];
            var right = (events[0].Last == events[1]) ? events[1] : events[0];

            // Count of Points
            var pointCnt = monoton.Points.Count;

            // Handle the 3rd...n-th Point to triangle
            for (int i = 2; i < pointCnt; i++)
            {
                // The current Point
                var newPoint = events[i];
                var top      = pointStack.Peek();
                // If the new Point is not on the same side as the last Point on the Stack
                //if (!(leftChain.Contains(top) && leftChain.Contains(newPoint) || rightChain.Contains(top) && rightChain.Contains(newPoint)))
                if (!(top.Last == newPoint || top.Next == newPoint))
                {
                    // Determine this Point's Chain (left or right)
                    if (left.Next == newPoint)
                    {
                        left = newPoint;
                    }
                    else if (right.Last == newPoint)
                    {
                        right = newPoint;
                    }

                    // Third triangle Point
                    var p2 = top;
                    // While there is a Point on the Stack
                    while (pointStack.Count != 0)
                    {
                        // Pop and set the third Point
                        top = pointStack.Pop();
                        p2  = top;
                        if (pointStack.Count != 0)
                        {
                            // Pop again
                            top = pointStack.Pop();

                            // Add to the result. The Order is depending on the Side
                            if (left == newPoint)
                            {
                                result.Add(newPoint.Index);
                                result.Add(p2.Index);
                                result.Add(top.Index);
                            }
                            else
                            {
                                result.Add(newPoint.Index);
                                result.Add(top.Index);
                                result.Add(p2.Index);
                            }
                        }
                        // If more Points are on the Stack,
                        // Push the Point back again, to be able to form the Triangles
                        if (pointStack.Count != 0)
                        {
                            pointStack.Push(top);
                        }
                    }
                    // Push the last to Points on the Stack
                    pointStack.Push(events[i - 1]);
                    pointStack.Push(newPoint);
                }
                // If the newPoint is on the same Side (i.e. Chain)
                else
                {
                    // Get to Point on the Stack
                    top = pointStack.Pop();
                    var p2 = top;

                    // Determine this Point's Chain (left or right)
                    if (left.Next == newPoint && right.Last == newPoint)
                    {
                        if (top.Last == newPoint)
                        {
                            right = newPoint;
                        }
                        else if (top.Next == newPoint)
                        {
                            left = newPoint;
                        }
                        else
                        {
                            throw new HelixToolkitException("Triangulation error");
                        }
                    }
                    else if (left.Next == newPoint)
                    {
                        left = newPoint;
                    }
                    else if (right.Last == newPoint)
                    {
                        right = newPoint;
                    }

                    while (pointStack.Count != 0)
                    {
                        // If the Triangle is possible, add it to the result (Point Order depends on the Side)
                        if (right == newPoint && isCCW(new List <Point> {
                            newPoint.Point, p2.Point, pointStack.Peek().Point
                        }))
                        {
                            top = pointStack.Pop();
                            result.Add(newPoint.Index);
                            result.Add(p2.Index);
                            result.Add(top.Index);
                            p2 = top;
                        }
                        else if (left == newPoint && !isCCW(new List <Point> {
                            newPoint.Point, p2.Point, pointStack.Peek().Point
                        }))
                        {
                            top = pointStack.Pop();
                            result.Add(newPoint.Index);
                            result.Add(top.Index);
                            result.Add(p2.Index);
                            p2 = top;
                        }
                        // No Triangle possible, just leave the Loop
                        else
                        {
                            break;
                        }
                    }
                    // Push the last two Points on the Stack
                    pointStack.Push(p2);
                    pointStack.Push(newPoint);
                }
            }
            // Return the Triangulation
            return(result);
        }