/// <summary> /// Creates a new vector out of the two passed vectors and takes the minimum values from these for each component. /// </summary> /// <param name="value1"> First vector. </param> /// <param name="value2"> Second vector. </param> /// <returns> Vector which components are the minimum of the respective components of the two passed vectors. </returns> public static Vector2F Min(Vector2F value1, Vector2F value2) { return new Vector2F(MathUtils.Min(value1.X, value2.X), MathUtils.Min(value1.Y, value2.Y)); }
/// <summary> /// Constructor. /// </summary> /// <param name="vector"> Initial vector. </param> public Vector2F(Vector2F vector) { this.X = vector.X; this.Y = vector.Y; }
/// <summary> /// Calculates the distance between this and the passed vector. /// </summary> /// <param name="vector"> Vector to compute distance to. </param> /// <returns> Distance between this and the passed vector. </returns> public float GetDistance(Vector2F vector) { return MathUtils.Sqrt(this.GetSquareDistance(vector)); }
/// <summary> /// Calculates the square distance between this and the passed vector. /// </summary> /// <param name="vector"> Vector to compute square distance to. </param> /// <returns> Square distance between this and the passed vector. </returns> public float GetSquareDistance(Vector2F vector) { return MathUtils.Pow(vector.X - this.X, 2) + MathUtils.Pow(vector.Y - this.Y, 2); }
/// <summary> /// This method detects if two line segments intersect, /// and, if so, the point of intersection. /// Note: If two line segments are coincident, then /// no intersection is detected (there are actually /// infinite intersection points). /// </summary> /// <param name="point1"> The first point of the first line segment. </param> /// <param name="point2"> The second point of the first line segment. </param> /// <param name="point3"> The first point of the second line segment. </param> /// <param name="point4"> The second point of the second line segment. </param> /// <param name="intersectionPoint"> This is set to the intersection point if an intersection is detected. </param> /// <returns> True if an intersection is detected, false otherwise. </returns> public static bool Intersect( Vector2I point1, Vector2I point2, Vector2I point3, Vector2I point4, out Vector2F intersectionPoint) { return Intersect(ref point1, ref point2, ref point3, ref point4, true, true, out intersectionPoint); }
/// <summary> /// Calculates the dot product of the two passed vectors. See http://en.wikipedia.org/wiki/Dot_product for more details. /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <returns> Dot product of the two passed vectors. </returns> public static float Dot(Vector2F a, Vector2F b) { return (a.X * b.X) + (a.Y * b.Y); }
/// <summary> /// Calculates the dot product of the two passed vectors. See http://en.wikipedia.org/wiki/Dot_product for more details. /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <returns> Dot product of the two passed vectors. </returns> public static float Dot(Vector2F a, Vector2F b) { return((a.X * b.X) + (a.Y * b.Y)); }
/// <summary> /// Computes the direction which is closest to the specified vector. /// </summary> /// <param name="vector">Vector to get direction for.</param> /// <returns>Direction which is closest to the specified vector.</returns> public static DirectionType ComputeCardinalDirection(Vector2F vector) { // Compute angle. float angle = Vector2F.CalculateAngle(Vector2F.Forward, vector); return ComputeCardinalDirection(angle); }
/// <summary> /// Calculates the cross product of the two passed vectors. See http://en.wikipedia.org/wiki/Cross_product for more /// details. /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <returns> Cross product of the two passed vectors. </returns> public static float Cross(Vector2F a, Vector2F b) { return(a.X * b.Y - a.Y * b.X); }
/// <summary> /// Returns the distance between the two passed vectors. /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <returns> Distance betwwen the two passed vectors. </returns> public static float Distance(Vector2F a, Vector2F b) { return((a - b).Magnitude); }
/// <summary> /// Determines if three vectors are collinear (ie. on a straight line). /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <param name="c"> Third vector. </param> /// <param name="tolerance"> Tolerance to allow. </param> /// <returns> True if the three vectors are collinear; otherwise, false. </returns> public static bool Collinear(ref Vector2F a, ref Vector2F b, ref Vector2F c, float tolerance) { return(MathUtils.FloatInRange(Area(a, b, c), -tolerance, tolerance)); }
/// <summary> /// Determines if three vectors are collinear (ie. on a straight line). /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <param name="c"> Third vector. </param> /// <returns> True if the three vectors are collinear; otherwise, false. </returns> public static bool Collinear(ref Vector2F a, ref Vector2F b, ref Vector2F c) { return(Collinear(ref a, ref b, ref c, 0)); }
/// <summary> /// Calculates the dot product of this and the passed vector. See http://en.wikipedia.org/wiki/Dot_product for more /// details. /// </summary> /// <param name="vector"> Vector to calculate dot product with. </param> /// <returns> Dot product of this and the passed vector. </returns> public float CalculateDotProduct(Vector2F vector) { return(Dot(this, vector)); }
/// <summary> /// Computes on which side of the line segment the passed point lies /// </summary> /// <param name="point"> </param> /// <returns> </returns> public Side ComputeSide(Vector2F point) { Vector2F perpendicularDirection = this.Direction.GetPerpendicularVector(); float dotProduct = perpendicularDirection.CalculateDotProduct(point - this.PointA); return dotProduct == 0.0f ? Side.On : (dotProduct < 0.0f ? Side.Left : Side.Right); }
/// <summary> /// Determines whether the specified <see cref="Vector2F" /> is equal to the current <see cref="Vector2F" />. /// </summary> /// <returns> /// true if the specified <see cref="Vector2F" /> is equal to the current <see cref="Vector2F" />; otherwise, false. /// </returns> /// <param name="other"> /// The <see cref="Vector2F" /> to compare with the current <see cref="Vector2F" />. /// </param> public bool Equals(Vector2F other) { return(this.X.Equals(other.X) && this.Y.Equals(other.Y)); }
/// <summary> /// Returns the squared distance of this segment to the passed point /// </summary> /// <param name="point"> Point which distance to the segment should be checked </param> /// <returns> Squared distance to the passed point </returns> public float GetSquareDistance(Vector2F point) { // Computing the closest point to get the distance is possible, // but not required // return (this.GetClosestPoint(point) - point).GetSquareMagnitude(); Vector2F segmentVector = this.PointB - this.PointA; Vector2F startToPoint = point - this.PointA; // Check if start point closest point float e = Vector2F.Dot(startToPoint, segmentVector); if (e <= 0.0f) { return Vector2F.Dot(startToPoint, startToPoint); } // Check if end point closest point float squareLength = Vector2F.Dot(segmentVector, segmentVector); if (e >= squareLength) { Vector2F endToPoint = point - this.PointB; return Vector2F.Dot(endToPoint, endToPoint); } // Handle cases where point projects onto segment return Vector2F.Dot(startToPoint, startToPoint) - (e * e / squareLength); }
/// <summary> /// Calculates the distance between this and the passed vector. /// </summary> /// <param name="vector"> Vector to compute distance to. </param> /// <returns> Distance between this and the passed vector. </returns> public float GetDistance(Vector2F vector) { return(MathUtils.Sqrt(this.GetSquareDistance(vector))); }
/// <summary> /// This method detects if two line segments (or lines) intersect, /// and, if so, the point of intersection. Use the <paramref name="firstIsSegment" /> and /// <paramref name="secondIsSegment" /> parameters to set whether the intersection point /// must be on the first and second line segments. Setting these /// both to true means you are doing a line-segment to line-segment /// intersection. Setting one of them to true means you are doing a /// line to line-segment intersection test, and so on. /// Note: If two line segments are coincident, then /// no intersection is detected (there are actually /// infinite intersection points). /// Author: Jeremy Bell /// </summary> /// <param name="point1"> The first point of the first line segment. </param> /// <param name="point2"> The second point of the first line segment. </param> /// <param name="point3"> The first point of the second line segment. </param> /// <param name="point4"> The second point of the second line segment. </param> /// <param name="point"> This is set to the intersection point if an intersection is detected. </param> /// <param name="firstIsSegment"> Set this to true to require that the intersection point be on the first line segment. </param> /// <param name="secondIsSegment"> Set this to true to require that the intersection point be on the second line segment. </param> /// <returns> True if an intersection is detected, false otherwise. </returns> public static bool Intersect( ref Vector2I point1, ref Vector2I point2, ref Vector2I point3, ref Vector2I point4, bool firstIsSegment, bool secondIsSegment, out Vector2F point) { point = new Vector2F(); // these are reused later. // each lettered sub-calculation is used twice, except // for b and d, which are used 3 times int a = point4.Y - point3.Y; int b = point2.X - point1.X; int c = point4.X - point3.X; int d = point2.Y - point1.Y; // denominator to solution of linear system int denom = (a * b) - (c * d); // if denominator is 0, then lines are parallel if (denom != 0) { int e = point1.Y - point3.Y; int f = point1.X - point3.X; float oneOverDenom = 1.0f / denom; // numerator of first equation float ua = (c * e) - (a * f); ua *= oneOverDenom; // check if intersection point of the two lines is on line segment 1 if (!firstIsSegment || ua >= 0.0f && ua <= 1.0f) { // numerator of second equation float ub = (b * e) - (d * f); ub *= oneOverDenom; // check if intersection point of the two lines is on line segment 2 // means the line segments intersect, since we know it is on // segment 1 as well. if (!secondIsSegment || ub >= 0.0f && ub <= 1.0f) { // check if they are coincident (no collision in this case) if (ua != 0f || ub != 0f) { // There is an intersection point = new Vector2F(point1.X + (ua * b), point1.Y + (ua * d)); return true; } } } } return false; }
/// <summary> /// Calculates the square distance between this and the passed vector. /// </summary> /// <param name="vector"> Vector to compute square distance to. </param> /// <returns> Square distance between this and the passed vector. </returns> public float GetSquareDistance(Vector2F vector) { return(MathUtils.Pow(vector.X - this.X, 2) + MathUtils.Pow(vector.Y - this.Y, 2)); }
/// <summary> /// Returns a positive number if c is to the left of the line going from a to b. /// </summary> /// <param name="a">First point of the line.</param> /// <param name="b">Second point of the line.</param> /// <param name="c">Point to check against the line.</param> /// <returns> Positive number if point is left, negative if point is right, and 0 if points are collinear. </returns> public static float Area(Vector2F a, Vector2F b, Vector2F c) { return(a.X * (b.Y - c.Y) + b.X * (c.Y - a.Y) + c.X * (a.Y - b.Y)); }
/// <summary> /// Creates a new vector out of the two passed vectors and takes the minimum values from these for each component. /// </summary> /// <param name="value1"> First vector. </param> /// <param name="value2"> Second vector. </param> /// <returns> Vector which components are the minimum of the respective components of the two passed vectors. </returns> public static Vector2F Min(Vector2F value1, Vector2F value2) { return(new Vector2F(MathUtils.Min(value1.X, value2.X), MathUtils.Min(value1.Y, value2.Y))); }
/// <summary> /// Determines whether the specified <see cref="Vector2F" /> is equal to the current <see cref="Vector2F" />. /// </summary> /// <returns> /// true if the specified <see cref="Vector2F" /> is equal to the current <see cref="Vector2F" />; otherwise, false. /// </returns> /// <param name="other"> /// The <see cref="Vector2F" /> to compare with the current <see cref="Vector2F" />. /// </param> public bool Equals(Vector2F other) { return this.X.Equals(other.X) && this.Y.Equals(other.Y); }
/// <summary> /// Constructor. /// </summary> /// <param name="vector"> Initial vector. </param> public Vector2F(Vector2F vector) { this.X = vector.X; this.Y = vector.Y; }
/// <summary> /// Creates a new vector which is reflected by the specified vector. /// </summary> /// <param name="reflect">Vector to reflect with.</param> /// <returns>This vector reflected with the specified vector.</returns> public Vector2F GetReflected(Vector2F reflect) { Vector2F normalizedReflect = reflect.GetNormalized(); return new Vector2F( this.X - 2 * normalizedReflect.X * (normalizedReflect.X * this.X + normalizedReflect.Y * this.Y), this.Y - 2 * normalizedReflect.Y * (normalizedReflect.X * this.X + normalizedReflect.Y * this.Y)); }
/// <summary> /// Returns a vector whose components represent the absolute values of /// the components of the specified vector. /// </summary> /// <param name="vector">Vector to compute the absolute component values of.</param> /// <returns> /// Vector whose components represent the absolute values of /// the components of the specified vector. /// </returns> public static Vector2F Abs(Vector2F vector) { return new Vector2F(Math.Abs(vector.X), Math.Abs(vector.Y)); }
/// <summary> /// Checks if this vector is parallel or anti-parallel to the passed one. /// </summary> /// <param name="other"> Vector to check. </param> /// <returns> True if both vectors are parallel or anti-parallel, else false. </returns> public bool IsParallel(Vector2F other) { if (this.IsZero || other.IsZero) { return false; } return Math.Abs(this.CalculateDotProduct(other) / (this.Magnitude * other.Magnitude)) == 1; }
/// <summary> /// Returns a positive number if c is to the left of the line going from a to b. /// </summary> /// <param name="a">First point of the line.</param> /// <param name="b">Second point of the line.</param> /// <param name="c">Point to check against the line.</param> /// <returns> Positive number if point is left, negative if point is right, and 0 if points are collinear. </returns> public static float Area(Vector2F a, Vector2F b, Vector2F c) { return a.X * (b.Y - c.Y) + b.X * (c.Y - a.Y) + c.X * (a.Y - b.Y); }
/// <summary> /// Spherically interpolates between the two passed vectors. /// </summary> /// <param name="from">First point of the arc.</param> /// <param name="to">Last point of the arc.</param> /// <param name="step">Interpolation parameter.</param> /// <returns> /// Value of <paramref name="step" /> along the path along the line segment in the plane. /// </returns> public static Vector2F Slerp(Vector2F from, Vector2F to, float step) { if (step == 0) { return from; } if (from == to || step == 1) { return to; } float theta = MathUtils.ACos(Dot(from, to)); if (theta == 0) { return to; } float sinTheta = MathUtils.Sin(theta); if (sinTheta == 0.0f) { return to; } return MathUtils.Sin((1 - step) * theta) / sinTheta * from + MathUtils.Sin(step * theta) / sinTheta * to; }
/// <summary> /// Calculates the angle between two vectors on a plane. /// </summary> /// <param name="vector1"> First vector. </param> /// <param name="vector2"> Second vector. </param> /// <returns> /// Return the angle between two vectors on a plane. The angle is from vector 1 to vector 2, positive /// counter-clockwise. The result is between -pi -> pi. /// </returns> public static float CalculateAngle(Vector2F vector1, Vector2F vector2) { float theta1 = MathUtils.Atan2(vector1.Y, vector1.X); float theta2 = MathUtils.Atan2(vector2.Y, vector2.X); float dtheta = theta2 - theta1; while (dtheta > MathUtils.Pi) { dtheta -= (2 * MathUtils.Pi); } while (dtheta < -MathUtils.Pi) { dtheta += (2 * MathUtils.Pi); } return (dtheta); }
/// <summary> /// Interpolates an angle from a start value to an end value. /// </summary> /// <param name="from"> Start angle (in radians). </param> /// <param name="to"> End angle (in radians). </param> /// <param name="step"> Step value (0...1). </param> /// <returns> Returns the start angle if step value is smaller or equal to zero, the end angle if step value is bigger or equal to 1 and an interpolated angle (in radians) if the step value is between 0 and 1. </returns> public static float CurveAngle(float from, float to, float step) { if (step <= 0) { return from; } if (from == to || step >= 1) { return to; } Vector2F fromVector = new Vector2F(MathUtils.Cos(from), MathUtils.Sin(from)); Vector2F toVector = new Vector2F(MathUtils.Cos(to), MathUtils.Sin(to)); Vector2F currentVector = Vector2F.Slerp(fromVector, toVector, step); return MathUtils.Atan2(currentVector.Y, currentVector.X); }
/// <summary> /// Calculates the dot product of this and the passed vector. See http://en.wikipedia.org/wiki/Dot_product for more /// details. /// </summary> /// <param name="vector"> Vector to calculate dot product with. </param> /// <returns> Dot product of this and the passed vector. </returns> public float CalculateDotProduct(Vector2F vector) { return Dot(this, vector); }
/// <summary> /// Computes the closest point on the line to the passed point /// </summary> /// <param name="point"> Point to find the closest point on the line segment for </param> /// <returns> Closest point on the line segment to the passed point </returns> public Vector2F GetClosestPoint(Vector2F point) { Vector2F segmentDirection = this.PointB - this.PointA; float projectionValue = Vector2F.Dot(point - this.PointA, segmentDirection); if (projectionValue <= 0.0f) { return this.PointA; } float denominator = Vector2F.Dot(segmentDirection, segmentDirection); if (projectionValue >= denominator) { return this.PointB; } projectionValue /= denominator; return this.PointA + (segmentDirection * projectionValue); }
/// <summary> /// Determines if three vectors are collinear (ie. on a straight line). /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <param name="c"> Third vector. </param> /// <returns> True if the three vectors are collinear; otherwise, false. </returns> public static bool Collinear(ref Vector2F a, ref Vector2F b, ref Vector2F c) { return Collinear(ref a, ref b, ref c, 0); }
/// <summary> /// Initializes a new instance of the <see cref="LineSegment2F" /> class. /// </summary> /// <param name="pointA"> First point of line segment </param> /// <param name="pointB"> Second point of line segment </param> public LineSegment2F(Vector2F pointA, Vector2F pointB) { this.PointA = pointA; this.PointB = pointB; }
/// <summary> /// Determines if three vectors are collinear (ie. on a straight line). /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <param name="c"> Third vector. </param> /// <param name="tolerance"> Tolerance to allow. </param> /// <returns> True if the three vectors are collinear; otherwise, false. </returns> public static bool Collinear(ref Vector2F a, ref Vector2F b, ref Vector2F c, float tolerance) { return MathUtils.FloatInRange(Area(a, b, c), -tolerance, tolerance); }
/// <summary> /// Returns directions of a vector, based on quadrants. /// </summary> /// <param name="vector">Vector to convert.</param> /// <returns> Set of directions.</returns> public static DirectionType ToDirections(Vector2F vector) { DirectionType ret = DirectionType.None; if (vector.Y == 0.0f && vector.X == 0.0f) { return DirectionType.None; } if (vector.Y != 0.0f) { ret |= (vector.Y > 0.0f) ? DirectionType.North : DirectionType.South; } if (vector.X != 0.0f) { ret |= (vector.X > 0.0f) ? DirectionType.East : DirectionType.West; } return ret; }
/// <summary> /// Calculates the cross product of the two passed vectors. See http://en.wikipedia.org/wiki/Cross_product for more /// details. /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <returns> Cross product of the two passed vectors. </returns> public static float Cross(Vector2F a, Vector2F b) { return a.X * b.Y - a.Y * b.X; }
/// <summary> /// This method detects if two line segments (or lines) intersect, /// and, if so, the point of intersection. Use the <paramref name="firstIsSegment" /> and /// <paramref name="secondIsSegment" /> parameters to set whether the intersection point /// must be on the first and second line segments. Setting these /// both to true means you are doing a line-segment to line-segment /// intersection. Setting one of them to true means you are doing a /// line to line-segment intersection test, and so on. /// Note: If two line segments are coincident, then /// no intersection is detected (there are actually /// infinite intersection points). /// Author: Jeremy Bell /// </summary> /// <param name="point1"> The first point of the first line segment. </param> /// <param name="point2"> The second point of the first line segment. </param> /// <param name="point3"> The first point of the second line segment. </param> /// <param name="point4"> The second point of the second line segment. </param> /// <param name="intersectionPoint"> This is set to the intersection point if an intersection is detected. </param> /// <param name="firstIsSegment"> Set this to true to require that the intersection point be on the first line segment. </param> /// <param name="secondIsSegment"> Set this to true to require that the intersection point be on the second line segment. </param> /// <returns> True if an intersection is detected, false otherwise. </returns> public static bool Intersect( Vector2I point1, Vector2I point2, Vector2I point3, Vector2I point4, bool firstIsSegment, bool secondIsSegment, out Vector2F intersectionPoint) { return Intersect( ref point1, ref point2, ref point3, ref point4, firstIsSegment, secondIsSegment, out intersectionPoint); }
/// <summary> /// Returns the distance between the two passed vectors. /// </summary> /// <param name="a"> First vector. </param> /// <param name="b"> Second vector. </param> /// <returns> Distance betwwen the two passed vectors. </returns> public static float Distance(Vector2F a, Vector2F b) { return (a - b).Magnitude; }
/// <summary> /// Checks if the passed line segments intersect and computes the intersection point if they do /// </summary> /// <param name="lineSegmentA"> </param> /// <param name="lineSegmentB"> </param> /// <param name="intersectionPoint"> Intersection point between the two passed line segments </param> /// <returns> Returns true if line segments intersect, otherwise false </returns> public static bool Intersect( LineSegment2I lineSegmentA, LineSegment2I lineSegmentB, out Vector2F intersectionPoint) { return Intersect( lineSegmentA.PointA, lineSegmentA.PointB, lineSegmentB.PointA, lineSegmentB.PointB, out intersectionPoint); }
/// <summary> /// Returns a vector whose components represent the absolute values of /// the components of the specified vector. /// </summary> /// <param name="vector">Vector to compute the absolute component values of.</param> /// <returns> /// Vector whose components represent the absolute values of /// the components of the specified vector. /// </returns> public static Vector2F Abs(Vector2F vector) { return(new Vector2F(Math.Abs(vector.X), Math.Abs(vector.Y))); }