// 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 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); }
// This clips a polygon and returns the triangles // The polygon may not have any holes or islands // See: http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf private int DoEarClip(EarClipPolygon poly, List <Vector2D> verticeslist, List <Sidedef> sidedefslist) { LinkedList <EarClipVertex> verts = new LinkedList <EarClipVertex>(); List <EarClipVertex> convexes = new List <EarClipVertex>(poly.Count); LinkedList <EarClipVertex> reflexes = new LinkedList <EarClipVertex>(); LinkedList <EarClipVertex> eartips = new LinkedList <EarClipVertex>(); LinkedListNode <EarClipVertex> n2; EarClipVertex[] t; int countvertices = 0; // Go for all vertices to fill list foreach (EarClipVertex vec in poly) { vec.SetVertsLink(verts.AddLast(vec)); } // Remove any zero-length lines, these will give problems LinkedListNode <EarClipVertex> n1 = verts.First; do { // Continue until adjacent zero-length lines are removed n2 = n1.Next ?? verts.First; Vector2D d = n1.Value.Position - n2.Value.Position; while ((Math.Abs(d.x) < 0.00001f) && (Math.Abs(d.y) < 0.00001f)) { n2.Value.Remove(); n2 = n1.Next ?? verts.First; if (n2 != null) { d = n1.Value.Position - n2.Value.Position; } else { break; } } // Next! n1 = n2; }while(n1 != verts.First); // Optimization: Vertices which have lines with the // same angle are useless. Remove them! n1 = verts.First; while (n1 != null) { // Get the next vertex n2 = n1.Next; // Get triangle for v t = GetTriangle(n1.Value); // Check if both lines have the same angle Line2D a = new Line2D(t[0].Position, t[1].Position); Line2D b = new Line2D(t[1].Position, t[2].Position); if (Math.Abs(Angle2D.Difference(a.GetAngle(), b.GetAngle())) < 0.00001f) { // Same angles, remove vertex n1.Value.Remove(); } // Next! n1 = n2; } // Go for all vertices to determine reflex or convex foreach (EarClipVertex vv in verts) { // Add to reflex or convex list if (IsReflex(GetTriangle(vv))) { vv.AddReflex(reflexes); } else { convexes.Add(vv); } } // Go for all convex vertices to see if they are ear tips foreach (EarClipVertex cv in convexes) { // Add when this is a valid ear t = GetTriangle(cv); if (CheckValidEar(t, reflexes)) { cv.AddEarTip(eartips); } } #if DEBUG if (OnShowPolygon != null) { OnShowPolygon(verts); } #endif // Process ears until done while ((eartips.Count > 0) && (verts.Count > 2)) { // Get next ear EarClipVertex v = eartips.First.Value; t = GetTriangle(v); // Only save this triangle when it has an area if (TriangleHasArea(t)) { // Add ear as triangle AddTriangleToList(t, verticeslist, sidedefslist, (verts.Count == 3)); countvertices += 3; } // Remove this ear from all lists v.Remove(); EarClipVertex v1 = t[0]; EarClipVertex v2 = t[2]; #if DEBUG if (TriangleHasArea(t)) { if (OnShowEarClip != null) { OnShowEarClip(t, verts); } } #endif // Test first neighbour EarClipVertex[] t1 = GetTriangle(v1); //bool t1a = true; //TriangleHasArea(t1); if (/*t1a && */ IsReflex(t1)) { // List as reflex if not listed yet if (!v1.IsReflex) { v1.AddReflex(reflexes); } v1.RemoveEarTip(); } else { // Remove from reflexes v1.RemoveReflex(); } // Test second neighbour EarClipVertex[] t2 = GetTriangle(v2); //bool t2a = true; //TriangleHasArea(t2); if (/*t2a && */ IsReflex(t2)) { // List as reflex if not listed yet if (!v2.IsReflex) { v2.AddReflex(reflexes); } v2.RemoveEarTip(); } else { // Remove from reflexes v2.RemoveReflex(); } // Check if any neightbour have become a valid or invalid ear if (!v1.IsReflex && (/*!t1a || */ CheckValidEar(t1, reflexes))) { v1.AddEarTip(eartips); } else { v1.RemoveEarTip(); } if (!v2.IsReflex && (/*!t2a || */ CheckValidEar(t2, reflexes))) { v2.AddEarTip(eartips); } else { v2.RemoveEarTip(); } } #if DEBUG if (OnShowRemaining != null) { OnShowRemaining(verts); } #endif // Dispose remaining vertices foreach (EarClipVertex ecv in verts) { ecv.Dispose(); } // Return the number of vertices in the result return(countvertices); }