Exemplo n.º 1
0
        /// <summary>
        /// Calculate the Diagonals to add inside the Polygon.
        /// </summary>
        /// <param name="events">The Events in sorted Form</param>
        /// <param name="sweepDown">True in the first Stage (sweeping down), false in the following Stages (sweeping up)</param>
        /// <returns></returns>
        private static List <Tuple <int, int> > CalculateDiagonals(List <PolygonPoint> events, Boolean sweepDown = true)
        {
            // Diagonals to add to the Polygon to make it monotone after the Down- and Up-Sweeps
            var diagonals = new List <Tuple <int, int> >();

            // Construct Status and Helper, a List of Edges left of every Point of the Polygon
            // by shooting a Ray from the Vertex to the left.
            // The Helper Point of that Edge will be used to create Monotone Polygons
            // by adding Diagonals from/to Split- and Merge-Points
            var statusAndHelper = new StatusHelper();

            // Sweep through the Polygon using the sorted Polygon Points
            for (int i = 0; i < events.Count; i++)
            {
                var ev = events[i];
                // Get the Class of this event (depending on the sweeping direction)
                var evClass = ev.PointClass(!sweepDown);

                // Temporary StatusHelperElement
                StatusHelperElement she = null;

                // Handle the different Point-Classes
                switch (evClass)
                {
                case PolygonPointClass.Start:
                    // Just add the left Edge (depending on the sweeping direction)
                    statusAndHelper.Add(new StatusHelperElement(sweepDown ? ev.EdgeTwo : ev.EdgeOne, ev));
                    break;

                case PolygonPointClass.Stop:
                    // Just remove the left Edge (depending on the sweeping direction)
                    statusAndHelper.Remove(sweepDown ? ev.EdgeOne : ev.EdgeTwo);
                    break;

                case PolygonPointClass.Regular:
                    // If the Polygon is positioned on the right Side of this Event
                    if (ev.Last > ev.Next)
                    {
                        // Replace the corresponding (old) StatusHelperElement with the new one
                        statusAndHelper.Remove(sweepDown ? ev.EdgeOne : ev.EdgeTwo);
                        statusAndHelper.Add(new StatusHelperElement(sweepDown ? ev.EdgeTwo : ev.EdgeOne, ev));
                    }
                    else
                    {
                        // Search Edge left of the Event and set Event as it's Helper
                        she        = statusAndHelper.SearchLeft(ev);
                        she.Helper = ev;
                    }
                    break;

                case PolygonPointClass.Merge:
                    // Just remove the left Edge (depending on the sweeping direction)
                    statusAndHelper.Remove(sweepDown ? ev.EdgeOne : ev.EdgeTwo);
                    // Search Edge left of the Event and set Event as it's Helper
                    she        = statusAndHelper.SearchLeft(ev);
                    she.Helper = ev;
                    break;

                case PolygonPointClass.Split:
                    // Search Edge left of the Event
                    she = statusAndHelper.SearchLeft(ev);
                    // Chose diagonal from Helper of Edge to Event.
                    var minP     = Math.Min(she.Helper.Index, ev.Index);
                    var maxP     = Math.Max(she.Helper.Index, ev.Index);
                    var diagonal = new Tuple <int, int>(minP, maxP);
                    diagonals.Add(diagonal);

                    // Replace the Helper of the StatusHelperElement by Event
                    she.Helper = ev;
                    // Insert the right Edge from Event
                    statusAndHelper.Add(new StatusHelperElement(sweepDown ? ev.EdgeTwo : ev.EdgeOne, ev));
                    break;
                }
            }
            return(diagonals);
        }