/// <summary> /// For a Point, last used Edge and possible Edges, retrieve the best next Edge /// </summary> /// <param name="point">The current Point</param> /// <param name="lastEdge">The last used Edge</param> /// <param name="possibleEdges">The possible next Edges</param> /// <returns>Best next Edge</returns> internal static PolygonEdge BestEdge(PolygonPoint point, PolygonEdge lastEdge, List <PolygonEdge> possibleEdges) { // If just Starting, return the first possible Edge of the Point // If only one possibility, return that if ((lastEdge.PointOne == null && lastEdge.PointTwo == null) || possibleEdges.Count == 1) { return(possibleEdges[0]); } // Variables needed to determine the next Edge var bestEdge = possibleEdges[0]; var bestAngle = (float)Math.PI * 2; // Vector from last Point to current Point var lastVector = (lastEdge.PointTwo.Point - lastEdge.PointOne.Point); lastVector.Normalize(); // Using CCW Point Order, so the left Vector always points towards the Polygon Center var insideVector = new Point(-lastVector.Y, lastVector.X); // Check all possible Edges foreach (var possibleEdge in possibleEdges) { // Next Edge Vector var edgeVector = (possibleEdge.PointTwo.Point - possibleEdge.PointOne.Point); edgeVector.Normalize(); // Dot determines if the Vector also points towards the Polygon Center or not (> 0, yes, < 0, no) var dot = insideVector.X * edgeVector.X + insideVector.Y * edgeVector.Y; // Cos represents the Angle between the last Edge and the next Edge var cos = lastVector.X * edgeVector.X + lastVector.Y * edgeVector.Y; var angle = 0f; // Depending on the Dot-Value, calculate the actual "inner" Angle if ((insideVector.X * edgeVector.X + insideVector.Y * edgeVector.Y) > 0) { angle = (float)Math.PI - (float)Math.Acos(cos); } else { angle = (float)Math.PI + (float)Math.Acos(cos); } // Replace the old Values if a better Edge was found if (angle < bestAngle) { bestAngle = angle; bestEdge = possibleEdge; } } return(bestEdge); }
/// <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> /// Constructor that takes both Points of the Edge /// </summary> /// <param name="one">The Startpoint</param> /// <param name="two">The Endpoint</param> internal PolygonEdge(PolygonPoint one, PolygonPoint two) { this.mPointOne = one; this.mPointTwo = two; }
/// <summary> /// Constructor taking an Edge and a Helper /// </summary> /// <param name="edge">The Edge of the StatusHelperElement</param> /// <param name="point">The Helper for the Edge of the StatusHelperElement</param> internal StatusHelperElement(PolygonEdge edge, PolygonPoint point) { this.Edge = edge; this.Helper = point; }