// This calculates the relative angle between two lines private double CalculateRelativeAngle(Linedef a, Linedef b) { // Determine angles double ana = a.Angle; if (a.End == basevertex) { ana += Angle2D.PI; } double anb = b.Angle; if (b.End == basevertex) { anb += Angle2D.PI; } // Take the difference from angles double n = Angle2D.Difference(ana, anb); // Get line end vertices a and b that are not connected to basevertex Vector2D va = (a.Start == basevertex ? a.End.Position : a.Start.Position); Vector2D vb = (b.Start == basevertex ? b.End.Position : b.Start.Position); // Check to which side the angle goes and adjust angle as needed double s = Line2D.GetSideOfLine(va, vb, basevertex.Position); if (((s < 0) && front) || ((s > 0) && !front)) { n = Angle2D.PI2 - n; } // Return result return(n); }
// This checks if a point is inside a triangle // When the point is on an edge of the triangle, it depends on the lines // adjacent to the point if it is considered inside or not // NOTE: vertices in t must be in clockwise order! private static bool PointInsideTriangle(EarClipVertex[] t, LinkedListNode <EarClipVertex> p) { // If the triangle has no area, there can never be a point inside if (TriangleHasArea(t)) { float lineside01 = Line2D.GetSideOfLine(t[0].Position, t[1].Position, p.Value.Position); float lineside12 = Line2D.GetSideOfLine(t[1].Position, t[2].Position, p.Value.Position); float lineside20 = Line2D.GetSideOfLine(t[2].Position, t[0].Position, p.Value.Position); float u_on_line = 0.5f; // If point p is on the line of an edge, find out where on the edge segment p is. if (lineside01 == 0.0f) { u_on_line = Line2D.GetNearestOnLine(t[0].Position, t[1].Position, p.Value.Position); } else if (lineside12 == 0.0f) { u_on_line = Line2D.GetNearestOnLine(t[1].Position, t[2].Position, p.Value.Position); } else if (lineside20 == 0.0f) { u_on_line = Line2D.GetNearestOnLine(t[2].Position, t[0].Position, p.Value.Position); } // If any of the lineside results are 0 then that means the point p lies on that edge and we // need to test if the lines adjacent to the point p are in the triangle or not. // If the lines are intersecting the triangle, we also consider the point inside. if ((lineside01 == 0.0f) || (lineside12 == 0.0f) || (lineside20 == 0.0f)) { // When the point p is outside the edge segment, then it is not inside the triangle if ((u_on_line < 0.0f) || (u_on_line > 1.0f)) { return(false); } // Point p is on an edge segment. We'll have to decide by it's lines if we call it inside or outside the triangle. LinkedListNode <EarClipVertex> p1 = p.Previous ?? p.List.Last; LinkedListNode <EarClipVertex> p2 = p.Next ?? p.List.First; if (LineInsideTriangle(t, p.Value.Position, p1.Value.Position)) { return(true); } if (LineInsideTriangle(t, p.Value.Position, p2.Value.Position)) { return(true); } return(false); } else { return((lineside01 < 0.0f) && (lineside12 < 0.0f) && (lineside20 < 0.0f)); } } else { return(false); } }
// This calculates the relative angle between two sides private float CalculateRelativeAngle(Sidedef a, Sidedef b) { float s, n, ana, anb; Vector2D va, vb; bool dir; // Determine angles ana = a.Line.Angle; if (a.Line.End == basevertex) { ana += Angle2D.PI; } anb = b.Line.Angle; if (b.Line.End == basevertex) { anb += Angle2D.PI; } // Take the difference from angles n = Angle2D.Difference(ana, anb); // Get line end vertices a and b that are not connected to basevertex if (a.Line.Start == basevertex) { va = a.Line.End.Position; } else { va = a.Line.Start.Position; } if (b.Line.Start == basevertex) { vb = b.Line.End.Position; } else { vb = b.Line.Start.Position; } // Determine rotation direction dir = baseside.IsFront; if (baseside.Line.End == basevertex) { dir = !dir; } // Check to which side the angle goes and adjust angle as needed s = Line2D.GetSideOfLine(va, vb, basevertex.Position); if ((s < 0) && dir) { n = Angle2D.PI2 - n; } if ((s > 0) && !dir) { n = Angle2D.PI2 - n; } // Return result return(n); }
public double GetSideOfLine(Vector2D p) { return(Line2D.GetSideOfLine(v1, v2, p)); }
// This checks if a vertex is reflex (corner > 180 deg) or convex (corner < 180 deg) private static bool IsReflex(EarClipVertex[] t) { // Return true when corner is > 180 deg return(Line2D.GetSideOfLine(t[0].Position, t[2].Position, t[1].Position) < 0.0f); }
// This checks if a line is inside a triangle (touching the triangle is allowed) // NOTE: We already know p1 is on an edge segment of the triangle private static bool LineInsideTriangle(EarClipVertex[] t, Vector2D p1, Vector2D p2) { float s01 = Line2D.GetSideOfLine(t[0].Position, t[1].Position, p2); float s12 = Line2D.GetSideOfLine(t[1].Position, t[2].Position, p2); float s20 = Line2D.GetSideOfLine(t[2].Position, t[0].Position, p2); float p2_on_edge = 2.0f; // somewhere outside the 0 .. 1 range float p1_on_same_edge = 2.0f; // Test if p2 is inside the triangle if ((s01 < 0.0f) && (s12 < 0.0f) && (s20 < 0.0f)) { // Line is inside triangle, because p2 is return(true); } // Test if p2 is on an edge of the triangle and if it is we would // like to know where on the edge segment p2 is else if (s01 == 0.0f) { p2_on_edge = Line2D.GetNearestOnLine(t[0].Position, t[1].Position, p2); p1_on_same_edge = Line2D.GetSideOfLine(t[0].Position, t[1].Position, p1); } else if (s12 == 0.0f) { p2_on_edge = Line2D.GetNearestOnLine(t[1].Position, t[2].Position, p2); p1_on_same_edge = Line2D.GetSideOfLine(t[1].Position, t[2].Position, p1); } else if (s20 == 0.0f) { p2_on_edge = Line2D.GetNearestOnLine(t[2].Position, t[0].Position, p2); p1_on_same_edge = Line2D.GetSideOfLine(t[2].Position, t[0].Position, p1); } // Is p2 actually on the edge segment? if ((p2_on_edge >= 0.0f) && (p2_on_edge <= 1.0f)) { // If p1 is on the same edge (or the unlimited line of that edge) // then the line is not inside this triangle. if (p1_on_same_edge == 0.0f) { return(false); } } // Do a complete line-triangle intersection test // We already know p1 is not inside the triangle (possibly on an edge) Line2D p = new Line2D(p1, p2); Line2D t01 = new Line2D(t[0].Position, t[1].Position); Line2D t12 = new Line2D(t[1].Position, t[2].Position); Line2D t20 = new Line2D(t[2].Position, t[0].Position); float pu, pt; // Test intersections t01.GetIntersection(p, out pu, out pt); if (!float.IsNaN(pu) && (pu >= 0.0f) && (pu <= 1.0f) && (pt >= 0.0f) && (pt <= 1.0f)) { return(true); } t12.GetIntersection(p, out pu, out pt); if (!float.IsNaN(pu) && (pu >= 0.0f) && (pu <= 1.0f) && (pt >= 0.0f) && (pt <= 1.0f)) { return(true); } t20.GetIntersection(p, out pu, out pt); if (!float.IsNaN(pu) && (pu >= 0.0f) && (pu <= 1.0f) && (pt >= 0.0f) && (pt <= 1.0f)) { return(true); } return(false); }
// This checks if a given ear is a valid (no intersections from reflex vertices) private static bool CheckValidEar(EarClipVertex[] t, LinkedList <EarClipVertex> reflexes) { //mxd Vector2D pos0 = t[0].Position; Vector2D pos1 = t[1].Position; Vector2D pos2 = t[2].Position; Vector2D vpos; LinkedListNode <EarClipVertex> p; // Go for all reflex vertices foreach (EarClipVertex rv in reflexes) { // Not one of the triangle corners? if ((rv.Position != pos0) && (rv.Position != pos1) && (rv.Position != pos2)) { // Return false on intersection // This checks if a point is inside a triangle // When the point is on an edge of the triangle, it depends on the lines // adjacent to the point if it is considered inside or not // NOTE: vertices in t must be in clockwise order! // If the triangle has no area, there can never be a point inside if (TriangleHasArea(t)) { //mxd pos0 = t[0].Position; pos1 = t[1].Position; pos2 = t[2].Position; p = rv.MainListNode; vpos = p.Value.Position; //mxd. Check bounds first... if (vpos.x < Math.Min(pos0.x, Math.Min(pos1.x, pos2.x)) || vpos.x > Math.Max(pos0.x, Math.Max(pos1.x, pos2.x)) || vpos.y < Math.Min(pos0.y, Math.Min(pos1.y, pos2.y)) || vpos.y > Math.Max(pos0.y, Math.Max(pos1.y, pos2.y))) { continue; } double lineside01 = Line2D.GetSideOfLine(pos0, pos1, vpos); double lineside12 = Line2D.GetSideOfLine(pos1, pos2, vpos); double lineside20 = Line2D.GetSideOfLine(pos2, pos0, vpos); double u_on_line = 0.5f; // If point p is on the line of an edge, find out where on the edge segment p is. if (lineside01 == 0.0f) { u_on_line = Line2D.GetNearestOnLine(pos0, pos1, vpos); } else if (lineside12 == 0.0f) { u_on_line = Line2D.GetNearestOnLine(pos1, pos2, vpos); } else if (lineside20 == 0.0f) { u_on_line = Line2D.GetNearestOnLine(pos2, pos0, vpos); } // If any of the lineside results are 0 then that means the point p lies on that edge and we // need to test if the lines adjacent to the point p are in the triangle or not. // If the lines are intersecting the triangle, we also consider the point inside. if (lineside01 == 0.0f || lineside12 == 0.0f || lineside20 == 0.0f) { // When the point p is outside the edge segment, then it is not inside the triangle if (u_on_line < 0.0f || u_on_line > 1.0f) { continue; } // Point p is on an edge segment. We'll have to decide by it's lines if we call it inside or outside the triangle. LinkedListNode <EarClipVertex> p1 = p.Previous ?? p.List.Last; if (LineInsideTriangle(t, vpos, p1.Value.Position)) { return(false); } LinkedListNode <EarClipVertex> p2 = p.Next ?? p.List.First; if (LineInsideTriangle(t, vpos, p2.Value.Position)) { return(false); } continue; } if (lineside01 < 0.0f && lineside12 < 0.0f && lineside20 < 0.0f) { return(false); } } } } // Valid ear! return(true); }
public float GetSideOfLine(Vector2D p) { return(Line2D.GetSideOfLine(v1, v2, p)); }