js-2dmath
Version:
Fast 2d geometry math: Vector2, Rectangle, Circle, Matrix2x3 (2D transformation), Circle, BoundingBox, Line2, Segment2, Intersections, Distances, Transitions (animation/tween), Random numbers, Noise
1,081 lines (976 loc) • 21.2 kB
JavaScript
/**
* Stability: 2 (fixes / performance improvements)
*
* Vec2 is represented as a two coordinates array
* [x:Number, y:Number]
*/
var aux_vec = [0, 0],
__x = 0,
__y = 0,
aux_number1 = 0,
aux_number2 = 0,
aux_number3 = 0,
//cache
EPS = Math.EPS,
acos = Math.acos,
cos = Math.cos,
sqrt = Math.sqrt,
__abs = Math.abs,
sin = Math.sin,
__min = Math.min,
atan2 = Math.atan2,
__pow = Math.pow,
HALF_NPI = Math.HALF_NPI,
HALF_PI = Math.HALF_PI,
DEG_TO_RAD = Math.DEG_TO_RAD,
Vec2;
/**
* Create a Vec2 given two coords
*
* @param {Vec2|Number} x
* @param {Number} y
* @return {Vec2}
*/
function create(x, y) {
return [x, y];
}
/**
* Create a Vec2 given length and angle
*
* @param {Number} length
* @param {Number} degrees
* @return {Vec2}
*/
function dFromPolar(length, degrees) {
return fromPolar(length, degrees * DEG_TO_RAD);
}
/**
* Create a Vec2 given length and angle
*
* @param {Number} length
* @param {Number} radians
* @return {Vec2}
*/
function fromPolar(length, radians) {
return [length * sin(radians), length * cos(radians)];
}
/**
* Create an empty Vec2
*
* @return {Vec2}
*/
function zero() {
return [0, 0];
}
/**
* Clone given vec2
*
* @param {Vec2} v1
* @return {Vec2}
*/
function clone(v1) {
return [v1[0], v1[1]];
}
// **********************************************************
// comparison operations
// **********************************************************
/**
* Returns true if both vectors are equal(same coords)
*
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Boolean}
*/
function equals(v1, v2) {
return v2[0] === v1[0] && v2[1] === v1[1];
}
/**
* Returns true if both vectors are "almost(Math.EPS)" equal
*
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Boolean}
*/
function equalsEpsilon(v1, v2) {
aux_number1 = __abs(v2[0] - v1[0]);
aux_number2 = __abs(v2[1] - v1[1]);
return aux_number1 < EPS && aux_number2 < EPS;
}
/**
* Returns true both coordinates of v1 area greater than v2
*
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Boolean}
*/
function gt(v1, v2) {
return v2[0] > v1[0] && v2[1] > v1[1];
}
/**
* Returns true both coordinates of v1 area lesser than v2
*
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Boolean}
*/
function lt(v1, v2) {
return v2[0] < v1[0] && v2[1] < v1[1];
}
/**
* Returns true if the distance between v1 and v2 is less than dist.
*
* @param {Vec2} v1
* @param {Vec2} v2
* @param {Number} dist
* @return {Boolean}
*/
function near(v1, v2, dist) {
// maybe inline
aux_number1 = sqrDistance(v1, v2);
return aux_number1 < dist * dist;
}
/**
* * 0 equal
* * 1 top
* * 2 top-right
* * 3 right
* * 4 bottom right
* * 5 bottom
* * 6 bottom-left
* * 7 left
* * 8 top-left
*
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Number}
*/
function compare(v1, v2) {
var v1x = v1[0],
v1y = v1[1],
v2x = v2[0],
v2y = v2[1];
if (v2x === v1x && v2y === v1y) {
return 0;
}
if (v2x === v1x) {
return v2y > v1y ? 1 : 5;
}
if (v2y === v1y) {
return v2x > v1x ? 3 : 7;
}
if (v2x > v1x) {
if (v2y > v1y) {
return 2;
}
if (v2y < v1y) {
return 4;
}
}
if (v2x < v1x) {
if (v2y < v1y) {
return 6;
}
if (v2y > v1y) {
return 8;
}
}
return -1;
}
// **********************************************************
// validation
// **********************************************************
/**
* The vector does not contain any not number value: ±Infinity || NaN
*
* @param {Vec2} v1
* @return {Boolean}
*/
function isValid(v1) {
return !(v1[0] === Infinity || v1[0] === -Infinity || isNaN(v1[0]) || v1[1] === Infinity || v1[1] === -Infinity || isNaN(v1[1]));
}
/**
* Any coordinate is NaN? -> true
*
* @param {Vec2} v1
* @return {Boolean}
*/
function isNaN(v1) {
return isNaN(v1[0]) || isNaN(v1[1]);
}
// **********************************************************
// first parameter is the output
// **********************************************************
/**
* Copy v1 into out_vec2
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @return {Vec2}
*/
function copy(out_vec2, v1) {
out_vec2[0] = v1[0];
out_vec2[1] = v1[1];
return out_vec2;
}
/**
* Negate v1 into out_vec2
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @return {Vec2}
*/
function negate(out_vec2, v1) {
out_vec2[0] = -v1[0];
out_vec2[1] = -v1[1];
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @return {Vec2}
*/
function normalize(out_vec2, v1) {
__x = v1[0];
__y = v1[1];
aux_number3 = sqrt(__x * __x + __y * __y);
if (aux_number3 > EPS) {
aux_number3 = 1 / aux_number3;
out_vec2[0] = v1[0] * aux_number3;
out_vec2[1] = v1[1] * aux_number3;
}
return out_vec2;
}
/**
* Normalize v1 but squared no use sqrt, for performance.
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @return {Vec2}
*/
function normalizeSq(out_vec2, v1) {
__x = v1[0];
__y = v1[1];
aux_number3 = __x * __x + __y * __y;
if (aux_number3 > EPS * EPS) {
aux_number3 = 1 / aux_number3;
out_vec2[0] = v1[0] * aux_number3;
out_vec2[1] = v1[1] * aux_number3;
}
return out_vec2;
}
/**
* Rotate the vector clockwise
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @return {Vec2}
*/
function perpendicular(out_vec2, v1) {
aux_number1 = v1[0];
out_vec2[0] = v1[1];
out_vec2[1] = -aux_number1;
return out_vec2;
}
/**
* Rotate the vector counterclockwise
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @return {Vec2}
*/
function rperpendicular(out_vec2, v1) {
aux_number1 = v1[0];
out_vec2[0] = -v1[1];
out_vec2[1] = aux_number1;
return out_vec2;
}
/**
* Linearly interpolate between a and b.
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @param {Number} t
* @return {Vec2}
*/
function lerp(out_vec2, v1, v2, t) {
out_vec2[0] = v1[0] + (v2[0] - v1[0]) * t;
out_vec2[1] = v1[1] + (v2[1] - v1[1]) * t;
return out_vec2;
}
/**
* Linearly interpolate between v1 towards v2 by distance d.
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @param {Number} d
* @return {Vec2}
*/
function lerpconst(out_vec2, v1, v2, d) {
out_vec2[0] = v2[0] - v1[0];
out_vec2[1] = v2[1] - v1[1];
clamp(out_vec2, out_vec2, d);
out_vec2[0] += v1[0];
out_vec2[1] += v1[1];
return out_vec2;
}
/**
* Spherical linearly interpolate between v1 and v2.
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @param {Number} t
* @return {Vec2}
*/
function slerp(out_vec2, v1, v2, t) {
var omega = acos(dot(v1, v2)),
denom;
if (omega) {
denom = 1.0 / sin(omega);
scale(out_vec2, v1, sin((1.0 - t) * omega) * denom);
scale(aux_vec, sin(t * omega) * denom);
return add(out_vec2, out_vec2, aux_vec);
}
return copy(out_vec2, v1);
}
/**
* Spherical linearly interpolate between v1 towards v2 by no more than angle a in radians.
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @param {Number} radians
* @return {Vec2}
*/
function slerpconst(out_vec2, v1, v2, radians) {
var _radians = acos(dot(v1, v2));
return slerp(out_vec2, v1, v2, __min(radians, _radians) / _radians);
}
/**
* Returns the unit length vector for the given angle (in radians).
*
* @param {Vec2} out_vec2
* @param {Number} radians
* @return {Vec2}
*/
function forAngle(out_vec2, radians) {
out_vec2[0] = cos(radians);
out_vec2[1] = sin(radians);
return out_vec2;
}
/**
* Returns the vector projection of v1 onto v2.
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Vec2}
*/
function project(out_vec2, v1, v2) {
multiply(out_vec2, v1, v2);
scale(out_vec2, dot(v1, v2) / dot(v2, v2));
return out_vec2;
}
/**
* Rotates the point by the given angle
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} radians
* @return {Vec2}
*/
function rotate(out_vec2, v1, radians) {
var s = sin(radians),
c = cos(radians);
__x = v1[0];
__y = v1[1];
out_vec2[0] = __x * c - __y * s;
out_vec2[1] = __y * c + __x * s;
return out_vec2;
}
/**
* Rotates the point by the given angle around an optional center point.
*
* @note center cannot be out_vec2
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} radians
* @param {Vec2} center
* @return {Vec2}
*/
function rotateFrom(out_vec2, v1, radians, center) {
subtract(out_vec2, v1, center);
__x = out_vec2[0];
__y = out_vec2[1];
var s = sin(radians),
c = cos(radians);
out_vec2[0] = __x * c - __y * s;
out_vec2[1] = __y * c + __x * s;
add(out_vec2, out_vec2, center);
return out_vec2;
}
/**
* Rotate a vector given "angle" by a normalized vector v2_n
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2_n
* @return {Vec2}
*/
function rotateVec(out_vec2, v1, v2_n) {
out_vec2[0] = v1[0] * v2_n[0] - v1[1] * v2_n[1];
out_vec2[1] = v1[0] * v2_n[1] + v1[1] * v2_n[0];
return out_vec2;
}
/**
* Un-rotate a vector given "angle" by a normalized vector v2_n
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2_n
* @return {Vec2}
*/
function unrotateVec(out_vec2, v1, v2_n) {
out_vec2[0] = v1[0] * v2_n[0] + v1[1] * v2_n[1];
out_vec2[1] = v1[1] * v2_n[0] - v1[0] * v2_n[1];
return out_vec2;
}
/**
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Vec2}
*/
function midPoint(out_vec2, v1, v2) {
out_vec2[0] = (v1[0] + v2[0]) * 0.5;
out_vec2[1] = (v1[1] + v2[1]) * 0.5;
return out_vec2;
}
var reflect_factor;
/**
* Reflect v1 by the imaginary line v2_n
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2_n
* @return {Vec2}
*/
function reflect(out_vec2, v1, v2_n) {
reflect_factor = dot(v1, v2_n);
scale(out_vec2, v2_n, 2 * reflect_factor);
subtract(out_vec2, v1, out_vec2);
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Vec2}
*/
function subtract(out_vec2, v1, v2) {
out_vec2[0] = v1[0] - v2[0];
out_vec2[1] = v1[1] - v2[1];
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} x
* @param {Number} y
* @return {Vec2}
*/
function subtract2(out_vec2, v1, x, y) {
out_vec2[0] = v1[0] - x;
out_vec2[1] = v1[1] - y;
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Vec2}
*/
function add(out_vec2, v1, v2) {
out_vec2[0] = v1[0] + v2[0];
out_vec2[1] = v1[1] + v2[1];
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} x
* @param {Number} y
* @return {Vec2}
*/
function add2(out_vec2, v1, x, y) {
out_vec2[0] = v1[0] + x;
out_vec2[1] = v1[1] + y;
return out_vec2;
}
/**
* @see scale
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Vec2}
*/
function multiply(out_vec2, v1, v2) {
out_vec2[0] = v1[0] * v2[0];
out_vec2[1] = v1[1] * v2[1];
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} x
* @param {Number} y
* @return {Vec2}
*/
function multiply2(out_vec2, v1, x, y) {
out_vec2[0] = v1[0] * x;
out_vec2[1] = v1[1] * y;
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Vec2}
*/
function divide(out_vec2, v1, v2) {
out_vec2[0] = v1[0] / v2[0];
out_vec2[1] = v1[1] / v2[1];
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} x
* @param {Number} y
* @return {Vec2}
*/
function divide2(out_vec2, v1, x, y) {
out_vec2[0] = v1[0] / x;
out_vec2[1] = v1[1] / y;
return out_vec2;
}
/**
* @see multiply
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} factor
* @return {Vec2}
*/
function scale(out_vec2, v1, factor) {
out_vec2[0] = v1[0] * factor;
out_vec2[1] = v1[1] * factor;
return out_vec2;
}
/**
* (x1^y, y1^y)
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} y
* @return {Vec2}
*/
function pow(out_vec2, v1, y) {
if (y === 2) {
out_vec2[0] = v1[0] * v1[0];
out_vec2[1] = v1[1] * v1[1];
} else {
out_vec2[0] = __pow(v1[0], y);
out_vec2[1] = __pow(v1[1], y);
}
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Vec2}
*/
function max(out_vec2, v1, v2) {
out_vec2[0] = v1[0] > v2[0] ? v1[0] : v2[0];
out_vec2[1] = v1[1] > v2[1] ? v1[1] : v2[1];
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Vec2}
*/
function min(out_vec2, v1, v2) {
out_vec2[0] = v1[0] < v2[0] ? v1[0] : v2[0];
out_vec2[1] = v1[1] < v2[1] ? v1[1] : v2[1];
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @return {Vec2}
*/
function abs(out_vec2, v1) {
out_vec2[0] = __abs(v1[0]);
out_vec2[1] = __abs(v1[1]);
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @param {Number} factor
* @return {Vec2}
*/
function scaleAndAdd(out_vec2, v1, v2, factor) {
out_vec2[0] = v1[0] + (v2[0] * factor);
out_vec2[1] = v1[1] + (v2[1] * factor);
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} length
* @return {Vec2}
*/
function clamp(out_vec2, v1, length) {
out_vec2[0] = v1[0];
out_vec2[1] = v1[1];
if (dot(v1, v1) > length * length) {
normalize(out_vec2);
multiply(out_vec2, length);
}
return out_vec2;
}
/**
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Number} length
*/
function truncate(out_vec2, v1, length) {
var length_sq = v1[0] * v1[0] + v1[1] * v1[1];
if (length_sq > length * length) {
return scale(out_vec2, v1, length / sqrt(length_sq));
}
out_vec2[0] = v1[0];
out_vec2[1] = v1[1];
return out_vec2;
}
/**
* Cross product between a vector and the Z component of a vector
* AKA Rotate CW and scale
*
* @todo test use rprependicular ?
*
* @param {Vec2} out_vec2
* @param {Vec2} vec2
* @param {Number} factor
* @return {Number}
*/
function crossVZ(out_vec2, vec2, factor) {
rotate(out_vec2, vec2, HALF_NPI); // Rotate according to the right hand rule
return scale(out_vec2, out_vec2, factor); // Scale with z
}
/**
* Cross product between a vector and the Z component of a vector
* AKA Rotate CCW and scale
*
* @todo test use prependicular ?
*
* @param {Vec2} out_vec2
* @param {Vec2} vec2
* @param {Number} factor
* @return {Vec2}
*/
function crossZV(out_vec2, factor, vec2) {
rotate(out_vec2, vec2, HALF_PI);
return scale(out_vec2, out_vec2, factor);
}
var tp_left = [0, 0],
tp_right = [0, 0];
/**
* (A x B) x C = B(C · A) - A(C · B)
* (A x B) x C = B(A.dot(C)) - A(B.dot(C))
*
* @param {Vec2} out_vec2
* @param {Vec2} v1
* @param {Vec2} v2
* @param {Vec2} v3
*/
function tripleProduct(out_vec2, v1, v2, v3) {
scale(tp_left, v2, dot(v1, v3));
scale(tp_right, v1, dot(v2, v3));
return subtract(out_vec2, tp_left, tp_right);
}
// **********************************************************
// functions that return numbers
// **********************************************************
/**
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Number}
*/
function magnitude(v1, v2) {
__x = v1[0] - v2[0];
__y = v1[1] - v2[1];
return __x / __y;
}
/**
* v1 · v2 = |a| * |b| * sin θ
*
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Number}
*/
function dot(v1, v2) {
return v1[0] * v2[0] + v1[1] * v2[1];
}
/**
* v1 × v2 = |a| * |b| * sin θ
*
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Number}
*/
function cross(v1, v2) {
return v1[0] * v2[1] - v1[1] * v2[0];
}
/**
* @param {Vec2} v1
* @return {Number}
*/
function toAngle(v1) {
return atan2(v1[1], v1[0]);
}
/**
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Number}
*/
function angleTo(v1, v2) {
return atan2(v2[1] - v1[1], v2[0] - v1[0]);
}
var distance_x,
distance_y;
/**
* Returns the distance between v1 and v2.
*
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Number}
*/
function distance(v1, v2) {
//subtract
distance_x = v2[0] - v1[0];
distance_y = v2[1] - v1[1];
//sqrLength
return sqrt(distance_x * distance_x + distance_y * distance_y);
}
/**
* Distance without using sqrt (squared distance)
*
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Number}
*/
function sqrDistance(v1, v2) {
//subtract
distance_x = v1[0] - v2[0];
distance_y = v1[1] - v2[1];
//sqrLength
return distance_x * distance_x + distance_y * distance_y;
}
/**
* Return vector the length.
*
* @param {Vec2} v1
* @return {Number}
*/
function length(v1) {
return sqrt(v1[0] * v1[0] + v1[1] * v1[1]);
}
/**
* Squared length (no sqrt)
*
* @param {Vec2} v1
* @return {Number}
*/
function sqrLength(v1) {
return v1[0] * v1[0] + v1[1] * v1[1];
}
/**
* Return true if v2 is between v1 and v3(inclusive)
*
* @param {Vec2} v1
* @param {Vec2} v2
* @param {Vec2} v3
* @return {Boolean}
*/
function within(v1, v2, v3) {
return ((v1[0] <= v2[0] && v2[0] <= v3[0]) || (v3[0] <= v2[0] && v2[0] <= v1[0])) &&
((v1[1] <= v2[1] && v2[1] <= v3[1]) || (v3[1] <= v2[1] && v2[1] <= v1[1]));
}
/**
* Return true if q is between p and r(inclusive)
*
* @param {Number} px
* @param {Number} py
* @param {Number} qx
* @param {Number} qy
* @param {Number} rx
* @param {Number} ry
* @return {Boolean}
*/
function $within(px, py, qx, qy, rx, ry) {
return ((px <= qx && qx <= rx) || (rx <= qx && qx <= px)) &&
((py <= qy && qy <= ry) || (ry <= qy && qy <= py));
}
/**
* p is near x ± dist ("box test")
*
* @param {Number} px
* @param {Number} py
* @param {Number} qx
* @param {Number} qy
* @param {Number} dist EPS
* @return {Boolean}
*/
function $near(px, py, qx, qy, dist) {
return (px > qx ? (px - qx) < dist : (qx - px) < dist) &&
(py > qy ? (py - qy) < dist : (qy - py) < dist);
}
/**
*
* @param {Number} x1
* @param {Number} y1
* @param {Number} x2
* @param {Number} y2
* @return {Number}
*/
function $cross(x1, y1, x2, y2) {
return x1 * y2 - y1 * x2;
}
/**
*
* @param {Number} x1
* @param {Number} y1
* @param {Number} x2
* @param {Number} y2
* @return {Number}
*/
function $dot(x1, y1, x2, y2) {
return x1 * x2 + y1 * y2;
}
/**
* Swap vectors, both will be modified.
* for lazy people
* @param {Vec2} v1
* @param {Vec2} v2
* @return {Undefined}
*/
function swap(v1, v2) {
__x = v2[0];
v2[0] = v1[0];
v1[0] = __x;
__x = v2[1];
v2[1] = v1[1];
v1[1] = __x;
}
/*
* (x, y) with only two decimals, for readability
* @param {Vec2} v1
* @return {String}
*/
function toString(v1) {
return "(" + v1[0].toFixed(2) + "," + v1[1].toFixed(2) + ")";
}
Vec2 = {
ZERO: [0, 0],
create: create,
dFromPolar: dFromPolar,
fromPolar: fromPolar,
zero: zero,
clone: clone,
equals: equals,
equalsEpsilon: equalsEpsilon,
gt: gt,
lt: lt,
near: near,
isValid: isValid,
isNaN: isNaN,
copy: copy,
negate: negate,
perpendicular: perpendicular,
perp: perpendicular,
rotateCW: perpendicular,
normalize: normalize,
normalizeSq: normalizeSq,
rperpendicular: rperpendicular,
rperp: rperpendicular,
rotateCCW: rperpendicular,
lerp: lerp,
interpolate: lerp,
lerpconst: lerpconst,
slerp: slerp,
slerpconst: slerpconst,
forAngle: forAngle,
project: project,
rotate: rotate,
rotateFrom: rotateFrom,
rotateVec: rotateVec,
unrotateVec: unrotateVec,
midPoint: midPoint,
reflect: reflect,
subtract: subtract,
subtract2: subtract2,
add: add,
add2: add2,
multiply: multiply,
multiply2: multiply2,
divide: divide,
divide2: divide2,
scale: scale,
pow: pow,
max: max,
min: min,
abs: abs,
scaleAndAdd: scaleAndAdd,
clamp: clamp,
truncate: truncate,
magnitude: magnitude,
compare: compare,
dot: dot,
cross: cross,
crossVZ: crossVZ,
crossZV: crossZV,
toAngle: toAngle,
angle: toAngle,
angleTo: angleTo,
distance: distance,
length: length,
sqrDistance: sqrDistance,
sqrLength: sqrLength,
within: within,
swap: swap,
tripleProduct: tripleProduct,
// alias
eq: equals,
sub: subtract,
sub2: subtract2,
mul: multiply,
mul2: multiply2,
div: divide,
div2: divide2,
distanceSq: sqrDistance,
lengthSq: sqrLength,
$within: $within,
$near: $near,
$cross: $cross,
$dot: $dot,
toString: toString
};
module.exports = Vec2;