private static Vector2I GetDirection(MoveDirection moveDirections) { var direction = new Vector2I(); if (moveDirections.IsOptionSet(MoveDirection.Forward)) { direction.Y += 1; } if (moveDirections.IsOptionSet(MoveDirection.Backward)) { direction.Y -= 1; } if (moveDirections.IsOptionSet(MoveDirection.Right)) { direction.X += 1; } if (moveDirections.IsOptionSet(MoveDirection.Left)) { direction.X -= 1; } return direction; }
/// <summary> /// Edits the specified context. /// </summary> /// <param name="context"> Editor context to work with. </param> public void Edit(IValueEditorContext context) { // Get value. Vector2I oldValue = context.GetValue<Vector2I>(); // Show editor. GUILayout.BeginHorizontal(); GUILayout.Label(context.Name); int newX; string newXString = GUILayout.TextField(oldValue.X.ToString(CultureInfo.InvariantCulture)); if (string.IsNullOrEmpty(newXString)) { newX = 0; } else if (!int.TryParse(newXString, out newX)) { newX = oldValue.X; } int newY; string newYString = GUILayout.TextField(oldValue.Y.ToString(CultureInfo.InvariantCulture)); if (string.IsNullOrEmpty(newYString)) { newY = 0; } else if (!int.TryParse(newYString, out newY)) { newY = oldValue.Y; } Vector2I newValue = new Vector2I(newX, newY); GUILayout.EndHorizontal(); // Set new value. if (newValue != oldValue) { context.Value = newValue; } }
/// <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 Vector2I a, ref Vector2I b, ref Vector2I c) { return Collinear(ref a, ref b, ref c, 0); }
/// <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(Vector2I vector) { DirectionType ret = DirectionType.None; if (vector.Y == 0 && vector.X == 0) { return DirectionType.None; } if (vector.Y != 0) { ret |= (vector.Y > 0) ? DirectionType.North : DirectionType.South; } if (vector.X != 0) { ret |= (vector.X > 0) ? DirectionType.East : DirectionType.West; } return ret; }
/// <summary> /// Constructor. /// </summary> /// <param name="vector"> Initial vector. </param> public Vector2I(Vector2I vector) { this.X = vector.X; this.Y = vector.Y; }
/// <summary> /// Sum of the absolute values of the differences of the components of both vectors. /// </summary> /// <param name="a">First vector.</param> /// <param name="b">Second vector.</param> /// <returns>|a.X - b.X| + |a.Y - b.Y|</returns> public static int ManhattanDistance(Vector2I a, Vector2I b) { return Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y); }
/// <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 int GetSquareDistance(Vector2I vector) { return MathUtils.Pow(vector.X - this.X, 2) + MathUtils.Pow(vector.Y - this.Y, 2); }
/// <summary> /// Determines whether the specified <see cref="Vector2I" /> is equal to the current <see cref="Vector2I" />. /// </summary> /// <returns> /// true if the specified <see cref="Vector2I" /> is equal to the current <see cref="Vector2I" />; otherwise, false. /// </returns> /// <param name="other"> /// The <see cref="Vector2I" /> to compare with the current <see cref="Vector2I" />. /// </param> public bool Equals(Vector2I other) { return this.X == other.X && this.Y == other.Y; }
/// <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(Vector2I a, Vector2I b) { return (a - b).Magnitude; }
/// <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 Vector2I GetClosestPoint(Vector2I point) { Vector2I segmentDirection = this.PointB - this.PointA; int projectionValue = Vector2I.Dot(point - this.PointA, segmentDirection); if (projectionValue <= 0) { return this.PointA; } int denominator = Vector2I.Dot(segmentDirection, segmentDirection); if (projectionValue >= denominator) { return this.PointB; } projectionValue /= denominator; return this.PointA + (segmentDirection * projectionValue); }
/// <summary> /// Computes on which side of the line segment the passed point lies /// </summary> /// <param name="point"> </param> /// <returns> </returns> public Side ComputeSide(Vector2I point) { Vector2I perpendicularDirection = this.Direction.GetPerpendicularVector(); int dotProduct = perpendicularDirection.CalculateDotProduct(point - this.PointA); return dotProduct == 0 ? Side.On : (dotProduct < 0.0f ? Side.Left : Side.Right); }
/// <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> /// 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> /// 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> /// 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 Vector2I a, ref Vector2I b, ref Vector2I c, float tolerance) { return MathUtils.FloatInRange(Area(a, b, c), -tolerance, tolerance); }
/// <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 int Cross(Vector2I a, Vector2I b) { return a.X * b.Y - a.Y * b.X; }
/// <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(Vector2I point) { // Computing the closest point to get the distance is possible, // but not required // return (this.GetClosestPoint(point) - point).GetSquareMagnitude(); Vector2I segmentVector = this.PointB - this.PointA; Vector2I startToPoint = point - this.PointA; // Check if start point closest point int e = Vector2I.Dot(startToPoint, segmentVector); if (e <= 0) { return Vector2I.Dot(startToPoint, startToPoint); } // Check if end point closest point int squareLength = Vector2I.Dot(segmentVector, segmentVector); if (e >= squareLength) { Vector2I endToPoint = point - this.PointB; return Vector2I.Dot(endToPoint, endToPoint); } // Handle cases where point projects onto segment return Vector2I.Dot(startToPoint, startToPoint) - (e * e * 1.0f / squareLength); }
/// <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 int Dot(Vector2I a, Vector2I b) { return (a.X * b.X) + (a.Y * b.Y); }
/// <summary> /// Initializes a new instance of the <see cref="LineSegment2I" /> class. /// </summary> /// <param name="pointA"> First point of line segment </param> /// <param name="pointB"> Second point of line segment </param> public LineSegment2I(Vector2I pointA, Vector2I pointB) { this.PointA = pointA; this.PointB = pointB; }
/// <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(Vector2I vector) { return MathUtils.Sqrt(this.GetSquareDistance(vector)); }
/// <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 Vector2I Abs(Vector2I vector) { return new Vector2I(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(Vector2I 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 int Area(Vector2I a, Vector2I b, Vector2I 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 Vector2I Min(Vector2I value1, Vector2I value2) { return new Vector2I(MathUtils.Min(value1.X, value2.X), MathUtils.Min(value1.Y, value2.Y)); }
/// <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(Vector2I vector1, Vector2I 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> /// 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 int CalculateDotProduct(Vector2I vector) { return Dot(this, vector); }
/// <summary> /// Moves the specified location by one field into the specified direction. /// </summary> /// <param name="gridLocation">Location to move.</param> /// <param name="direction">Direction to move to.</param> /// <returns>New location after moving the specified location into the specified direction.</returns> public static Vector2I MoveLocation(Vector2I gridLocation, DirectionType direction) { return gridLocation + ToVector2I(direction); }