package com.glview.graphics;
public class Vector extends PointF {
public Vector() {
}
public Vector(float x, float y) {
super(x, y);
}
public Vector(Vector v) {
super(v);
}
/** @return a copy of this vector */
public Vector cpy () {
return new Vector(this);
}
/** @return The euclidian length */
public float len () {
return (float)Math.sqrt(x * x + y * y);
}
/** @return The squared euclidian length */
public float len2 () {
return x * x + y * y;
}
/** Sets this vector from the given vector
* @param v The vector
* @return This vector for chaining */
public Vector set (Vector v) {
x = v.x;
y = v.y;
return this;
}
/** Subtracts the given vector from this vector.
* @param v The vector
* @return This vector for chaining */
public Vector sub (Vector v) {
x -= v.x;
y -= v.y;
return this;
}
/** Normalizes this vector. Does nothing if it is zero.
* @return This vector for chaining */
public Vector nor () {
float len = len();
if (len != 0) {
x /= len;
y /= len;
}
return this;
}
/** Adds the given vector to this vector
* @param v The vector
* @return This vector for chaining */
public Vector add (Vector v) {
x += v.x;
y += v.y;
return this;
}
/** Adds the given components to this vector
* @param x The x-component
* @param y The y-component
* @return This vector for chaining */
public Vector add (float x, float y) {
this.x += x;
this.y += y;
return this;
}
/** @param v The other vector
* @return The dot product between this and the other vector */
public float dot (Vector v) {
return x * v.x + y * v.y;
}
/** Multiplies this vector by a scalar
* @param scalar The scalar
* @return This vector for chaining */
public Vector scl (float scalar) {
x *= scalar;
y *= scalar;
return this;
}
/** @deprecated Use {@link #scl(float)} instead. */
public Vector mul (float scalar) {
return scl(scalar);
}
/** Multiplies this vector by a scalar
* @return This vector for chaining */
public Vector scl (float x, float y) {
this.x *= x;
this.y *= y;
return this;
}
/** @deprecated Use {@link #scl(float, float)} instead. */
public Vector mul (float x, float y) {
return scl(x, y);
}
/** Multiplies this vector by a vector
* @return This vector for chaining */
public Vector scl (Vector v) {
this.x *= v.x;
this.y *= v.y;
return this;
}
/** @deprecated Use {@link #scl(Vector)} instead. */
public Vector mul (Vector v) {
return scl(v);
}
public Vector div (float value) {
return this.scl(1 / value);
}
public Vector div (float vx, float vy) {
return this.scl(1 / vx, 1 / vy);
}
public Vector div (Vector other) {
return this.scl(1 / other.x, 1 / other.y);
}
/** @param v The other vector
* @return the distance between this and the other vector */
public float dst (Vector v) {
final float x_d = v.x - x;
final float y_d = v.y - y;
return (float)Math.sqrt(x_d * x_d + y_d * y_d);
}
/** @param x The x-component of the other vector
* @param y The y-component of the other vector
* @return the distance between this and the other vector */
public float dst (float x, float y) {
final float x_d = x - this.x;
final float y_d = y - this.y;
return (float)Math.sqrt(x_d * x_d + y_d * y_d);
}
/** @param v The other vector
* @return the squared distance between this and the other vector */
public float dst2 (Vector v) {
final float x_d = v.x - x;
final float y_d = v.y - y;
return x_d * x_d + y_d * y_d;
}
/** @param x The x-component of the other vector
* @param y The y-component of the other vector
* @return the squared distance between this and the other vector */
public float dst2 (float x, float y) {
final float x_d = x - this.x;
final float y_d = y - this.y;
return x_d * x_d + y_d * y_d;
}
/** Limits this vector's length to given value
* @param limit Max length
* @return This vector for chaining */
public Vector limit (float limit) {
if (len2() > limit * limit) {
nor();
scl(limit);
}
return this;
}
/** Clamps this vector's length to given value
* @param min Min length
* @param max Max length
* @return This vector for chaining */
public Vector clamp (float min, float max) {
final float l2 = len2();
if (l2 == 0f) return this;
if (l2 > max * max) return nor().scl(max);
if (l2 < min * min) return nor().scl(min);
return this;
}
public String toString () {
return "[" + x + ":" + y + "]";
}
/** Substracts the other vector from this vector.
* @param x The x-component of the other vector
* @param y The y-component of the other vector
* @return This vector for chaining */
public Vector sub (float x, float y) {
this.x -= x;
this.y -= y;
return this;
}
/** Calculates the 2D cross product between this and the given vector.
* @param v the other vector
* @return the cross product */
public float crs (Vector v) {
return this.x * v.y - this.y * v.x;
}
/** Calculates the 2D cross product between this and the given vector.
* @param x the x-coordinate of the other vector
* @param y the y-coordinate of the other vector
* @return the cross product */
public float crs (float x, float y) {
return this.x * y - this.y * x;
}
/** @return the angle in degrees of this vector (point) relative to the x-axis. Angles are towards the positive y-axis (typically
* counter-clockwise) and between 0 and 360. */
public float angle () {
float angle = (float) (Math.atan2(y, x) * (180f / Math.PI));
if (angle < 0) angle += 360;
return angle;
}
/** Sets the angle of the vector in degrees relative to the x-axis, towards the positive y-axis (typically counter-clockwise).
* @param degrees The angle to set. */
public Vector setAngle (float degrees) {
this.set(len(), 0f);
this.rotate(degrees);
return this;
}
/** Rotates the Vector by the given angle, counter-clockwise assuming the y-axis points up.
* @param degrees the angle in degrees */
public Vector rotate (float degrees) {
float rad = (float) (degrees * (Math.PI / 180));
float cos = (float)Math.cos(rad);
float sin = (float)Math.sin(rad);
float newX = this.x * cos - this.y * sin;
float newY = this.x * sin + this.y * cos;
this.x = newX;
this.y = newY;
return this;
}
/** Rotates the Vector by 90 degrees in the specified direction, where >= 0 is counter-clockwise and < 0 is clockwise. */
public Vector rotateCCW () {
float x = this.x;
this.x = this.y;
this.y = -x;
return this;
}
/** Rotates the Vector by 90 degrees in the specified direction, where >= 0 is counter-clockwise and < 0 is clockwise. */
public Vector rotateCW () {
float x = this.x;
this.x = -this.y;
this.y = x;
return this;
}
/** Linearly interpolates between this vector and the target vector by alpha which is in the range [0,1]. The result is stored
* in this vector.
*
* @param target The target vector
* @param alpha The interpolation coefficient
* @return This vector for chaining. */
public Vector lerp (Vector target, float alpha) {
final float invAlpha = 1.0f - alpha;
this.x = (x * invAlpha) + (target.x * alpha);
this.y = (y * invAlpha) + (target.y * alpha);
return this;
}
/** Compares this vector with the other vector, using the supplied epsilon for fuzzy equality testing.
* @param obj
* @param epsilon
* @return whether the vectors are the same. */
public boolean epsilonEquals (Vector obj, float epsilon) {
if (obj == null) return false;
if (Math.abs(obj.x - x) > epsilon) return false;
if (Math.abs(obj.y - y) > epsilon) return false;
return true;
}
/** Compares this vector with the other vector, using the supplied epsilon for fuzzy equality testing.
* @param x
* @param y
* @param epsilon
* @return whether the vectors are the same. */
public boolean epsilonEquals (float x, float y, float epsilon) {
if (Math.abs(x - this.x) > epsilon) return false;
if (Math.abs(y - this.y) > epsilon) return false;
return true;
}
}