Skip to content

Instantly share code, notes, and snippets.

@Eggbertx
Last active June 20, 2020 01:07
Show Gist options
  • Select an option

  • Save Eggbertx/349076b7a0c2f0cf11abcec7f3a5edec to your computer and use it in GitHub Desktop.

Select an option

Save Eggbertx/349076b7a0c2f0cf11abcec7f3a5edec to your computer and use it in GitHub Desktop.
An ES6 JavaScript class for handling vector algebra in two or three dimensions
/**
* A class for handling vector algebra in two or three dimensions
* If you only need a two-dimensional vector, you can just ignore
* the z property and all z parameters, since they aren't required
*
* See https://en.wikipedia.org/wiki/Euclidean_vector
*/
export class Vector {
/**
* Constructs a Vector object
*
* @param {number} x
* @param {number} y
* @param {number} z (optional)
*/
constructor(x = 0, y = 0, z = 0) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Use distance formula to calculate length of vector
*
* @return {number} (0,0) to (this.x, this.y, this.z)
*/
get length() {
return Math.sqrt(
Math.pow(this.x, 2) +
Math.pow(this.y, 2) +
Math.pow(this.z, 2)
);
}
/**
* Theta (angle in radians) of vector on x,y plane
*/
get thetaXY() {
return Math.atan2(this.y, this.x);
}
/**
* Theta (angle in radians) of vector on y,z plane
*/
get thetaYZ() {
return Math.atan2(this.z, this.y);
}
/**
* Theta (angle in radians) of vector on z,x plane
*/
get thetaZX() {
return Math.atan2(this.x, this.z);
}
/**
* Calculate the angle between this and another vector in radians
*
* @param {Vector} vector the other vector
* @return {number} angle in radians
*/
angleBetween(vector) {
return Math.acos(this.dotProduct(vector) / (this.length * vector.length));
// return Math.atan2(this.y - vector.y, this.x - vector.x);
}
/**
* Add two vectors together
*
* @param {Vector} vector the vector to add to this
*/
add(vector) {
this.x += vector.x;
this.y += vector.y;
this.z += vector.z;
}
/**
* Subtract two vectors
*
* @param {Vector} vector the vector to subtract from this
*/
subtract(vector) {
this.x -= vector.x;
this.y -= vector.y;
this.z -= vector.z;
}
/**
* Scale up by scalar
*
* @param {number} scalar the scalar to multiply by
*/
scale(by) {
this.x *= by;
this.y *= by;
this.z *= by;
}
/**
* Scale by individual axes
*
* @param {number} amount to scale the x axis by
* @param {number} amount to scale the y axis by
* @param {number} amount to scale the z axis by
*/
scaleAxes(x,y,z) {
this.x *= x;
this.y *= y;
this.z *= z;
}
/**
* Calculate a dot product
*
* See https://en.wikipedia.org/wiki/Euclidean_vector#Dot_product
* @param {Vector} vector the vector to multiply by
* @return {number} scalar product of two Vectors
*/
dotProduct(vector) {
return this.x * vector.x + this.y * vector.y + this.z * vector.z;
}
/**
* Calculates a Cross product
*
* see https://en.wikipedia.org/wiki/Euclidean_vector#Cross_product
* @param {Vector} the vector to multiply by
* @return {Vector} Vector product of two Vectors
*/
crossProduct(vector) {
return new Vector(
this.y * vector.z - this.z * vector.y,
this.z * vector.x - this.x * vector.z,
this.x * vector.y - this.y * vector.x
);
}
/**
* Return a copy of this
* @return {Vector} the clone
*/
clone() {
return new Vector(this.x, this.y, this.z);
}
/**
* Rotates the vector on a single axis
* (TODO: Add ability to rotate on multiple axes)
*
* @param {number} angle rotate around this angle (in radians)
* @param {string} axis (optional) axis to rotate around,
* must be 'x', 'y' * or 'z'. Defaults to 'z'
*/
rotate(angle, axis = 'z') {
var cosA = Math.cos(angle);
var sinA = Math.sin(angle);
let _x, _y, _z;
switch(axis) {
case 'X':
case 'x':
_y = this.y * cosA + this.z * sinA;
_z = this.z * cosA - this.y * sinA;
this.y = _y;
this.z = _z;
break;
case 'Y':
case 'y':
_z = this.z * cosA + this.x * sinA;
_x = this.x * cosA - this.z * sinA;
this.z = _z;
this.x = _x;
break;
default:
// z, undefined, or invalid
_x = this.x * cosA - this.y * sinA;
_y = this.x * sinA + this.y * sinA;
this.x = _x;
this.y = _y;
break;
}
// this.roundAxes();
}
/**
* Return a string representation of the Vector
*
* @override
* @return {string} a human-readable string for debugging
*/
toString() {
return `Vector(${this.x},${this.y},${this.z})`;
}
/**
* Round the axes to three decimal places, automatically done by rotate()
*/
roundAxes() {
this.x = Math.round(this.x * 1000) / 1000;
this.y = Math.round(this.y * 1000) / 1000;
this.z = Math.round(this.z * 1000) / 1000;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment