Ejemplo n.º 1
0
        /// <summary>
        /// Determines whether or not a point is contained within a circle.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The test is inclusive of the circle boundary.
        /// </para>
        /// </remarks>
        /// <param name="point">The point to test.</param>
        /// <param name="circle">The center point of the circle.</param>
        /// <param name="radius">The radius of the circle.</param>
        /// <returns>True if the point is contained within the circle.</returns>
        public static bool Contains(Vector2 point, Vector2 circle, float radius)
        {
            float dx = point.x - circle.x;
            float dy = point.y - circle.y;

            return((dx * dx + dy * dy) <= radius * radius);
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Determines whether or not two circles intersect each other.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Test is inclusive of the circle boundary.
 /// </para>
 /// <para>
 /// Containment of one circle by another is considered intersection.
 /// </para>
 /// </remarks>
 /// <param name="acenter">The center point of circle A.</param>
 /// <param name="aradius">The radius of circle A.</param>
 /// <param name="bcenter">The center point of circle B.</param>
 /// <param name="bradius">The radius of Circle B.</param>
 /// <returns>True if the circles intersect.</returns>
 public static bool Intersects(Vector2 acenter, float aradius
     , Vector2 bcenter, float bradius)
 {
     float dx = acenter.x - bcenter.x;
     float dy = acenter.y - bcenter.y;
     return (dx * dx + dy * dy) <= (aradius + bradius) * (aradius + bradius);
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns the square of the distance between two points.
        /// </summary>
        /// <param name="a">Point A.</param>
        /// <param name="b">Point B.</param>
        /// <returns>The square of the distance between the points.</returns>
        public static float GetDistanceSq(Vector2 a, Vector2 b)
        {
            float dx = a.x - b.x;
            float dy = a.y - b.y;

            return(dx * dx + dy * dy);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Returns the distance squared from point P to the nearest point on line AB.
        /// </summary>
        /// <param name="p">The point.</param>
        /// <param name="a">Point A on line AB.</param>
        /// <param name="b">Point B on line AB.</param>
        /// <returns>The distance squared from the point to line AB.</returns>
        public static float GetPointLineDistanceSq(Vector2 p, Vector2 a, Vector2 b)
        {
            /*
             * Reference:
             * http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
             *
             * The goal of the algorithm is to find the point on line AB that is
             * closest to P and then calculate the distance between P and that
             * point.
             */

            Vector2 deltaAB = b - a;
            Vector2 deltaAP = p - a;

            float segmentABLengthSq = deltaAB.x * deltaAB.x + deltaAB.y * deltaAB.y;

            if (segmentABLengthSq < MathUtil.Epsilon)
            {
                // AB is not a line segment.  So just return
                // distanceSq from P to A
                return(deltaAP.x * deltaAP.x + deltaAP.y * deltaAP.y);
            }

            float u = (deltaAP.x * deltaAB.x + deltaAP.y * deltaAB.y) / segmentABLengthSq;

            // The calculation in parenthesis is the location of the point on
            // the line segment.
            float deltaX = (a.x + u * deltaAB.x) - p.x;
            float deltaY = (a.y + u * deltaAB.y) - p.y;

            return(deltaX * deltaX + deltaY * deltaY);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Derives the normalized direction vector from point A to point B. (Costly method!)
        /// </summary>
        /// <param name="a">The starting point A.</param>
        /// <param name="b">The end point B.</param>
        /// <returns>
        /// The normalized direction vector for the vector pointing from point A to B.
        /// </returns>
        public static Vector2 GetDirectionAB(Vector2 a, Vector2 b)
        {
            // Subtract.
            Vector2 result = new Vector2(b.x - a.x, b.y - a.y);

            // Normalize.
            float length = (float)Math.Sqrt((result.x * result.x) + (result.y * result.y));

            if (length <= Epsilon)
            {
                length = 1;
            }

            result.x /= length;
            result.y /= length;

            if (Math.Abs(result.x) < Epsilon)
            {
                result.x = 0;
            }
            if (Math.Abs(result.y) < Epsilon)
            {
                result.y = 0;
            }

            return(result);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Determines whether or not two circles intersect each other.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Test is inclusive of the circle boundary.
        /// </para>
        /// <para>
        /// Containment of one circle by another is considered intersection.
        /// </para>
        /// </remarks>
        /// <param name="acenter">The center point of circle A.</param>
        /// <param name="aradius">The radius of circle A.</param>
        /// <param name="bcenter">The center point of circle B.</param>
        /// <param name="bradius">The radius of Circle B.</param>
        /// <returns>True if the circles intersect.</returns>
        public static bool Intersects(Vector2 acenter, float aradius
                                      , Vector2 bcenter, float bradius)
        {
            float dx = acenter.x - bcenter.x;
            float dy = acenter.y - bcenter.y;

            return((dx * dx + dy * dy) <= (aradius + bradius) * (aradius + bradius));
        }
Ejemplo n.º 7
0
 /// <summary>
 /// The absolute value of the returned value is two times the area of the triangle ABC.
 /// </summary>
 /// <remarks>
 /// <para>
 /// A positive return value indicates:
 /// </para>
 /// <ul>
 /// <li>Counterclockwise wrapping of the vertices.</li>
 /// <li>Vertex B lies to the right of line AC, looking from A toward C.</li>
 /// </ul>
 /// <para>A negative value indicates:</para>
 /// <ul>
 /// <li>Clockwise wrapping of the vertices.</li>
 /// <li>Vertex B lies to the left of line AC, looking from A toward C.</li>
 /// </ul>
 /// <para>
 /// A value of zero indicates that all points are collinear or represent the same point.
 /// </para>
 /// <para>
 /// This is a low cost method.
 /// </para>
 /// </remarks>
 /// <param name="a">Vertex A of triangle ABC.</param>
 /// <param name="b">Vertex B of triangle ABC</param>
 /// <param name="c">Vertex C of triangle ABC</param>
 /// <returns>
 /// The absolute value of the returned value is two times the area of the triangle ABC.
 /// </returns>
 public static float GetSignedAreaX2(Vector2 a, Vector2 b, Vector2 c)
 {
     // References:
     // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles
     // http://mathworld.wolfram.com/TriangleArea.html
     // (Search for "signed".)
     return((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y));
 }
Ejemplo n.º 8
0
        /// <summary>
        /// Determines whether or not the specified vectors are equal within the specified tolerance.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Change in beahvior:  Prior to version 0.4, the area of equality  for this method was
        /// an axis-aligned bounding box at the tip of the vector. As of version 0.4 the area of
        /// equality is a sphere. This change improves performance.
        /// </para>
        /// </remarks>
        /// <param name="u">Vector u.</param>
        /// <param name="v">Vector v</param>
        /// <param name="tolerance">The allowed tolerance. [Limit: >= 0]
        /// </param>
        /// <returns>
        /// True if the specified vectors are similar enough to be considered equal.
        /// </returns>
        public static bool SloppyEquals(Vector2 u, Vector2 v, float tolerance)
        {
            // Duplicating code for performance reasons.
            float dx = u.x - v.x;
            float dy = u.y - v.y;

            return((dx * dx + dy * dy) <= tolerance * tolerance);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Indicates whether or not line AB intersects line BC.
        /// </summary>
        /// <param name="a">Point A on line AB.</param>
        /// <param name="b">Point B on ling AB.</param>
        /// <param name="c">Point C on line CD.</param>
        /// <param name="d">Point D on line CD.</param>
        /// <returns>True if the two lines are either collinear or intersect at one point.</returns>
        public static bool LinesIntersect(Vector2 a, Vector2 b, Vector2 c, Vector2 d)
        {
            float numerator = ((a.y - c.y) * (d.x - c.x)) - ((a.x - c.x) * (d.y - c.y));
            float denominator = ((b.x - a.x) * (d.y - c.y)) - ((b.y - a.y) * (d.x - c.x));

            if (denominator == 0 && numerator != 0)
                // Lines are parallel.
                return false;

            // Lines are collinear or intersect at a single point.
            return true;  
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Returns the normalized vector that is perpendicular to line AB. (Costly method!)
        /// </summary>
        /// <remarks>
        /// <para>
        /// The direction of the vector will be to the right when viewed from point A to point B 
        /// along the line.
        /// </para>
        /// <para>
        /// Special Case: A zero length vector will be returned if the points are collocated.
        /// </para>
        /// </remarks>
        /// <param name="a">Point A on line AB.</param>
        /// <param name="b">Point B on line AB.</param>
        /// <returns>
        /// The normalized vector that is perpendicular to line AB, or a zero length vector if the 
        /// points are collocated.
        /// </returns>
        public static Vector2 GetNormalAB(Vector2 a, Vector2 b)
        {
            if (Vector2Util.SloppyEquals(a, b, MathUtil.Tolerance))
                // Points do not form a line.
                return new Vector2();

            Vector2 result = Vector2Util.GetDirectionAB(a, b);

            float origX = result.x;
            result.x = result.y;
            result.y = -origX;

            return result;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Scales the vector to the specified length. (Costly method!)
        /// </summary>
        /// <param name="v">A vector.</param>
        /// <param name="length">The length to scale the vector to.</param>
        /// <returns>A vector scaled to the specified length.</returns>
        public static Vector2 ScaleTo(Vector2 v, float length)
        {
            if (length == 0 || (v.x == 0 && v.y == 0))
            {
                return(new Vector2(0, 0));
            }

            float factor = (length / (float)(Math.Sqrt(v.x * v.x + v.y * v.y)));

            v.x *= factor;
            v.y *= factor;

            return(v);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Indicates whether or not line AB intersects line BC.
        /// </summary>
        /// <param name="a">Point A on line AB.</param>
        /// <param name="b">Point B on ling AB.</param>
        /// <param name="c">Point C on line CD.</param>
        /// <param name="d">Point D on line CD.</param>
        /// <returns>True if the two lines are either collinear or intersect at one point.</returns>
        public static bool LinesIntersect(Vector2 a, Vector2 b, Vector2 c, Vector2 d)
        {
            float numerator   = ((a.y - c.y) * (d.x - c.x)) - ((a.x - c.x) * (d.y - c.y));
            float denominator = ((b.x - a.x) * (d.y - c.y)) - ((b.y - a.y) * (d.x - c.x));

            if (denominator == 0 && numerator != 0)
            {
                // Lines are parallel.
                return(false);
            }

            // Lines are collinear or intersect at a single point.
            return(true);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Returns the distance squared from point P to the nearest point on line segment AB.
        /// </summary>
        /// <param name="p">The point.</param>
        /// <param name="a">Endpoint A of line segment AB.</param>
        /// <param name="b">Endpoing B of line segment AB.</param>
        /// <returns>The distance squared from the point to line segment AB.</returns>
        public static float GetPointSegmentDistanceSq(Vector2 p, Vector2 a, Vector2 b)
        {
            /*
             * Reference:
             * http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
             *
             * The goal of the algorithm is to find the point on line AB that
             * is closest to P and then calculate the distance between P and
             * that point.
             */

            Vector2 deltaAB = b - a;
            Vector2 deltaAP = p - a;

            float segmentABLengthSq = deltaAB.x * deltaAB.x + deltaAB.y * deltaAB.y;

            if (segmentABLengthSq < MathUtil.Epsilon)
            {
                // AB is not a line segment.  So just return
                // distanceSq from P to A
                return(deltaAP.x * deltaAP.x + deltaAP.y * deltaAP.y);
            }

            float u = (deltaAP.x * deltaAB.x + deltaAP.y * deltaAB.y) / segmentABLengthSq;

            if (u < 0)
            {
                // Closest point on line AB is outside segment AB and
                // closer to A. So return distanceSq from P to A.
                return(deltaAP.x * deltaAP.x + deltaAP.y * deltaAP.y);
            }
            else if (u > 1)
            {
                // Closest point on line AB is outside segment AB and closer
                // to B. So return distanceSq from P to B.
                return((p.x - b.x) * (p.x - b.x) + (p.y - b.y) * (p.y - b.y));
            }

            // Closest point on lineAB is inside segment AB.  So find the exact
            // point on AB and calculate the distanceSq from it to P.

            // The calculation in parenthesis is the location of the point on
            // the line segment.
            float deltaX = (a.x + u * deltaAB.x) - p.x;
            float deltaY = (a.y + u * deltaAB.y) - p.y;

            return(deltaX * deltaX + deltaY * deltaY);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Determines the relationship between lines AB and CD.
        /// </summary>
        /// <remarks>
        /// <para>
        /// While this check is technically inclusive of segment end points, floating point errors
        /// can result in end point intersection being missed.  If this matters, a
        /// <see  cref="Vector2Util.SloppyEquals(Vector2, Vector2, float)">
        /// SloppyEquals</see> or similar test of the intersection point can be performed.
        /// </para>
        /// </remarks>
        /// <param name="a">Point A on line AB.</param>
        /// <param name="b">Point B on ling AB.</param>
        /// <param name="c">Point C on line CD.</param>
        /// <param name="d">Point D on line CD.</param>
        /// <param name="intersectPoint">The point of intersection, if applicable.</param>
        /// <returns>The relationship between lines AB and CD.</returns>
        public static LineRelType GetRelationship(Vector2 a, Vector2 b, Vector2 c, Vector2 d
                                                  , out Vector2 intersectPoint)
        {
            Vector2 deltaAB = b - a;
            Vector2 deltaCD = d - c;
            Vector2 deltaCA = a - c;

            float numerator   = (deltaCA.y * deltaCD.x) - (deltaCA.x * deltaCD.y);
            float denominator = (deltaAB.x * deltaCD.y) - (deltaAB.y * deltaCD.x);

            // Exit early if the lines do not intersect at a single point.
            if (denominator == 0)
            {
                intersectPoint = Vector2Util.Zero;
                if (numerator == 0)
                {
                    return(LineRelType.Collinear);
                }
                return(LineRelType.Parallel);
            }

            // Lines definitely intersect at a single point.

            float factorAB = numerator / denominator;
            float factorCD = ((deltaCA.y * deltaAB.x) - (deltaCA.x * deltaAB.y)) / denominator;

            intersectPoint =
                new Vector2(a.x + (factorAB * deltaAB.x), a.y + (factorAB * deltaAB.y));

            // Determine the type of intersection
            if ((factorAB >= 0.0f) &&
                (factorAB <= 1.0f) &&
                (factorCD >= 0.0f) &&
                (factorCD <= 1.0f))
            {
                return(LineRelType.SegmentsIntersect);
            }
            else if ((factorCD >= 0.0f) && (factorCD <= 1.0f))
            {
                return(LineRelType.ALineCrossesBSeg);
            }
            else if ((factorAB >= 0.0f) && (factorAB <= 1.0f))
            {
                return(LineRelType.BLineCrossesASeg);
            }

            return(LineRelType.LinesIntersect);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Returns the normalized vector that is perpendicular to line AB. (Costly method!)
        /// </summary>
        /// <remarks>
        /// <para>
        /// The direction of the vector will be to the right when viewed from point A to point B
        /// along the line.
        /// </para>
        /// <para>
        /// Special Case: A zero length vector will be returned if the points are collocated.
        /// </para>
        /// </remarks>
        /// <param name="a">Point A on line AB.</param>
        /// <param name="b">Point B on line AB.</param>
        /// <returns>
        /// The normalized vector that is perpendicular to line AB, or a zero length vector if the
        /// points are collocated.
        /// </returns>
        public static Vector2 GetNormalAB(Vector2 a, Vector2 b)
        {
            if (Vector2Util.SloppyEquals(a, b, MathUtil.Tolerance))
            {
                // Points do not form a line.
                return(new Vector2());
            }

            Vector2 result = Vector2Util.GetDirectionAB(a, b);

            float origX = result.x;

            result.x = result.y;
            result.y = -origX;

            return(result);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Returns true if the point is contained by the triangle.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The test is inclusive of the triangle edges.
        /// </para>
        /// </remarks>
        /// <param name="p">The point to test.</param>
        /// <param name="a">Vertex A of triangle ABC.</param>
        /// <param name="b">Vertex B of triangle ABC</param>
        /// <param name="c">Vertex C of triangle ABC</param>
        /// <returns>True if the point is contained by the triangle ABC.</returns>
        public static bool Contains(Vector2 p, Vector2 a, Vector2 b, Vector2 c)
        {
            Vector2 dirAB = b - a;
            Vector2 dirAC = c - a;
            Vector2 dirAP = p - a;

            float dotABAB = Vector2Util.Dot(dirAB, dirAB);
            float dotACAB = Vector2Util.Dot(dirAC, dirAB);
            float dotACAC = Vector2Util.Dot(dirAC, dirAC);
            float dotACAP = Vector2Util.Dot(dirAC, dirAP);
            float dotABAP = Vector2Util.Dot(dirAB, dirAP);

            float invDenom = 1 / (dotACAC * dotABAB - dotACAB * dotACAB);
            float u        = (dotABAB * dotACAP - dotACAB * dotABAP) * invDenom;
            float v        = (dotACAC * dotABAP - dotACAB * dotACAP) * invDenom;

            // Altered this slightly from the reference so that points on the
            // vertices and edges are considered to be inside the triangle.
            return((u >= 0) && (v >= 0) && (u + v <= 1));
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Returns true if the point is contained by the triangle.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The test is inclusive of the triangle edges.
        /// </para>
        /// </remarks>
        /// <param name="p">The point to test.</param>
        /// <param name="a">Vertex A of triangle ABC.</param>
        /// <param name="b">Vertex B of triangle ABC</param>
        /// <param name="c">Vertex C of triangle ABC</param>
        /// <returns>True if the point is contained by the triangle ABC.</returns>
        public static bool Contains(Vector2 p, Vector2 a, Vector2 b, Vector2 c)
        {
            Vector2 dirAB = b - a;
            Vector2 dirAC = c - a;
            Vector2 dirAP = p - a;

            float dotABAB = Vector2Util.Dot(dirAB, dirAB);
            float dotACAB = Vector2Util.Dot(dirAC, dirAB);
            float dotACAC = Vector2Util.Dot(dirAC, dirAC);
            float dotACAP = Vector2Util.Dot(dirAC, dirAP);
            float dotABAP = Vector2Util.Dot(dirAB, dirAP);

            float invDenom = 1 / (dotACAC * dotABAB - dotACAB * dotACAB);
            float u = (dotABAB * dotACAP - dotACAB * dotABAP) * invDenom;
            float v = (dotACAC * dotABAP - dotACAB * dotACAP) * invDenom;

            // Altered this slightly from the reference so that points on the 
            // vertices and edges are considered to be inside the triangle.
            return (u >= 0) && (v >= 0) && (u + v <= 1);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Derives the normalized direction vector from point A to point B. (Costly method!)
        /// </summary>
        /// <param name="a">The starting point A.</param>
        /// <param name="b">The end point B.</param>
        /// <returns>
        /// The normalized direction vector for the vector pointing from point A to B.
        /// </returns>
        public static Vector2 GetDirectionAB(Vector2 a, Vector2 b)
        {
            // Subtract.
            Vector2 result = new Vector2(b.x - a.x, b.y - a.y);
            
            // Normalize.
            float length = (float)Math.Sqrt((result.x * result.x) + (result.y * result.y));

            if (length <= Epsilon) 
                length = 1;
            
            result.x /= length;
            result.y /= length;
            
            if (Math.Abs(result.x) < Epsilon) 
                result.x = 0;
            if (Math.Abs(result.y) < Epsilon) 
                result.y = 0;    
            
            return result;
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Truncates the length of the vector to the specified value.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If the vector's length is longer than the specified value the length of the vector is
        /// scaled back to the specified length.
        /// </para>
        /// <para>
        /// If the vector's length is shorter than the specified value, it is not changed.
        /// </para>
        /// <para>
        /// This is a potentially costly method.
        /// </para>
        /// </remarks>
        /// <param name="v">The vector to truncate.</param>
        /// <param name="maxLength">The maximum allowed length of the resulting vector.</param>
        /// <returns>A vector with a length at or below the maximum length.</returns>
        public static Vector2 TruncateLength(Vector2 v, float maxLength)
        {
            if (maxLength == 0 || (v.x < float.Epsilon && v.y < float.Epsilon))
            {
                return(new Vector2(0, 0));
            }

            float csq = v.x * v.x + v.y * v.y;

            if (csq <= maxLength * maxLength)
            {
                return(v);
            }

            float factor = (float)(maxLength / Math.Sqrt(csq));

            v.x *= factor;
            v.y *= factor;

            return(v);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Normalizes the specified vector such that its length is equal to one. (Costly method!)
        /// </summary>
        /// <param name="v">A vector.</param>
        /// <returns>The normalized vector.</returns>
        public static Vector2 Normalize(Vector2 v)
        {
            float length = (float)Math.Sqrt(v.x * v.x + v.y * v.y);

            if (length <= Epsilon)
            {
                length = 1;
            }

            v.x /= length;
            v.y /= length;

            if (Math.Abs(v.x) < Epsilon)
            {
                v.x = 0;
            }
            if (Math.Abs(v.y) < Epsilon)
            {
                v.y = 0;
            }

            return(v);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Returns the distance squared from point P to the nearest point on line AB.
        /// </summary>
        /// <param name="p">The point.</param>
        /// <param name="a">Point A on line AB.</param>
        /// <param name="b">Point B on line AB.</param>
        /// <returns>The distance squared from the point to line AB.</returns>
        public static float GetPointLineDistanceSq(Vector2 p, Vector2 a, Vector2 b)
        {
            /*
             * Reference: 
             * http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
             * 
             * The goal of the algorithm is to find the point on line AB that is
             * closest to P and then calculate the distance between P and that 
             * point.
             */

            Vector2 deltaAB = b - a;
            Vector2 deltaAP = p - a;         
            
            float segmentABLengthSq =  deltaAB.x * deltaAB.x + deltaAB.y * deltaAB.y;
            
            if (segmentABLengthSq < MathUtil.Epsilon)
                // AB is not a line segment.  So just return
                // distanceSq from P to A
                return deltaAP.x * deltaAP.x + deltaAP.y * deltaAP.y;
                
            float u = (deltaAP.x * deltaAB.x + deltaAP.y * deltaAB.y) / segmentABLengthSq;
            
            // The calculation in parenthesis is the location of the point on 
            // the line segment.
            float deltaX = (a.x + u * deltaAB.x) - p.x;
            float deltaY = (a.y + u * deltaAB.y) - p.y;
        
            return deltaX * deltaX + deltaY * deltaY;
        }
Ejemplo n.º 22
0
 /// <summary>
 /// Returns the <a href="http://en.wikipedia.org/wiki/Dot_product" target="_blank">
 /// dot product</a> of the specified vectors. (u . v)
 /// </summary>
 /// <param name="u">Vector u</param>
 /// <param name="v">Vector v</param>
 /// <returns>The dot product of the specified vectors.</returns>
 public static float Dot(Vector2 u, Vector2 v)
 {
     return((u.x * v.x) + (u.y * v.y));
 }
        /// <summary>
        /// Normalizes the specified vector such that its length is equal to one. (Costly method!)
        /// </summary>
        /// <param name="v">A vector.</param>
        /// <returns>The normalized vector.</returns>
        public static Vector2 Normalize(Vector2 v)
        {
            float length = (float)Math.Sqrt(v.x * v.x + v.y * v.y);

            if (length <= Epsilon)
                length = 1;

            v.x /= length;
            v.y /= length;

            if (Math.Abs(v.x) < Epsilon)
                v.x = 0;
            if (Math.Abs(v.y) < Epsilon)
                v.y = 0;

            return v;
        }
        /// <summary>
        /// Scales the vector to the specified length. (Costly method!)
        /// </summary>
        /// <param name="v">A vector.</param>
        /// <param name="length">The length to scale the vector to.</param>
        /// <returns>A vector scaled to the specified length.</returns>
        public static Vector2 ScaleTo(Vector2 v, float length)
        {
            if (length == 0 || (v.x == 0 && v.y == 0))
                return new Vector2(0, 0);

            float factor = (length / (float)(Math.Sqrt(v.x * v.x + v.y * v.y)));

            v.x *= factor;
            v.y *= factor;

            return v;
        }
Ejemplo n.º 25
0
 /// <summary>
 /// The absolute value of the returned value is two times the area of the triangle ABC.
 /// </summary>
 /// <remarks>
 /// <para>
 /// A positive return value indicates:
 /// </para>
 /// <ul>
 /// <li>Counterclockwise wrapping of the vertices.</li>
 /// <li>Vertex B lies to the right of line AC, looking from A toward C.</li>
 /// </ul>
 /// <para>A negative value indicates:</para>
 /// <ul>
 /// <li>Clockwise wrapping of the vertices.</li>
 /// <li>Vertex B lies to the left of line AC, looking from A toward C.</li>
 /// </ul>
 /// <para>
 /// A value of zero indicates that all points are collinear or represent the same point.
 /// </para>
 /// <para>
 /// This is a low cost method.
 /// </para>
 /// </remarks>
 /// <param name="a">Vertex A of triangle ABC.</param>
 /// <param name="b">Vertex B of triangle ABC</param>
 /// <param name="c">Vertex C of triangle ABC</param>
 /// <returns>
 /// The absolute value of the returned value is two times the area of the triangle ABC.
 /// </returns>
 public static float GetSignedAreaX2(Vector2 a, Vector2 b, Vector2 c)
 {
     // References:
     // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles
     // http://mathworld.wolfram.com/TriangleArea.html 
     // (Search for "signed".)
     return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
 }
 /// <summary>
 /// Determines whether or not the specified vectors are equal within the specified tolerance.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Change in beahvior:  Prior to version 0.4, the area of equality  for this method was 
 /// an axis-aligned bounding box at the tip of the vector. As of version 0.4 the area of 
 /// equality is a sphere. This change improves performance.
 /// </para>
 /// </remarks>
 /// <param name="u">Vector u.</param>
 /// <param name="v">Vector v</param>
 /// <param name="tolerance">The allowed tolerance. [Limit: >= 0]
 /// </param>
 /// <returns>
 /// True if the specified vectors are similar enough to be considered equal.
 /// </returns>
 public static bool SloppyEquals(Vector2 u, Vector2 v, float tolerance)
 {
     // Duplicating code for performance reasons.
     float dx = u.x - v.x;
     float dy = u.y - v.y;
     return (dx * dx + dy * dy) <= tolerance * tolerance;
 }
Ejemplo n.º 27
0
 /// <summary>
 /// Determines whether or not a point is contained within a circle.
 /// </summary>
 /// <remarks>
 /// <para>
 /// The test is inclusive of the circle boundary.
 /// </para>
 /// </remarks>
 /// <param name="point">The point to test.</param>
 /// <param name="circle">The center point of the circle.</param>
 /// <param name="radius">The radius of the circle.</param>
 /// <returns>True if the point is contained within the circle.</returns>
 public static bool Contains(Vector2 point, Vector2 circle, float radius)
 {
     float dx = point.x - circle.x;
     float dy = point.y - circle.y;
     return (dx * dx + dy * dy) <= radius * radius;
 }
Ejemplo n.º 28
0
        /// <summary>
        /// Returns the distance squared from point P to the nearest point on line segment AB.
        /// </summary>
        /// <param name="p">The point.</param>
        /// <param name="a">Endpoint A of line segment AB.</param>
        /// <param name="b">Endpoing B of line segment AB.</param>
        /// <returns>The distance squared from the point to line segment AB.</returns>
        public static float GetPointSegmentDistanceSq(Vector2 p, Vector2 a, Vector2 b)
        {
            /*
             * Reference: 
             * http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
             * 
             * The goal of the algorithm is to find the point on line AB that 
             * is closest to P and then calculate the distance between P and 
             * that point.
             */

            Vector2 deltaAB = b - a;
            Vector2 deltaAP = p - a;    
            
            float segmentABLengthSq = deltaAB.x * deltaAB.x + deltaAB.y * deltaAB.y;
            
            if (segmentABLengthSq < MathUtil.Epsilon)
                // AB is not a line segment.  So just return
                // distanceSq from P to A
                return deltaAP.x * deltaAP.x + deltaAP.y * deltaAP.y;
                
            float u = (deltaAP.x * deltaAB.x + deltaAP.y * deltaAB.y) / segmentABLengthSq;
            
            if (u < 0)
                // Closest point on line AB is outside segment AB and 
                // closer to A. So return distanceSq from P to A.
                return deltaAP.x * deltaAP.x + deltaAP.y * deltaAP.y;
            else if (u > 1)
                // Closest point on line AB is outside segment AB and closer 
                // to B. So return distanceSq from P to B.
                return (p.x - b.x) * (p.x - b.x) + (p.y - b.y) * (p.y - b.y);
            
            // Closest point on lineAB is inside segment AB.  So find the exact
            // point on AB and calculate the distanceSq from it to P.
            
            // The calculation in parenthesis is the location of the point on 
            // the line segment.
            float deltaX = (a.x + u * deltaAB.x) - p.x;
            float deltaY = (a.y + u * deltaAB.y) - p.y;
        
            return deltaX * deltaX + deltaY * deltaY;
        }
        /// <summary>
        /// Truncates the length of the vector to the specified value.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If the vector's length is longer than the specified value the length of the vector is 
        /// scaled back to the specified length.
        /// </para>
        /// <para>
        /// If the vector's length is shorter than the specified value, it is not changed.
        /// </para>
        /// <para>
        /// This is a potentially costly method.
        /// </para>
        /// </remarks>
        /// <param name="v">The vector to truncate.</param>
        /// <param name="maxLength">The maximum allowed length of the resulting vector.</param>
        /// <returns>A vector with a length at or below the maximum length.</returns>
        public static Vector2 TruncateLength(Vector2 v, float maxLength)
        {
            if (maxLength == 0 || (v.x < float.Epsilon && v.y < float.Epsilon))
                return new Vector2(0, 0);

            float csq = v.x * v.x + v.y * v.y;

            if (csq <= maxLength * maxLength)
                return v;

            float factor = (float)(maxLength / Math.Sqrt(csq));

            v.x *= factor;
            v.y *= factor;

            return v;
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Determines the relationship between lines AB and CD.
        /// </summary>
        /// <remarks>
        /// <para>
        /// While this check is technically inclusive of segment end points, floating point errors
        /// can result in end point intersection being missed.  If this matters, a 
        /// <see  cref="Vector2Util.SloppyEquals(Vector2, Vector2, float)">
        /// SloppyEquals</see> or similar test of the intersection point can be performed.
        /// </para>
        /// </remarks>
        /// <param name="a">Point A on line AB.</param>
        /// <param name="b">Point B on ling AB.</param>
        /// <param name="c">Point C on line CD.</param>
        /// <param name="d">Point D on line CD.</param>
        /// <param name="intersectPoint">The point of intersection, if applicable.</param>
        /// <returns>The relationship between lines AB and CD.</returns>
        public static LineRelType GetRelationship(Vector2 a, Vector2 b, Vector2 c, Vector2 d
            , out Vector2 intersectPoint)
        {
            Vector2 deltaAB = b - a;
            Vector2 deltaCD = d - c;
            Vector2 deltaCA = a - c; 
            
            float numerator =  (deltaCA.y * deltaCD.x) - (deltaCA.x * deltaCD.y);
            float denominator = (deltaAB.x * deltaCD.y) - (deltaAB.y * deltaCD.x);

            // Exit early if the lines do not intersect at a single point.
            if (denominator == 0)
            {
                intersectPoint = Vector2Util.Zero;
                if (numerator == 0)
                    return LineRelType.Collinear;
                return LineRelType.Parallel;
            }

            // Lines definitely intersect at a single point.
            
            float factorAB = numerator / denominator;
            float factorCD = ((deltaCA.y * deltaAB.x) - (deltaCA.x * deltaAB.y)) / denominator;

            intersectPoint = 
                new Vector2(a.x + (factorAB * deltaAB.x), a.y + (factorAB * deltaAB.y));            

            // Determine the type of intersection
            if ((factorAB >= 0.0f) 
                && (factorAB <= 1.0f) 
                && (factorCD >= 0.0f) 
                && (factorCD <= 1.0f))
            {
                return LineRelType.SegmentsIntersect;
            }
            else if ((factorCD >= 0.0f) && (factorCD <= 1.0f))
            {
                return LineRelType.ALineCrossesBSeg;
            }
            else if ((factorAB >= 0.0f) && (factorAB <= 1.0f))
            {
                return LineRelType.BLineCrossesASeg;
            }

            return LineRelType.LinesIntersect;
        }
 /// <summary>
 /// Returns the square of the distance between two points.
 /// </summary>
 /// <param name="a">Point A.</param>
 /// <param name="b">Point B.</param>
 /// <returns>The square of the distance between the points.</returns>
 public static float GetDistanceSq(Vector2 a, Vector2 b)
 {
     float dx = a.x - b.x;
     float dy = a.y - b.y;
     return (dx * dx + dy * dy);
 }
 /// <summary>
 /// Returns the <a href="http://en.wikipedia.org/wiki/Dot_product" target="_blank">
 /// dot product</a> of the specified vectors. (u . v)
 /// </summary>
 /// <param name="u">Vector u</param>
 /// <param name="v">Vector v</param>
 /// <returns>The dot product of the specified vectors.</returns>
 public static float Dot(Vector2 u, Vector2 v)
 {
     return (u.x * v.x) + (u.y * v.y);
 }