/// <summary> /// Searches the nearest StatusHelperElement from the given Point /// </summary> /// <param name="point">The Point to search a StatusHelperElement for</param> /// <returns>The nearest StatusHelperElement that is positioned left of the Poin</returns> internal StatusHelperElement SearchLeft(PolygonPoint point) { // The found StatusHelperElement and the Distance Variables StatusHelperElement result = null; var dist = Double.PositiveInfinity; // Search for the right StatusHelperElement foreach (var she in this.EdgesHelpers) { // Calculate the x-Coordinate of the Intersection between // a horizontal Line from the Point to the Left and the Edge of the StatusHelperElement Double xValue = Double.NaN; if (point.Y == she.Edge.PointOne.Y) { xValue = she.Edge.PointOne.X; } else if (point.Y == she.Edge.PointTwo.Y) { xValue = she.Edge.PointTwo.X; } else { xValue = she.Edge.PointOne.X + ((point.Y - she.Edge.PointOne.Y) / (she.Edge.PointTwo.Y - she.Edge.PointOne.Y)) * (she.Edge.PointTwo.X - she.Edge.PointOne.X); } // If the xValue is smaller than or equal to the Point's x-Coordinate // (i.e. it lies on the left Side of it - allows a small Error) if (xValue <= (point.X + SweepLinePolygonTriangulator.Epsilon)) { // Calculate the Distance var sheDist = point.X - xValue; // Update, if the Distance is smaller than a previously found Result if (sheDist < dist) { dist = sheDist; result = she; } } } // Return the nearest found StatusHelperElement return(result); }
/// <summary> /// Searches the nearest StatusHelperElement from the given Point /// </summary> /// <param name="point">The Point to search a StatusHelperElement for</param> /// <returns>The nearest StatusHelperElement that is positioned left of the Poin</returns> internal StatusHelperElement SearchLeft(PolygonPoint point) { // The found StatusHelperElement and the Distance Variables StatusHelperElement result = null; var dist = Double.PositiveInfinity; var px = point.X; var py = point.Y; // Search for the right StatusHelperElement foreach (var she in this.EdgesHelpers) { // No need to calculate the X-Value if (she.MinX > px) { continue; } // Calculate the x-Coordinate of the Intersection between // a horizontal Line from the Point to the Left and the Edge of the StatusHelperElement var xValue = she.Edge.PointOne.X + (py - she.Edge.PointOne.Y) * she.Factor; // If the xValue is smaller than or equal to the Point's x-Coordinate // (i.e. it lies on the left Side of it - allows a small Error) if (xValue <= (px + SweepLinePolygonTriangulator.Epsilon)) { // Calculate the Distance var sheDist = px - xValue; // Update, if the Distance is smaller than a previously found Result if (sheDist < dist) { dist = sheDist; result = she; } } } // Return the nearest found StatusHelperElement return(result); }
/// <summary> /// Adds a StatusHelperElement to the List /// </summary> /// <param name="element"></param> internal void Add(StatusHelperElement element) { this.EdgesHelpers.Add(element); }
/// <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); }