File: src/geometry/Vector.js
/**
* The `Matter.Vector` module contains methods for creating and manipulating vectors.
* Vectors are the basis of all the geometry related operations in the engine.
* A `Matter.Vector` object is of the form `{ x: 0, y: 0 }`.
*
* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
*
* @class Vector
*/
// TODO: consider params for reusing vector objects
var Vector = {};
module.exports = Vector;
(function() {
/**
* Creates a new vector.
* @method create
* @param {number} x
* @param {number} y
* @return {vector} A new vector
*/
Vector.create = function(x, y) {
return { x: x || 0, y: y || 0 };
};
/**
* Returns a new vector with `x` and `y` copied from the given `vector`.
* @method clone
* @param {vector} vector
* @return {vector} A new cloned vector
*/
Vector.clone = function(vector) {
return { x: vector.x, y: vector.y };
};
/**
* Returns the magnitude (length) of a vector.
* @method magnitude
* @param {vector} vector
* @return {number} The magnitude of the vector
*/
Vector.magnitude = function(vector) {
return Math.sqrt((vector.x * vector.x) + (vector.y * vector.y));
};
/**
* Returns the magnitude (length) of a vector (therefore saving a `sqrt` operation).
* @method magnitudeSquared
* @param {vector} vector
* @return {number} The squared magnitude of the vector
*/
Vector.magnitudeSquared = function(vector) {
return (vector.x * vector.x) + (vector.y * vector.y);
};
/**
* Rotates the vector about (0, 0) by specified angle.
* @method rotate
* @param {vector} vector
* @param {number} angle
* @param {vector} [output]
* @return {vector} The vector rotated about (0, 0)
*/
Vector.rotate = function(vector, angle, output) {
var cos = Math.cos(angle), sin = Math.sin(angle);
if (!output) output = {};
var x = vector.x * cos - vector.y * sin;
output.y = vector.x * sin + vector.y * cos;
output.x = x;
return output;
};
/**
* Rotates the vector about a specified point by specified angle.
* @method rotateAbout
* @param {vector} vector
* @param {number} angle
* @param {vector} point
* @param {vector} [output]
* @return {vector} A new vector rotated about the point
*/
Vector.rotateAbout = function(vector, angle, point, output) {
var cos = Math.cos(angle), sin = Math.sin(angle);
if (!output) output = {};
var x = point.x + ((vector.x - point.x) * cos - (vector.y - point.y) * sin);
output.y = point.y + ((vector.x - point.x) * sin + (vector.y - point.y) * cos);
output.x = x;
return output;
};
/**
* Normalises a vector (such that its magnitude is `1`).
* @method normalise
* @param {vector} vector
* @return {vector} A new vector normalised
*/
Vector.normalise = function(vector) {
var magnitude = Vector.magnitude(vector);
if (magnitude === 0)
return { x: 0, y: 0 };
return { x: vector.x / magnitude, y: vector.y / magnitude };
};
/**
* Returns the dot-product of two vectors.
* @method dot
* @param {vector} vectorA
* @param {vector} vectorB
* @return {number} The dot product of the two vectors
*/
Vector.dot = function(vectorA, vectorB) {
return (vectorA.x * vectorB.x) + (vectorA.y * vectorB.y);
};
/**
* Returns the cross-product of two vectors.
* @method cross
* @param {vector} vectorA
* @param {vector} vectorB
* @return {number} The cross product of the two vectors
*/
Vector.cross = function(vectorA, vectorB) {
return (vectorA.x * vectorB.y) - (vectorA.y * vectorB.x);
};
/**
* Returns the cross-product of three vectors.
* @method cross3
* @param {vector} vectorA
* @param {vector} vectorB
* @param {vector} vectorC
* @return {number} The cross product of the three vectors
*/
Vector.cross3 = function(vectorA, vectorB, vectorC) {
return (vectorB.x - vectorA.x) * (vectorC.y - vectorA.y) - (vectorB.y - vectorA.y) * (vectorC.x - vectorA.x);
};
/**
* Adds the two vectors.
* @method add
* @param {vector} vectorA
* @param {vector} vectorB
* @param {vector} [output]
* @return {vector} A new vector of vectorA and vectorB added
*/
Vector.add = function(vectorA, vectorB, output) {
if (!output) output = {};
output.x = vectorA.x + vectorB.x;
output.y = vectorA.y + vectorB.y;
return output;
};
/**
* Subtracts the two vectors.
* @method sub
* @param {vector} vectorA
* @param {vector} vectorB
* @param {vector} [output]
* @return {vector} A new vector of vectorA and vectorB subtracted
*/
Vector.sub = function(vectorA, vectorB, output) {
if (!output) output = {};
output.x = vectorA.x - vectorB.x;
output.y = vectorA.y - vectorB.y;
return output;
};
/**
* Multiplies a vector and a scalar.
* @method mult
* @param {vector} vector
* @param {number} scalar
* @return {vector} A new vector multiplied by scalar
*/
Vector.mult = function(vector, scalar) {
return { x: vector.x * scalar, y: vector.y * scalar };
};
/**
* Divides a vector and a scalar.
* @method div
* @param {vector} vector
* @param {number} scalar
* @return {vector} A new vector divided by scalar
*/
Vector.div = function(vector, scalar) {
return { x: vector.x / scalar, y: vector.y / scalar };
};
/**
* Returns the perpendicular vector. Set `negate` to true for the perpendicular in the opposite direction.
* @method perp
* @param {vector} vector
* @param {bool} [negate=false]
* @return {vector} The perpendicular vector
*/
Vector.perp = function(vector, negate) {
negate = negate === true ? -1 : 1;
return { x: negate * -vector.y, y: negate * vector.x };
};
/**
* Negates both components of a vector such that it points in the opposite direction.
* @method neg
* @param {vector} vector
* @return {vector} The negated vector
*/
Vector.neg = function(vector) {
return { x: -vector.x, y: -vector.y };
};
/**
* Returns the angle between the vector `vectorB - vectorA` and the x-axis in radians.
* @method angle
* @param {vector} vectorA
* @param {vector} vectorB
* @return {number} The angle in radians
*/
Vector.angle = function(vectorA, vectorB) {
return Math.atan2(vectorB.y - vectorA.y, vectorB.x - vectorA.x);
};
/**
* Temporary vector pool (not thread-safe).
* @property _temp
* @type {vector[]}
* @private
*/
Vector._temp = [
Vector.create(), Vector.create(),
Vector.create(), Vector.create(),
Vector.create(), Vector.create()
];
})();