|
@@ -7,69 +7,144 @@ using System.Threading.Tasks;
|
|
|
|
|
|
namespace bbiwarg.Utility
|
|
|
{
|
|
|
+ /// <summary>
|
|
|
+ /// Class with represents a vector or a point in 2 dimensional space.
|
|
|
+ /// </summary>
|
|
|
public class Vector2D
|
|
|
{
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// length of the vector, is initialized with -1 and will only be calculated if needed and only once
|
|
|
+ /// </summary>
|
|
|
+ private float length = -1;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// the null vector or origin
|
|
|
+ /// </summary>
|
|
|
public static Vector2D Zero { get { return new Vector2D(0, 0); } }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// X (first) component
|
|
|
+ /// </summary>
|
|
|
public float X { get; private set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Y (second) component
|
|
|
+ /// </summary>
|
|
|
public float Y { get; private set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// X component as integer
|
|
|
+ /// </summary>
|
|
|
public int IntX { get { return (int)X; } }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Y component as integer
|
|
|
+ /// </summary>
|
|
|
public int IntY { get { return (int)Y; } }
|
|
|
- public float Length { get { return (float)Math.Sqrt(X * X + Y * Y); } }
|
|
|
-
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// length of the vector, computed in euclidean distance (2. norm)
|
|
|
+ /// </summary>
|
|
|
+ public float Length { get { if (length == -1) length = (float)Math.Sqrt(X * X + Y * Y); return length; } }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Standard constructor which sets the components.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="x">first component</param>
|
|
|
+ /// <param name="y">second component</param>
|
|
|
public Vector2D(float x, float y)
|
|
|
{
|
|
|
X = x;
|
|
|
Y = y;
|
|
|
}
|
|
|
|
|
|
- public Vector2D(Vector2D vec)
|
|
|
- {
|
|
|
- X = vec.X;
|
|
|
- Y = vec.Y;
|
|
|
- }
|
|
|
-
|
|
|
+ /// <summary>
|
|
|
+ /// Constructor to create a Vector2D from a Point .
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="point">a Point</param>
|
|
|
public Vector2D(Point point)
|
|
|
{
|
|
|
X = point.X;
|
|
|
Y = point.Y;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Constructor to create a Vector2D from a PointF.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="point">a PointF</param>
|
|
|
public Vector2D(PointF point)
|
|
|
{
|
|
|
X = point.X;
|
|
|
Y = point.Y;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Computes the euclidean distance between the point this vector describes and another point described by a Vector.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="point">a Point</param>
|
|
|
+ /// <returns>euclidean distance</returns>
|
|
|
public float getDistanceTo(Vector2D point)
|
|
|
{
|
|
|
return (this - point).Length;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Computes the angle between this vector and another vector in radians.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vector">a vector</param>
|
|
|
+ /// <returns>angle in radians</returns>
|
|
|
public float getAngleBetween(Vector2D vector)
|
|
|
{
|
|
|
return (float)Math.Acos(dotProduct(vector) / (Length * vector.Length));
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Computes whether this vector and another vector point in opposite directions, meaning the smallest angle is between 90° and 180°.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vector">a vector</param>
|
|
|
+ /// <returns>true iff the vectors point in opposite directions</returns>
|
|
|
public bool isInOppositeDirection(Vector2D vector)
|
|
|
{
|
|
|
return (getAngleBetween(vector) > Math.PI / 2);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Computes the dot product of this vector and another vector.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vector">the other vector</param>
|
|
|
+ /// <returns>the dot product</returns>
|
|
|
public float dotProduct(Vector2D vector)
|
|
|
{
|
|
|
return X * vector.X + Y * vector.Y;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Computes the cross product (determinant) of this vector and another vector.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="v">the other vector</param>
|
|
|
+ /// <returns>cross product of this and v</returns>
|
|
|
public float crossProduct(Vector2D v)
|
|
|
{
|
|
|
return X * v.Y - Y * v.X;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Multiplies this vector component-by-component with another vector.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="v">the other vector</param>
|
|
|
+ /// <returns>the component-by-component multiplied vector</returns>
|
|
|
public Vector2D scale(Vector2D v)
|
|
|
{
|
|
|
return new Vector2D(X * v.X, Y * v.Y);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Determines whether this point (vector) is inside a given box or not.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="corner1">first corner of the box</param>
|
|
|
+ /// <param name="corner2">second corner of the box</param>
|
|
|
+ /// <returns>true iff point is inside the box</returns>
|
|
|
public bool isInBox(Vector2D corner1, Vector2D corner2)
|
|
|
{
|
|
|
float minX = Math.Min(corner1.X, corner2.X);
|
|
@@ -79,42 +154,62 @@ namespace bbiwarg.Utility
|
|
|
return (minX <= X && X <= maxX && minY <= Y && Y <= maxY);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Determines whether a this point is inside the boundaries of a given image or not.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="imageSize">a imageSize object</param>
|
|
|
+ /// <returns>true iff point is inside the image boundaries</returns>
|
|
|
public bool isInBound(ImageSize imageSize)
|
|
|
{
|
|
|
return isInBound(Vector2D.Zero, imageSize.MaxPixel);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Determines whether a point is inside a box. iff bottomRight is higher or more left than topLeft the result is false.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="topLeft">top left corner of the box</param>
|
|
|
+ /// <param name="bottomRight">bottom right corner of the box</param>
|
|
|
+ /// <returns>true iff point is in box</returns>
|
|
|
public bool isInBound(Vector2D topLeft, Vector2D bottomRight)
|
|
|
{
|
|
|
return (X >= topLeft.X && X <= bottomRight.X && Y >= topLeft.Y && Y <= bottomRight.Y);
|
|
|
}
|
|
|
-
|
|
|
- public Vector2D moveInBound(ImageSize imageSize, Vector2D inBoundDirection)
|
|
|
- {
|
|
|
- return moveInBound(Vector2D.Zero, imageSize.MaxPixel, inBoundDirection);
|
|
|
- }
|
|
|
-
|
|
|
- public Vector2D moveInBound(Vector2D topLeft, Vector2D bottomRight, Vector2D inBoundDirection)
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Moves this vector along the direction vector factor times inside the imageSize, this point won't leave the image.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="imageSize">the imagesize</param>
|
|
|
+ /// <param name="direction">the move direction</param>
|
|
|
+ /// <param name="factor">the move factor</param>
|
|
|
+ /// <returns>a point inside the image</returns>
|
|
|
+ public Vector2D moveWithinBound(ImageSize imageSize, Vector2D direction, float factor)
|
|
|
{
|
|
|
- Vector2D position = new Vector2D(X, Y);
|
|
|
- while (!position.isInBound(topLeft, bottomRight))
|
|
|
- position += inBoundDirection;
|
|
|
- return position;
|
|
|
- }
|
|
|
-
|
|
|
- public Vector2D moveWithinBound(ImageSize imageSize, Vector2D direction, float factor) {
|
|
|
Vector2D newPosition = this + factor * direction;
|
|
|
if (!newPosition.isInBound(imageSize))
|
|
|
- newPosition = newPosition.moveInBound(imageSize, direction.getInverse());
|
|
|
+ {
|
|
|
+ Vector2D inverseDirection = direction.getInverse().normalize();
|
|
|
+ while (!newPosition.isInBound(imageSize))
|
|
|
+ {
|
|
|
+ newPosition += inverseDirection;
|
|
|
+ }
|
|
|
+ }
|
|
|
return newPosition;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Normalizes this vector with the euclidean norm (2. norm).
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>normalized vector</returns>
|
|
|
public Vector2D normalize()
|
|
|
{
|
|
|
- float length = Length;
|
|
|
- return new Vector2D(X / length, Y / length);
|
|
|
+ return new Vector2D(X / Length, Y / Length);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Computes a orthogonal vector of this vector, if side is true the X component will be switched, else the Y component.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="side">which vector</param>
|
|
|
+ /// <returns>a orthogonal vector</returns>
|
|
|
public Vector2D getOrthogonal(bool side = true)
|
|
|
{
|
|
|
if (side)
|
|
@@ -123,61 +218,124 @@ namespace bbiwarg.Utility
|
|
|
return new Vector2D(-Y, X);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Computes the inverse vector of this vector.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>inverse vector</returns>
|
|
|
public Vector2D getInverse()
|
|
|
{
|
|
|
return new Vector2D(-X, -Y);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Computes the absolute vector of this vector.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>absolute vector</returns>
|
|
|
public Vector2D getAbsolute()
|
|
|
{
|
|
|
return new Vector2D(Math.Abs(X), Math.Abs(Y));
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Copies this vector (clone).
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>this vector as new vector</returns>
|
|
|
public Vector2D copy()
|
|
|
{
|
|
|
return new Vector2D(X, Y);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Creates a description of this vector.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>a string describing this vector</returns>
|
|
|
public override string ToString()
|
|
|
{
|
|
|
return "(" + X + "|" + Y + ")";
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Multiplies this vector component-by-component with a scalar value.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="scalar">multiplier</param>
|
|
|
+ /// <param name="vector">multiplicant</param>
|
|
|
+ /// <returns>multiplied vector (product)</returns>
|
|
|
public static Vector2D operator *(float scalar, Vector2D vector)
|
|
|
{
|
|
|
return new Vector2D(scalar * vector.X, scalar * vector.Y);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Multiplies this vector component-by-component with a scalar value.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vector">multiplicant</param>
|
|
|
+ /// <param name="scalar">multiplier</param>
|
|
|
+ /// <returns>multiplied vector (product)</returns>
|
|
|
public static Vector2D operator *(Vector2D vector, float scalar)
|
|
|
{
|
|
|
return new Vector2D(scalar * vector.X, scalar * vector.Y);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Divides this vector with a scalar value.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vector">this vector</param>
|
|
|
+ /// <param name="scalar">the value</param>
|
|
|
+ /// <returns>the divided vector</returns>
|
|
|
public static Vector2D operator /(Vector2D vector, float scalar)
|
|
|
{
|
|
|
return new Vector2D(vector.X / scalar, vector.Y / scalar);
|
|
|
}
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Divides on vector with another vector component-by-component.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vector1">the dividend</param>
|
|
|
+ /// <param name="vector2">the divisor</param>
|
|
|
+ /// <returns>the component divided vector</returns>
|
|
|
public static Vector2D operator /(Vector2D vector1, Vector2D vector2)
|
|
|
{
|
|
|
return new Vector2D(vector1.X / vector2.X, vector1.Y / vector2.Y);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Adds two vectors (component-by-component).
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vector1">first addend</param>
|
|
|
+ /// <param name="vector2">second addend</param>
|
|
|
+ /// <returns>sum of the vectors</returns>
|
|
|
public static Vector2D operator +(Vector2D vector1, Vector2D vector2)
|
|
|
{
|
|
|
return new Vector2D(vector1.X + vector2.X, vector1.Y + vector2.Y);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Subtracts two vectors (component-by-component).
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vector1">the minuend</param>
|
|
|
+ /// <param name="vector2">the subtrahend</param>
|
|
|
+ /// <returns>the difference of the two vectors</returns>
|
|
|
public static Vector2D operator -(Vector2D vector1, Vector2D vector2)
|
|
|
{
|
|
|
return new Vector2D(vector1.X - vector2.X, vector1.Y - vector2.Y);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Computes the mean of two vectors.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vectors">second vector</param>
|
|
|
+ /// <returns>the mean vector</returns>
|
|
|
public static Vector2D mean(List<Vector2D> vectors)
|
|
|
{
|
|
|
Vector2D sumVector = Vector2D.sum(vectors);
|
|
|
return sumVector / vectors.Count;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Sums a list of vectors (component-by-component).
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vectors">a list of vectors</param>
|
|
|
+ /// <returns>vector of sumed components</returns>
|
|
|
public static Vector2D sum(List<Vector2D> vectors)
|
|
|
{
|
|
|
Vector2D sumVector = new Vector2D(0, 0);
|
|
@@ -187,11 +345,21 @@ namespace bbiwarg.Utility
|
|
|
return sumVector;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Casts a Vector2D to PointF.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vec">a vector</param>
|
|
|
+ /// <returns>a PointF</returns>
|
|
|
public static implicit operator PointF(Vector2D vec)
|
|
|
{
|
|
|
return new PointF(vec.X, vec.Y);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Casts a Vector2D to Point.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="vec">a vector</param>
|
|
|
+ /// <returns>a Point</returns>
|
|
|
public static implicit operator Point(Vector2D vec)
|
|
|
{
|
|
|
return new Point(vec.IntX, vec.IntY);
|