public Vector2D GetCoordinatesAt(double u) { return(Line2D.GetCoordinatesAt(v1, v2, u)); }
// This finds the cut coordinates and splits the other poly with inner vertices private static void SplitOuterWithInner(LinkedListNode <EarClipVertex> start, EarClipPolygon p) { LinkedListNode <EarClipVertex> insertbefore = null; float foundu = float.MaxValue; Vector2D foundpos = new Vector2D(); // Create a line from start that goes beyond the right most vertex of p LinkedListNode <EarClipVertex> pr = FindRightMostVertex(p); float startx = start.Value.Position.x; float endx = pr.Value.Position.x + 10.0f; Line2D starttoright = new Line2D(start.Value.Position, new Vector2D(endx, start.Value.Position.y)); // Calculate a small bonus (0.1 mappixel) float bonus = starttoright.GetNearestOnLine(new Vector2D(start.Value.Position.x + 0.1f, start.Value.Position.y)); // Go for all lines in the outer polygon LinkedListNode <EarClipVertex> v1 = p.Last; LinkedListNode <EarClipVertex> v2 = p.First; while (v2 != null) { // Check if the line goes between startx and endx if ((v1.Value.Position.x > startx || v2.Value.Position.x > startx) && (v1.Value.Position.x < endx || v2.Value.Position.x < endx)) { // Find intersection Line2D pl = new Line2D(v1.Value.Position, v2.Value.Position); float u, ul; pl.GetIntersection(starttoright, out u, out ul); if (float.IsNaN(u)) { // We have found a line that is perfectly horizontal // (parallel to the cut scan line) Check if the line // is overlapping the cut scan line. if (v1.Value.Position.y == start.Value.Position.y) { // This is an exceptional situation which causes a bit of a problem, because // this could be a previously made cut, which overlaps another line from the // same cut and we have to determine which of the two we will join with. If we // pick the wrong one, the polygon is no longer valid and triangulation will fail. // Calculate distance of each vertex in units u = starttoright.GetNearestOnLine(v1.Value.Position); ul = starttoright.GetNearestOnLine(v2.Value.Position); // Rule out vertices before the scan line if (u < 0.0f) { u = float.MaxValue; } if (ul < 0.0f) { ul = float.MaxValue; } float insert_u = Math.Min(u, ul); Vector2D inserpos = starttoright.GetCoordinatesAt(insert_u); // Check in which direction the line goes. if (v1.Value.Position.x > v2.Value.Position.x) { // The line goes from right to left (towards our start point) // so we must always insert our cut after this line. // If the next line goes up, we consider this a better candidate than // a horizontal line that goes from left to right (the other cut line) // so we give it a small bonus. LinkedListNode <EarClipVertex> v3 = v2.Next ?? v2.List.First; if (v3.Value.Position.y < v2.Value.Position.y) { insert_u -= bonus; } // Remember this when it is a closer match if (insert_u <= foundu) { insertbefore = v2.Next ?? v2.List.First; foundu = insert_u; foundpos = inserpos; } } else { // The line goes from left to right (away from our start point) // so we must always insert our cut before this line. // If the previous line goes down, we consider this a better candidate than // a horizontal line that goes from right to left (the other cut line) // so we give it a small bonus. LinkedListNode <EarClipVertex> v3 = v1.Previous ?? v1.List.Last; if (v3.Value.Position.y > v1.Value.Position.y) { insert_u -= bonus; } // Remember this when it is a closer match if (insert_u <= foundu) { insertbefore = v2; foundu = insert_u; foundpos = inserpos; } } } } // Found a closer match? else if ((ul >= 0.0f) && (ul <= 1.0f) && (u > 0.0f) && (u <= foundu)) { // Found a closer intersection insertbefore = v2; foundu = u; foundpos = starttoright.GetCoordinatesAt(u); } } // Next v1 = v2; v2 = v2.Next; } // Found anything? if (insertbefore != null) { Sidedef sd = (insertbefore.Previous == null) ? insertbefore.List.Last.Value.Sidedef : insertbefore.Previous.Value.Sidedef; // Find the position where we have to split the outer polygon EarClipVertex split = new EarClipVertex(foundpos, null); // Insert manual split vertices p.AddBefore(insertbefore, new EarClipVertex(split, sd)); // Start inserting from the start (do I make sense this time?) v1 = start; do { // Insert inner polygon vertex p.AddBefore(insertbefore, new EarClipVertex(v1.Value)); v1 = (v1.Next ?? v1.List.First); } while(v1 != start); // Insert manual split vertices p.AddBefore(insertbefore, new EarClipVertex(start.Value, sd)); if (split.Position != insertbefore.Value.Position) { p.AddBefore(insertbefore, new EarClipVertex(split, sd)); } } }