Exemple #1
0
        // 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));
 }