/**
* A class to describe a two or three dimensional vector.
* Created for use in examples from the Nature of Code course at ITP.
*
* http://www.shiffman.net/
* http://www.shiffman.net/teaching/the-nature-of-code
*/
public class Vector3D {
/**
* The x component of the vector.
*/
public float x;
/**
* The y component of the vector.
*/
public float y;
/**
* The z component of the vector.
*/
public float z;
/**
* Constructor for a 3D vector.
*
* @param x_
* the x coordinate.
* @param y_
* the y coordinate.
* @param z_
* the y coordinate.
*/
public Vector3D(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
/**
* Constructor for a 2D vector: z coordinate is set to 0.
*
* @param x_
* the x coordinate.
* @param y_
* the y coordinate.
*/
public Vector3D(float x_, float y_) {
x = x_;
y = y_;
z = 0f;
}
/**
* Constructor for an empty vector: x, y, and z are set to 0.
*/
public Vector3D() {
x = 0f;
y = 0f;
z = 0f;
}
/**
* Set the x coordinate.
*
* @param x_
* the x coordinate.
*/
public void setX(float x_) {
x = x_;
}
/**
* Set the y coordinate.
*
* @param y_
* the y coordinate.
*/
public void setY(float y_) {
y = y_;
}
/**
* Set the z coordinate.
*
* @param z_
* the z coordinate.
*/
public void setZ(float z_) {
z = z_;
}
/**
* Set x,y, and z coordinates.
*
* @param x_
* the x coordinate.
* @param y_
* the y coordinate.
* @param z_
* the z coordinate.
*/
public void setXYZ(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
/**
* Set x,y, and z coordinates from a Vector3D object.
*
* @param v
* the Vector3D object to be copied
*/
public void setXYZ(Vector3D v) {
x = v.x;
y = v.y;
z = v.z;
}
/**
* Calculate the magnitude (length) of the vector
*
* @return the magnitude of the vector
*/
public float magnitude() {
return (float) Math.sqrt(x * x + y * y + z * z);
}
/**
* Copy the vector
*
* @return a copy of the vector
*/
public Vector3D copy() {
return new Vector3D(x, y, z);
}
/**
* Copy the vector
*
* @param v
* the vector to be copied
* @return a copy of the vector
*/
public static Vector3D copy(Vector3D v) {
return new Vector3D(v.x, v.y, v.z);
}
/**
* Add a vector to this vector
*
* @param v
* the vector to be added
*/
public void add(Vector3D v) {
x += v.x;
y += v.y;
z += v.z;
}
/**
* Subtract a vector from this vector
*
* @param v
* the vector to be subtracted
*/
public void sub(Vector3D v) {
x -= v.x;
y -= v.y;
z -= v.z;
}
/**
* Multiply this vector by a scalar
*
* @param n
* the value to multiply by
*/
public void mult(float n) {
x *= n;
y *= n;
z *= n;
}
/**
* Divide this vector by a scalar
*
* @param n
* the value to divide by
*/
public void div(float n) {
x /= n;
y /= n;
z /= n;
}
/**
* Calculate the dot product with another vector
*
* @return the dot product
*/
public float dot(Vector3D v) {
float dot = x * v.x + y * v.y;
return dot;
}
/**
* Calculate the cross product with another vector
*
* @return the cross product
*/
public Vector3D cross(Vector3D v) {
float crossX = y * v.z - v.y * z;
float crossY = z * v.x - v.z * x;
float crossZ = x * v.y - v.x * y;
return (new Vector3D(crossX, crossY, crossZ));
}
/**
* Normalize the vector to length 1 (make it a unit vector)
*/
public void normalize() {
float m = magnitude();
if (m > 0) {
div(m);
}
}
/**
* Limit the magnitude of this vector
*
* @param max
* the maximum length to limit this vector
*/
public void limit(float max) {
if (magnitude() > max) {
normalize();
mult(max);
}
}
/**
* Calculate the angle of rotation for this vector (only 2D vectors)
*
* @return the angle of rotation
*/
public float heading2D() {
float angle = (float) Math.atan2(-y, x);
return -1 * angle;
}
/**
* Add two vectors
*
* @param v1
* a vector
* @param v2
* another vector
* @return a new vector that is the sum of v1 and v2
*/
public static Vector3D add(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
return v;
}
/**
* Subtract one vector from another
*
* @param v1
* a vector
* @param v2
* another vector
* @return a new vector that is v1 - v2
*/
public static Vector3D sub(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
return v;
}
/**
* Divide a vector by a scalar
*
* @param v1
* a vector
* @param n
* scalar
* @return a new vector that is v1 / n
*/
public static Vector3D div(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x / n, v1.y / n, v1.z / n);
return v;
}
/**
* Multiply a vector by a scalar
*
* @param v1
* a vector
* @param n
* scalar
* @return a new vector that is v1 * n
*/
public static Vector3D mult(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x * n, v1.y * n, v1.z * n);
return v;
}
/**
* Calculate the Euclidean distance between two points (considering a point
* as a vector object)
*
* @param v1
* a vector
* @param v2
* another vector
* @return the Euclidean distance between v1 and v2
*/
public static float distance(Vector3D v1, Vector3D v2) {
float dx = v1.x - v2.x;
float dy = v1.y - v2.y;
float dz = v1.z - v2.z;
return (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
}
/**
* Calculate the angle between two vectors, using the dot product
*
* @param v1
* a vector
* @param v2
* another vector
* @return the angle between the vectors
*/
public static float angleBetween(Vector3D v1, Vector3D v2) {
float dot = v1.dot(v2);
float theta = (float) Math
.acos(dot / (v1.magnitude() * v2.magnitude()));
return theta;
}
}