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,454 lines (1,248 loc) • 1.1 MB
JavaScript
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"js-2dmath":[function(require,module,exports){
module.exports=require('Focm2+');
},{}],"Focm2+":[function(require,module,exports){
require("./lib/math.js");
module.exports = {
Vec2: require("./lib/vec2.js"),
Line2: require("./lib/line2.js"),
Segment2: require("./lib/segment2.js"),
//geom
Rectangle: require("./lib/rectangle.js"),
AABB2: require("./lib/aabb2.js"),
Circle: require("./lib/circle.js"),
Triangle: require("./lib/triangle.js"),
Polygon: require("./lib/polygon.js"),
Beizer: require("./lib/beizer.js"),
Matrix23: require("./lib/matrix23.js"),
Matrix22: require("./lib/matrix22.js"),
Collide: require("./lib/collide.js"),
Intersection: require("./lib/intersection.js"),
Transitions: require("./lib/transitions.js"),
Xorshift: require("./lib/xorshift.js"),
Noise: require("./lib/noise.js"),
Draw: require("./lib/draw.js"),
NMtree: require("./lib/nmtree.js"),
Collision : {
Response: require("./lib/collision/response.js"),
GJK: require("./lib/collision/gjk.js"),
EPA: require("./lib/collision/epa.js"),
Manifold: require("./lib/collision/manifold.js"),
SAT: require("./lib/collision/sat.js"),
Resolve: require("./lib/collision/resolve.js")
},
NumericalIntegration: {
RK4: require("./lib/numerical-integration/rk4.js"),
Verlet: require("./lib/numerical-integration/verlet.js"),
Euler: require("./lib/numerical-integration/euler.js")
}
};
module.exports.globalize = function (object) {
var i;
for (i in module.exports) {
if ("globalize" !== i) {
object[i] = module.exports[i];
}
}
};
},{"./lib/aabb2.js":3,"./lib/beizer.js":4,"./lib/circle.js":5,"./lib/collide.js":6,"./lib/collision/epa.js":7,"./lib/collision/gjk.js":8,"./lib/collision/manifold.js":9,"./lib/collision/resolve.js":10,"./lib/collision/response.js":11,"./lib/collision/sat.js":12,"./lib/draw.js":14,"./lib/intersection.js":15,"./lib/line2.js":16,"./lib/math.js":17,"./lib/matrix22.js":18,"./lib/matrix23.js":19,"./lib/nmtree.js":20,"./lib/noise.js":21,"./lib/numerical-integration/euler.js":22,"./lib/numerical-integration/rk4.js":23,"./lib/numerical-integration/verlet.js":24,"./lib/polygon.js":25,"./lib/rectangle.js":26,"./lib/segment2.js":27,"./lib/transitions.js":28,"./lib/triangle.js":29,"./lib/vec2.js":30,"./lib/xorshift.js":31}],3:[function(require,module,exports){
/**
* Stability: 1 (Only additions & fixes)
*
* BoundingBox2 is represented as a 5 coordinates array
* [left: Number, bottom: Number, right: Number, top: Number, normalized: Boolean]
*/
var min = Math.min,
max = Math.max,
TOPLEFT = 1,
TOPMIDDLE = 2,
TOPRIGHT = 3,
CENTERLEFT = 4,
CENTER = 5,
CENTERRIGHT = 6,
BOTTOMLEFT = 7,
BOTTOM = 8,
BOTTOMRIGHT = 9,
r = 0,
x = 0,
y = 0,
min_x = 0,
max_x = 0,
min_y = 0,
max_y = 0;
/**
* @param {Number} l
* @param {Number} b
* @param {Number} r
* @param {Number} t
* @return {AABB2}
*/
function create(l, b, r, t) {
if (l == undefined || Number.isNaN(l) || 'number' !== typeof l) {
throw new Error("l is undefined or null")
}
if (b == undefined || Number.isNaN(b) || 'number' !== typeof b) {
throw new Error("b is undefined or null")
}
if (r == undefined || Number.isNaN(r) || 'number' !== typeof r) {
throw new Error("r is undefined or null")
}
if (t == undefined || Number.isNaN(t) || 'number' !== typeof t) {
throw new Error("t is undefined or null")
}
var out = [l, b, r, t, false];
normalize(out, out);
return out;
}
/**
* @param {AABB2} aabb2
* @param {Number} x
* @param {Number} y
* @return {Array<AABB2>}
*/
function fromAABB2Division(aabb2, x, y) {
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
if (x == undefined || Number.isNaN(x) || 'number' !== typeof x) {
throw new Error("x is undefined or null")
}
if (y == undefined || Number.isNaN(y) || 'number' !== typeof y) {
throw new Error("y is undefined or null")
}
var out = [],
i,
j,
l = aabb2[0],
b = aabb2[1],
r = aabb2[2],
t = aabb2[3],
w = (r - l) / x,
h = (t - b) / y;
for (i = 0; i < x; ++i) {
for (j = 0; j < y; ++j) {
out.push([l + i * w, b + j * h, l + (i + 1) * w, b + (j + 1) * h]);
}
}
return out;
}
/**
* @param {Segment2} seg2
* @return {AABB2}
*/
function fromSegment2(seg2) {
var out = [seg2[0], seg2[1], seg2[2], seg2[3], false];
normalize(out, out);
return out;
}
/**
* @param {Circle} circle
* @return {AABB2}
*/
function fromCircle(circle) {
r = circle[1];
x = circle[0][0];
y = circle[0][1];
return create(
x - r,
y - r,
x + r,
y + r
);
}
/**
* @param {Rectangle} rect
* @return {AABB2}
*/
function fromRectangle(rect) {
if (!Array.isArray(rect) || rect[0][0] == undefined || Number.isNaN(rect[0][0]) || 'number' !== typeof rect[0][0] || rect[0][1] == undefined || Number.isNaN(rect[0][1]) || 'number' !== typeof rect[0][1] || rect[1][0] == undefined || Number.isNaN(rect[1][0]) || 'number' !== typeof rect[1][0] || rect[1][1] == undefined || Number.isNaN(rect[1][1]) || 'number' !== typeof rect[1][1]) {
throw new Error("invalid Rectangle rect")
}
var out = [rect[0][0], rect[0][1], rect[1][0], rect[1][1], false];
normalize(out, out);
return out;
}
/**
* @todo implement a more robust / fast algorithm http://stackoverflow.com/questions/2587751/an-algorithm-to-find-bounding-box-of-closed-bezier-curves (Timo answer)
*
* @reference http://jsfiddle.net/4VCVX/3/
*
* @param {Beizer} beizer
* @param {Number} npoints
* @return {AABB2}
*/
function fromBeizer(beizer, npoints) {
if (npoints == undefined || Number.isNaN(npoints) || 'number' !== typeof npoints) {
throw new Error("npoints is undefined or null")
}
npoints = npoints || 40;
var vec2_list = Beizer.get(beizer, npoints),
i,
l = Infinity,
b = Infinity,
r = -Infinity,
t = -Infinity,
v,
x,
y;
// loop min, max
for (i = 0; i < npoints; ++i) {
v = vec2_list[i];
x = v[0];
y = v[1];
if (x > r) {
r = x;
} else if (x < l) {
l = x;
}
if (y < b) {
b = y;
} else if (y > t) {
t = y;
}
}
return [l, b, r, t, true];
}
/**
* @return {AABB2}
*/
function zero() {
return [0, 0, 0, 0, true];
}
/**
* @param {AABB2} aabb2
* @return {AABB2}
*/
function clone(aabb2) {
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
return [aabb2[0], aabb2[1], aabb2[2], aabb2[3], aabb2[4]];
}
/**
* @param {AABB2} out
* @param {AABB2} aabb2
* @return {AABB2}
*/
function copy(out, aabb2) {
if (!Array.isArray(out) || out[0] == undefined || Number.isNaN(out[0]) || 'number' !== typeof out[0] || out[1] == undefined || Number.isNaN(out[1]) || 'number' !== typeof out[1] || out[2] == undefined || Number.isNaN(out[2]) || 'number' !== typeof out[2] || out[3] == undefined || Number.isNaN(out[3]) || 'number' !== typeof out[3]) {
throw new Error("invalid AABB2 out")
}
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
out[0] = aabb2[0];
out[1] = aabb2[1];
out[2] = aabb2[2];
out[3] = aabb2[3];
out[4] = aabb2[4];
return out;
}
/**
* @param {AABB2} out
* @param {AABB2} aabb2
* @param {Number} margin
* @return {AABB2}
*/
function expand(out, aabb2, margin) {
if (!Array.isArray(out) || out[0] == undefined || Number.isNaN(out[0]) || 'number' !== typeof out[0] || out[1] == undefined || Number.isNaN(out[1]) || 'number' !== typeof out[1] || out[2] == undefined || Number.isNaN(out[2]) || 'number' !== typeof out[2] || out[3] == undefined || Number.isNaN(out[3]) || 'number' !== typeof out[3]) {
throw new Error("invalid AABB2 out")
}
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
if (margin == undefined || Number.isNaN(margin) || 'number' !== typeof margin) {
throw new Error("margin is undefined or null")
}
out[0] = aabb2[0] - margin;
out[1] = aabb2[1] - margin;
out[2] = aabb2[2] + margin;
out[3] = aabb2[3] + margin;
return out;
}
/**
* @param {AABB2} out
* @param {AABB2} aabb2_1
* @param {AABB2} aabb2_2
* @return {AABB2}
*/
function merge(out, aabb2_1, aabb2_2) {
if (!Array.isArray(out) || out[0] == undefined || Number.isNaN(out[0]) || 'number' !== typeof out[0] || out[1] == undefined || Number.isNaN(out[1]) || 'number' !== typeof out[1] || out[2] == undefined || Number.isNaN(out[2]) || 'number' !== typeof out[2] || out[3] == undefined || Number.isNaN(out[3]) || 'number' !== typeof out[3]) {
throw new Error("invalid AABB2 out")
}
if (!Array.isArray(aabb2_1) || aabb2_1[0] == undefined || Number.isNaN(aabb2_1[0]) || 'number' !== typeof aabb2_1[0] || aabb2_1[1] == undefined || Number.isNaN(aabb2_1[1]) || 'number' !== typeof aabb2_1[1] || aabb2_1[2] == undefined || Number.isNaN(aabb2_1[2]) || 'number' !== typeof aabb2_1[2] || aabb2_1[3] == undefined || Number.isNaN(aabb2_1[3]) || 'number' !== typeof aabb2_1[3]) {
throw new Error("invalid AABB2 aabb2_1")
}
if (!Array.isArray(aabb2_2) || aabb2_2[0] == undefined || Number.isNaN(aabb2_2[0]) || 'number' !== typeof aabb2_2[0] || aabb2_2[1] == undefined || Number.isNaN(aabb2_2[1]) || 'number' !== typeof aabb2_2[1] || aabb2_2[2] == undefined || Number.isNaN(aabb2_2[2]) || 'number' !== typeof aabb2_2[2] || aabb2_2[3] == undefined || Number.isNaN(aabb2_2[3]) || 'number' !== typeof aabb2_2[3]) {
throw new Error("invalid AABB2 aabb2_2")
}
out[0] = min(aabb2_1[0], aabb2_2[0]);
out[1] = min(aabb2_1[1], aabb2_2[1]);
out[2] = max(aabb2_1[2], aabb2_2[2]);
out[3] = max(aabb2_1[3], aabb2_2[3]);
return out;
}
/**
* @param {AABB2} out
* @param {AABB2} aabb2_1
* @param {AABB2} aabb2_2
* @param {Vec2} vec2_offset
* @return {AABB2}
*/
function offsetMerge(out, aabb2_1, aabb2_2, vec2_offset) {
if (!Array.isArray(out) || out[0] == undefined || Number.isNaN(out[0]) || 'number' !== typeof out[0] || out[1] == undefined || Number.isNaN(out[1]) || 'number' !== typeof out[1] || out[2] == undefined || Number.isNaN(out[2]) || 'number' !== typeof out[2] || out[3] == undefined || Number.isNaN(out[3]) || 'number' !== typeof out[3]) {
throw new Error("invalid AABB2 out")
}
if (!Array.isArray(aabb2_1) || aabb2_1[0] == undefined || Number.isNaN(aabb2_1[0]) || 'number' !== typeof aabb2_1[0] || aabb2_1[1] == undefined || Number.isNaN(aabb2_1[1]) || 'number' !== typeof aabb2_1[1] || aabb2_1[2] == undefined || Number.isNaN(aabb2_1[2]) || 'number' !== typeof aabb2_1[2] || aabb2_1[3] == undefined || Number.isNaN(aabb2_1[3]) || 'number' !== typeof aabb2_1[3]) {
throw new Error("invalid AABB2 aabb2_1")
}
if (!Array.isArray(aabb2_2) || aabb2_2[0] == undefined || Number.isNaN(aabb2_2[0]) || 'number' !== typeof aabb2_2[0] || aabb2_2[1] == undefined || Number.isNaN(aabb2_2[1]) || 'number' !== typeof aabb2_2[1] || aabb2_2[2] == undefined || Number.isNaN(aabb2_2[2]) || 'number' !== typeof aabb2_2[2] || aabb2_2[3] == undefined || Number.isNaN(aabb2_2[3]) || 'number' !== typeof aabb2_2[3]) {
throw new Error("invalid AABB2 aabb2_2")
}
if (!Array.isArray(vec2_offset) || vec2_offset[0] == undefined || Number.isNaN(vec2_offset[0]) || 'number' !== typeof vec2_offset[0] || vec2_offset[1] == undefined || Number.isNaN(vec2_offset[1]) || 'number' !== typeof vec2_offset[1]) {
throw new Error("invalid Vec2 vec2_offset")
}
out[0] = min(aabb2_1[0], aabb2_2[0] + vec2_offset[0]);
out[1] = min(aabb2_1[1], aabb2_2[1] + vec2_offset[1]);
out[2] = max(aabb2_1[2], aabb2_2[2] + vec2_offset[0]);
out[3] = max(aabb2_1[3], aabb2_2[3] + vec2_offset[1]);
return out;
}
/**
* offset & scale merge
* @param {AABB2} out
* @param {AABB2} aabb2_1
* @param {AABB2} aabb2_2
* @param {Vec2} vec2_offset
* @param {Vec2} vec2_scale
* @return {AABB2}
*/
function osMerge(out, aabb2_1, aabb2_2, vec2_offset, vec2_scale) {
if (!Array.isArray(out) || out[0] == undefined || Number.isNaN(out[0]) || 'number' !== typeof out[0] || out[1] == undefined || Number.isNaN(out[1]) || 'number' !== typeof out[1] || out[2] == undefined || Number.isNaN(out[2]) || 'number' !== typeof out[2] || out[3] == undefined || Number.isNaN(out[3]) || 'number' !== typeof out[3]) {
throw new Error("invalid AABB2 out")
}
if (!Array.isArray(aabb2_1) || aabb2_1[0] == undefined || Number.isNaN(aabb2_1[0]) || 'number' !== typeof aabb2_1[0] || aabb2_1[1] == undefined || Number.isNaN(aabb2_1[1]) || 'number' !== typeof aabb2_1[1] || aabb2_1[2] == undefined || Number.isNaN(aabb2_1[2]) || 'number' !== typeof aabb2_1[2] || aabb2_1[3] == undefined || Number.isNaN(aabb2_1[3]) || 'number' !== typeof aabb2_1[3]) {
throw new Error("invalid AABB2 aabb2_1")
}
if (!Array.isArray(aabb2_2) || aabb2_2[0] == undefined || Number.isNaN(aabb2_2[0]) || 'number' !== typeof aabb2_2[0] || aabb2_2[1] == undefined || Number.isNaN(aabb2_2[1]) || 'number' !== typeof aabb2_2[1] || aabb2_2[2] == undefined || Number.isNaN(aabb2_2[2]) || 'number' !== typeof aabb2_2[2] || aabb2_2[3] == undefined || Number.isNaN(aabb2_2[3]) || 'number' !== typeof aabb2_2[3]) {
throw new Error("invalid AABB2 aabb2_2")
}
if (!Array.isArray(vec2_offset) || vec2_offset[0] == undefined || Number.isNaN(vec2_offset[0]) || 'number' !== typeof vec2_offset[0] || vec2_offset[1] == undefined || Number.isNaN(vec2_offset[1]) || 'number' !== typeof vec2_offset[1]) {
throw new Error("invalid Vec2 vec2_offset")
}
if (!Array.isArray(vec2_scale) || vec2_scale[0] == undefined || Number.isNaN(vec2_scale[0]) || 'number' !== typeof vec2_scale[0] || vec2_scale[1] == undefined || Number.isNaN(vec2_scale[1]) || 'number' !== typeof vec2_scale[1]) {
throw new Error("invalid Vec2 vec2_scale")
}
out[0] = min(aabb2_1[0], (aabb2_2[0] * vec2_scale[0]) + vec2_offset[0]);
out[1] = min(aabb2_1[1], (aabb2_2[1] * vec2_scale[1]) + vec2_offset[1]);
out[2] = max(aabb2_1[2], (aabb2_2[2] * vec2_scale[0]) + vec2_offset[0]);
out[3] = max(aabb2_1[3], (aabb2_2[3] * vec2_scale[1]) + vec2_offset[1]);
return out;
}
/**
* offset & scale merge
* @param {AABB2} aabb2
* @return {Number}
*/
function area(aabb2) {
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
return (aabb2[2] - aabb2[0]) * (aabb2[3] - aabb2[1]);
}
/**
* @param {AABB2} out
* @param {AABB2} aabb2
* @return {AABB2}
*/
function normalize(out, aabb2) {
if (!Array.isArray(out) || out[0] == undefined || Number.isNaN(out[0]) || 'number' !== typeof out[0] || out[1] == undefined || Number.isNaN(out[1]) || 'number' !== typeof out[1] || out[2] == undefined || Number.isNaN(out[2]) || 'number' !== typeof out[2] || out[3] == undefined || Number.isNaN(out[3]) || 'number' !== typeof out[3]) {
throw new Error("invalid AABB2 out")
}
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
min_x = aabb2[0] > aabb2[2] ? aabb2[2] : aabb2[0];
max_x = aabb2[0] > aabb2[2] ? aabb2[0] : aabb2[2];
min_y = aabb2[1] > aabb2[3] ? aabb2[3] : aabb2[1];
max_y = aabb2[1] > aabb2[3] ? aabb2[1] : aabb2[3];
out[0] = min_x;
out[1] = min_y;
out[2] = max_x;
out[3] = max_y;
out[4] = true;
}
/**
* @param {AABB2} out
* @param {AABB2} aabb2
* @param {Vec2} vec2
* @return {AABB2}
*/
function translate(out, aabb2, vec2) {
if (!Array.isArray(out) || out[0] == undefined || Number.isNaN(out[0]) || 'number' !== typeof out[0] || out[1] == undefined || Number.isNaN(out[1]) || 'number' !== typeof out[1] || out[2] == undefined || Number.isNaN(out[2]) || 'number' !== typeof out[2] || out[3] == undefined || Number.isNaN(out[3]) || 'number' !== typeof out[3]) {
throw new Error("invalid AABB2 out")
}
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
x = vec2[0];
y = vec2[1];
out[0] = aabb2[0] + x;
out[1] = aabb2[1] + y;
out[2] = aabb2[2] + x;
out[3] = aabb2[3] + y;
return out;
}
/**
* @param {Vec2} out_vec2
* @param {AABB2} aabb2
* @param {Vec2} vec2
* @return {Vec2}
*/
function clampVec(out_vec2, aabb2, vec2) {
if (!Array.isArray(out_vec2) || out_vec2[0] == undefined || Number.isNaN(out_vec2[0]) || 'number' !== typeof out_vec2[0] || out_vec2[1] == undefined || Number.isNaN(out_vec2[1]) || 'number' !== typeof out_vec2[1]) {
throw new Error("invalid Vec2 out_vec2")
}
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
out_vec2[0] = min(max(aabb2[0], vec2[0]), aabb2[2]);
out_vec2[1] = min(max(aabb2[1], vec2[1]), aabb2[3]);
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {AABB2} aabb2
*/
function center(out_vec2, aabb2) {
if (!Array.isArray(out_vec2) || out_vec2[0] == undefined || Number.isNaN(out_vec2[0]) || 'number' !== typeof out_vec2[0] || out_vec2[1] == undefined || Number.isNaN(out_vec2[1]) || 'number' !== typeof out_vec2[1]) {
throw new Error("invalid Vec2 out_vec2")
}
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
out_vec2[0] = (aabb2[0] + aabb2[1]) * 0.5;
out_vec2[1] = (aabb2[3] + aabb2[2]) * 0.5;
return out_vec2;
}
/**
* alignment values: AABB2.TOPLEFT, AABB2.TOPMIDDLE, AABB2.TOPRIGHT, AABB2.CENTERLEFT, AABB2.CENTER, AABB2.CENTERRIGHT, AABB2.BOTTOMLEFT, AABB2.BOTTOM, AABB2.BOTTOMRIGH
*
* @param {Vec2} out_vec2
* @param {AABB2} aabb2
* @param {Number} alignment
* @return {Vec2}
*/
function align(out_vec2, aabb2, alignment) {
if (!Array.isArray(out_vec2) || out_vec2[0] == undefined || Number.isNaN(out_vec2[0]) || 'number' !== typeof out_vec2[0] || out_vec2[1] == undefined || Number.isNaN(out_vec2[1]) || 'number' !== typeof out_vec2[1]) {
throw new Error("invalid Vec2 out_vec2")
}
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
if (alignment == undefined || Number.isNaN(alignment) || 'number' !== typeof alignment) {
throw new Error("alignment is undefined or null")
}
switch (alignment) {
case TOPLEFT:
// do nothing!
out_vec2[0] = aabb2[0];
out_vec2[1] = aabb2[1];
break;
case TOPMIDDLE:
out_vec2[0] = (aabb2[2] - aabb2[0]) * 0.5 + aabb2[0];
out_vec2[1] = aabb2[1];
break;
case TOPRIGHT:
out_vec2[0] = aabb2[2];
out_vec2[1] = aabb2[1];
break;
case CENTERLEFT:
out_vec2[0] = aabb2[0];
out_vec2[1] = (aabb2[3] - aabb2[1]) * 0.5 + aabb2[1];
break;
case CENTER:
out_vec2[0] = (aabb2[2] - aabb2[0]) * 0.5 + aabb2[0];
out_vec2[1] = (aabb2[3] - aabb2[1]) * 0.5 + aabb2[1];
break;
case CENTERRIGHT:
out_vec2[0] = aabb2[2];
out_vec2[1] = (aabb2[3] - aabb2[1]) * 0.5 + aabb2[1];
break;
case BOTTOMLEFT:
out_vec2[0] = aabb2[0];
out_vec2[1] = aabb2[3];
break;
case BOTTOM:
out_vec2[0] = (aabb2[2] - aabb2[0]) * 0.5 + aabb2[0];
out_vec2[1] = aabb2[3];
break;
case BOTTOMRIGHT:
out_vec2[0] = aabb2[2];
out_vec2[1] = aabb2[3];
break;
}
return out_vec2;
}
/**
* @param {AABB2} aabb2
* @param {Vec2} vec2
* @return {Boolean}
*/
function isVec2Inside(aabb2, vec2) {
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
return aabb2[0] < vec2[0] && aabb2[2] > vec2[0] && aabb2[1] < vec2[1] && aabb2[3] > vec2[1];
}
/**
* @param {AABB2} aabb2
* @param {AABB2} aabb2_2
* @return {Boolean}
*/
function isAABB2Inside(aabb2, aabb2_2) {
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
if (!Array.isArray(aabb2_2) || aabb2_2[0] == undefined || Number.isNaN(aabb2_2[0]) || 'number' !== typeof aabb2_2[0] || aabb2_2[1] == undefined || Number.isNaN(aabb2_2[1]) || 'number' !== typeof aabb2_2[1] || aabb2_2[2] == undefined || Number.isNaN(aabb2_2[2]) || 'number' !== typeof aabb2_2[2] || aabb2_2[3] == undefined || Number.isNaN(aabb2_2[3]) || 'number' !== typeof aabb2_2[3]) {
throw new Error("invalid AABB2 aabb2_2")
}
return aabb2[0] <= aabb2_2[0] &&
aabb2[1] <= aabb2_2[1] &&
aabb2_2[2] <= aabb2[2] &&
aabb2_2[3] <= aabb2[3];
}
/**
* @param {AABB2} aabb2
* @return {Number}
*/
function perimeter(aabb2) {
if (!Array.isArray(aabb2) || aabb2[0] == undefined || Number.isNaN(aabb2[0]) || 'number' !== typeof aabb2[0] || aabb2[1] == undefined || Number.isNaN(aabb2[1]) || 'number' !== typeof aabb2[1] || aabb2[2] == undefined || Number.isNaN(aabb2[2]) || 'number' !== typeof aabb2[2] || aabb2[3] == undefined || Number.isNaN(aabb2[3]) || 'number' !== typeof aabb2[3]) {
throw new Error("invalid AABB2 aabb2")
}
return (aabb2[2] - aabb2[0]) * 2 + (aabb2[3] - aabb2[1]) * 2;
}
/**
* @class AABB2
*/
var AABB2 = {
// defines
TOPLEFT: TOPLEFT,
TOPMIDDLE: TOPMIDDLE,
TOPRIGHT: TOPRIGHT,
CENTERLEFT: CENTERLEFT,
CENTER: CENTER,
CENTERRIGHT: CENTERRIGHT,
BOTTOMLEFT: BOTTOMLEFT,
BOTTOM: BOTTOM,
BOTTOMRIGHT: BOTTOMRIGHT,
create: create,
fromAABB2Division: fromAABB2Division,
fromSegment2: fromSegment2,
fromCircle: fromCircle,
fromRectangle: fromRectangle,
zero: zero,
clone: clone,
copy: copy,
expand: expand,
merge: merge,
offsetMerge: offsetMerge,
osMerge: osMerge,
area: area,
normalize: normalize,
translate: translate,
clampVec: clampVec,
center: center,
align: align,
isVec2Inside: isVec2Inside,
isAABB2Inside: isAABB2Inside,
perimeter: perimeter,
// alias
contains: isAABB2Inside
};
module.exports = AABB2;
},{}],4:[function(require,module,exports){
/**
* Stability: 1 (Only additions & fixes)
*
* @reference http://pomax.github.io/bezierinfo/
* @reference https://github.com/jackcviers/Degrafa/blob/master/Degrafa/com/degrafa/geometry/utilities/BezierUtils.as
* @reference http://cagd.cs.byu.edu/~557/text/ch7.pdf
* @reference http://algorithmist.wordpress.com/2009/02/02/degrafa-closest-point-on-quad-bezier/
* @reference http://algorithmist.wordpress.com/2009/01/26/degrafa-bezierutils-class/
*/
var sqrt = Math.sqrt,
cl0 = 0,
cl1 = 0,
cl2 = 0,
cl3 = 0,
t1 = 0,
t2 = 0,
t3 = 0;
/**
* cp0 - start point
* cp1 - start control point
* cp2 - end control point
* cp3 - end point
*
* @param {Number} cp0x
* @param {Number} cp0y
* @param {Number} cp1x
* @param {Number} cp1y
* @param {Number} cp2x
* @param {Number} cp2y
* @param {Number} cp3x
* @param {Number} cp3y
* @return {Beizer}
*/
function cubic(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cp3x, cp3y) {
if (cp0x == undefined || Number.isNaN(cp0x) || 'number' !== typeof cp0x) {
throw new Error("cp0x is undefined or null")
}
if (cp0y == undefined || Number.isNaN(cp0y) || 'number' !== typeof cp0y) {
throw new Error("cp0y is undefined or null")
}
if (cp1x == undefined || Number.isNaN(cp1x) || 'number' !== typeof cp1x) {
throw new Error("cp1x is undefined or null")
}
if (cp1y == undefined || Number.isNaN(cp1y) || 'number' !== typeof cp1y) {
throw new Error("cp1y is undefined or null")
}
if (cp2x == undefined || Number.isNaN(cp2x) || 'number' !== typeof cp2x) {
throw new Error("cp2x is undefined or null")
}
if (cp2y == undefined || Number.isNaN(cp2y) || 'number' !== typeof cp2y) {
throw new Error("cp2y is undefined or null")
}
if (cp3x == undefined || Number.isNaN(cp3x) || 'number' !== typeof cp3x) {
throw new Error("cp3x is undefined or null")
}
if (cp3y == undefined || Number.isNaN(cp3y) || 'number' !== typeof cp3y) {
throw new Error("cp3y is undefined or null")
}
return [[cp0x, cp0y], [cp1x, cp1y], [cp2x, cp2y], [cp3x, cp3y]];
}
/**
* For implementation see Figure 21.2
* @reference http://pomax.github.io/bezierinfo/
* @todo DO IT!
*
* @param {Number} cp0x
* @param {Number} cp0y
* @param {Number} cp1x
* @param {Number} cp1y
* @param {Number} cp2x
* @param {Number} cp2y
* @return {Beizer}
*/
function from3Points(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y) {
if (cp0x == undefined || Number.isNaN(cp0x) || 'number' !== typeof cp0x) {
throw new Error("cp0x is undefined or null")
}
if (cp0y == undefined || Number.isNaN(cp0y) || 'number' !== typeof cp0y) {
throw new Error("cp0y is undefined or null")
}
if (cp1x == undefined || Number.isNaN(cp1x) || 'number' !== typeof cp1x) {
throw new Error("cp1x is undefined or null")
}
if (cp1y == undefined || Number.isNaN(cp1y) || 'number' !== typeof cp1y) {
throw new Error("cp1y is undefined or null")
}
if (cp2x == undefined || Number.isNaN(cp2x) || 'number' !== typeof cp2x) {
throw new Error("cp2x is undefined or null")
}
if (cp2y == undefined || Number.isNaN(cp2y) || 'number' !== typeof cp2y) {
throw new Error("cp2y is undefined or null")
}
}
/**
* @param {Number} cp0x
* @param {Number} cp0y
* @param {Number} cp1x
* @param {Number} cp1y
* @param {Number} cp2x
* @param {Number} cp2y
* @return {Beizer}
*/
function quadric(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y) {
if (cp0x == undefined || Number.isNaN(cp0x) || 'number' !== typeof cp0x) {
throw new Error("cp0x is undefined or null")
}
if (cp0y == undefined || Number.isNaN(cp0y) || 'number' !== typeof cp0y) {
throw new Error("cp0y is undefined or null")
}
if (cp1x == undefined || Number.isNaN(cp1x) || 'number' !== typeof cp1x) {
throw new Error("cp1x is undefined or null")
}
if (cp1y == undefined || Number.isNaN(cp1y) || 'number' !== typeof cp1y) {
throw new Error("cp1y is undefined or null")
}
if (cp2x == undefined || Number.isNaN(cp2x) || 'number' !== typeof cp2x) {
throw new Error("cp2x is undefined or null")
}
if (cp2y == undefined || Number.isNaN(cp2y) || 'number' !== typeof cp2y) {
throw new Error("cp2y is undefined or null")
}
return [[cp0x, cp0y], [cp1x, cp1y], [cp2x, cp2y]];
}
/**
* For implementation see Figure 21.1
* @reference http://pomax.github.io/bezierinfo/
* @param {Number} cp0x
* @param {Number} cp0y
* @param {Number} cp1x
* @param {Number} cp1y
* @param {Number} cp2x
* @param {Number} cp2y
*/
function quadricFrom3Points(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y) {
if (cp0x == undefined || Number.isNaN(cp0x) || 'number' !== typeof cp0x) {
throw new Error("cp0x is undefined or null")
}
if (cp0y == undefined || Number.isNaN(cp0y) || 'number' !== typeof cp0y) {
throw new Error("cp0y is undefined or null")
}
if (cp1x == undefined || Number.isNaN(cp1x) || 'number' !== typeof cp1x) {
throw new Error("cp1x is undefined or null")
}
if (cp1y == undefined || Number.isNaN(cp1y) || 'number' !== typeof cp1y) {
throw new Error("cp1y is undefined or null")
}
if (cp2x == undefined || Number.isNaN(cp2x) || 'number' !== typeof cp2x) {
throw new Error("cp2x is undefined or null")
}
if (cp2y == undefined || Number.isNaN(cp2y) || 'number' !== typeof cp2y) {
throw new Error("cp2y is undefined or null")
}
}
/**
* Solves the curve (quadric or cubic) for any given parameter t.
* @source https://github.com/hyperandroid/CAAT/blob/master/src/Math/Bezier.js
* @param {Vec2} out_vec2
* @param {Beizer} curve
* @param {Number} t [0-1]
* @return {Vec2}
*/
function solve(out_vec2, curve, t) {
if (!Array.isArray(out_vec2) || out_vec2[0] == undefined || Number.isNaN(out_vec2[0]) || 'number' !== typeof out_vec2[0] || out_vec2[1] == undefined || Number.isNaN(out_vec2[1]) || 'number' !== typeof out_vec2[1]) {
throw new Error("invalid Vec2 out_vec2")
}
if (t == undefined || Number.isNaN(t) || 'number' !== typeof t) {
throw new Error("t is undefined or null")
}
if (curve.length === 4) {
//cubic
t2 = t * t;
t3 = t * t2;
cl0 = curve[0];
cl1 = curve[1];
cl2 = curve[2];
cl3 = curve[3];
out_vec2[0] = (cl0[0] + t * (-cl0[0] * 3 + t * (3 * cl0[0] - cl0[0] * t))) +
t * (3 * cl1[0] + t * (-6 * cl1[0] + cl1[0] * 3 * t)) +
t2 * (cl2[0] * 3 - cl2[0] * 3 * t) +
cl3[0] * t3;
out_vec2[1] = (cl0[1] + t * (-cl0[1] * 3 + t * (3 * cl0[1] - cl0[1] * t))) +
t * (3 * cl1[1] + t * (-6 * cl1[1] + cl1[1] * 3 * t)) +
t2 * (cl2[1] * 3 - cl2[1] * 3 * t) +
cl3[1] * t3;
} else {
// quadric
cl0 = curve[0];
cl1 = curve[1];
cl2 = curve[2];
t1 = 1 - t;
out_vec2[0] = t1 * t1 * cl0[0] + 2 * t1 * t * cl1[0] + t * t * cl2[0];
out_vec2[1] = t1 * t1 * cl0[1] + 2 * t1 * t * cl1[1] + t * t * cl2[1];
}
return out_vec2;
}
/**
* Solve the curve npoints times and return the solution array.
*
* @see Polygon.fromBeizer
*
* @param {Beizer} curve
* @param {Number} npoints
* @return {Vec2[]}
*/
function getPoints(curve, npoints) {
if (npoints == undefined || Number.isNaN(npoints) || 'number' !== typeof npoints) {
throw new Error("npoints is undefined or null")
}
var inv_npoints = 1 / npoints,
i,
output = [],
vec2;
for (i = 0; i <= 1; i += inv_npoints) {
vec2 = [0, 0];
output.push(solve(vec2, curve, i));
}
return output;
}
/**
* Calculate the curve length by incrementally solving the curve every substep=CAAT.Curve.k. This value defaults
* to .05 so at least 20 iterations will be performed.
* @todo some kind of cache maybe it's needed!
* @param {Beizer} curve
* @param {Number} step
* @return {Number} the approximate curve length.
*/
function length(curve, step) {
if (step == undefined || Number.isNaN(step) || 'number' !== typeof step) {
throw new Error("step is undefined or null")
}
step = step || 0.05;
var x1,
y1,
llength = 0,
pt = [0, 0],
t;
x1 = curve[0][0];
y1 = curve[0][1];
for (t = step; t <= 1 + step; t += step) {
solve(pt, curve, t);
llength += sqrt((pt[0] - x1) * (pt[0] - x1) + (pt[1] - y1) * (pt[1] - y1));
x1 = pt[0];
y1 = pt[1];
}
return llength;
}
/**
* credits - CAAT
*
* @class Beizer
*/
var Beizer = {
cubic: cubic,
quadric: quadric,
solve: solve,
length: length,
getPoints: getPoints
};
module.exports = Beizer;
},{}],5:[function(require,module,exports){
/**
* Stability: 1 (Only additions & fixes)
*
* Circle is represented as a two coordinates array
* [c:Vec2, r:Number]
*/
var Vec2 = require("./vec2.js"),
vec2_sub = Vec2.sub,
vec2_distance = Vec2.distance,
vec2_distance_sq = Vec2.distanceSq,
vec2_midpoint = Vec2.midPoint,
Rectangle = require("./rectangle.js"),
rectangle_center = Rectangle.center,
Triangle = require("./triangle.js"),
triangle_circumcenter = Triangle.circumcenter,
triangle_center = Triangle.center,
triangle_abmidpoint = Triangle.abMidPoint,
triangle_bcmidpoint = Triangle.bcMidPoint,
triangle_camidpoint = Triangle.caMidPoint,
max = Math.max,
TWOPI = Math.TWOPI,
QUATER_PI = Math.PI * 0.25,
PI = Math.PI,
sqrt = Math.sqrt,
aux_vec2 = [0, 0],
aux_num,
aux_num2;
/**
* @param {Number} x
* @param {Number} y
* @param {Number} radius
* @return {Circle}
*/
function create(x, y, radius) {
if (x == undefined || Number.isNaN(x) || 'number' !== typeof x) {
throw new Error("x is undefined or null")
}
if (y == undefined || Number.isNaN(y) || 'number' !== typeof y) {
throw new Error("y is undefined or null")
}
if (radius == undefined || Number.isNaN(radius) || 'number' !== typeof radius) {
throw new Error("radius is undefined or null")
}
return [[x, y], radius];
}
/**
* @param {Vec2} vec2
* @param {Number} radius
* @return {Circle}
*/
function fromVec2(vec2, radius) {
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
if (radius == undefined || Number.isNaN(radius) || 'number' !== typeof radius) {
throw new Error("radius is undefined or null")
}
return [[vec2[0], vec2[1]], radius];
}
/**
* Create a Circle with seg2 as diameter
*
* @param {Segment2} seg2
* @return {Circle}
*/
function fromSegment2(seg2) {
var out = [[0, 0], 0];
out[0][0] = (seg2[0] + seg2[2]) * 0.5;
out[0][1] = (seg2[1] + seg2[3]) * 0.5;
//subtract
aux_num = out[0][0] - seg2[0];
aux_num2 = out[0][1] - seg2[1];
//sqrLength
out[1] = sqrt(aux_num * aux_num + aux_num2 * aux_num2);
return out;
}
/**
* @param {Rectangle} rect
* @param {Boolean=} inside
* @return {Circle}
*/
function fromRectangle(rect, inside) {
if (!Array.isArray(rect) || rect[0][0] == undefined || Number.isNaN(rect[0][0]) || 'number' !== typeof rect[0][0] || rect[0][1] == undefined || Number.isNaN(rect[0][1]) || 'number' !== typeof rect[0][1] || rect[1][0] == undefined || Number.isNaN(rect[1][0]) || 'number' !== typeof rect[1][0] || rect[1][1] == undefined || Number.isNaN(rect[1][1]) || 'number' !== typeof rect[1][1]) {
throw new Error("invalid Rectangle rect")
}
if (inside !== undefined) {
if ('boolean' !== typeof inside) {
throw new Error("inside is not a boolean")
}
}
var out = [[0, 0], 0];
rectangle_center(out[0], rect);
if (inside) {
aux_vec2[0] = rect[0][0] + (rect[1][0] - rect[0][0]) * 0.5;
aux_vec2[1] = rect[0][1];
out[1] = vec2_distance(out[0], aux_vec2);
} else {
out[1] = vec2_distance(out[0], rect[0]);
}
return out;
}
/**
* @todo review inside cases
* @param {Triangle} tri
* @param {Boolean=} inside
* @param {Boolean=} circumcenter
* @return {Circle}
*/
function fromTriangle(tri, inside, circumcenter) {
if (!Array.isArray(tri) || tri[0][0] == undefined || Number.isNaN(tri[0][0]) || 'number' !== typeof tri[0][0] || tri[0][1] == undefined || Number.isNaN(tri[0][1]) || 'number' !== typeof tri[0][1] || tri[1][0] == undefined || Number.isNaN(tri[1][0]) || 'number' !== typeof tri[1][0] || tri[1][1] == undefined || Number.isNaN(tri[1][1]) || 'number' !== typeof tri[1][1] || tri[2][0] == undefined || Number.isNaN(tri[2][0]) || 'number' !== typeof tri[2][0] || tri[2][1] == undefined || Number.isNaN(tri[2][1]) || 'number' !== typeof tri[2][1]) {
throw new Error("invalid Traingle tri")
}
if (inside !== undefined) {
if ('boolean' !== typeof inside) {
throw new Error("inside is not a boolean")
}
}
if (circumcenter !== undefined) {
if ('boolean' !== typeof circumcenter) {
throw new Error("circumcenter is not a boolean")
}
}
var out = [[0, 0], 0];
if (circumcenter && !inside) {
triangle_circumcenter(out[0], tri);
// use distance^2 for comparison
out[1] = vec2_distance_sq(out[0], tri[0]);
aux_num = vec2_distance_sq(out[0], tri[1]);
if (aux_num > out[1]) {
out[1] = aux_num;
}
out[1] = vec2_distance_sq(out[0], tri[2]);
if (aux_num > out[1]) {
out[1] = aux_num;
}
// and now return the good one :)
out[1] = sqrt(out[1]);
return out;
}
triangle_center(out[0], tri);
// use distance^2 for comparison
triangle_abmidpoint(aux_vec2, tri);
out[1] = vec2_distance_sq(out[0], aux_vec2);
triangle_bcmidpoint(aux_vec2, tri);
aux_num = vec2_distance_sq(out[0], aux_vec2);
if (aux_num < out[1]) {
out[1] = aux_num;
}
triangle_camidpoint(aux_vec2, tri);
aux_num = vec2_distance_sq(out[0], aux_vec2);
if (aux_num < out[1]) {
out[1] = aux_num;
}
// and now return the good one :)
out[1] = sqrt(out[1]);
return out;
}
/**
* @param {Circle} circle
* @return {Circle}
*/
function clone(circle) {
return [[circle[0][0], circle[0][1]], circle[1]];
}
/**
* @param {Circle} out
* @param {Circle} circle
* @return {Circle}
*/
function copy(out, circle) {
out[0][0] = circle[0][0];
out[0][1] = circle[0][1];
out[1] = circle[1];
return out;
}
/**
* @param {Circle} out
* @param {Circle} circle
* @param {Vec2} vec2
* @return {Circle}
*/
function translate(out, circle, vec2) {
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
out[0][0] = circle[0][0] + vec2[0];
out[0][1] = circle[0][1] + vec2[1];
out[1] = circle[1];
return out;
}
/**
* @param {Circle} out
* @param {Circle} circle
* @param {Vec2} vec2
* @return {Circle}
*/
function moveTo(out, circle, vec2) {
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
out[0][0] = vec2[0];
out[0][1] = vec2[1];
out[1] = circle[1];
return out;
}
/**
* @param {Circle} circle
* @param {Circle} circle_2
* @return {Number}
*/
function distance(circle, circle_2) {
return max(0, vec2_distance(circle[0], circle_2[0]) - circle[1] - circle_2[1]);
}
/**
* @param {Circle} circle
* @return {Number}
*/
function length(circle) {
return TWOPI * circle[1];
}
/**
* @param {Circle} circle
* @return {Number}
*/
function area(circle) {
return PI * circle[1] * circle[1];
}
/**
* @param {Circle} circle
* @param {Vec2} vec2
* @return {Boolean}
*/
function isVec2Inside(circle, vec2) {
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
return vec2_distance(circle[0], vec2) < circle[1];
}
/**
* @param {Vec2} out_vec2
* @param {Circle} circle
* @param {Vec2} vec2
* @return {Vec2}
*/
function closestPoint(out_vec2, circle, vec2) {
if (!Array.isArray(out_vec2) || out_vec2[0] == undefined || Number.isNaN(out_vec2[0]) || 'number' !== typeof out_vec2[0] || out_vec2[1] == undefined || Number.isNaN(out_vec2[1]) || 'number' !== typeof out_vec2[1]) {
throw new Error("invalid Vec2 out_vec2")
}
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
//const Vector& P, const Vector& Centre, float radius, bool* inside)
vec2_sub(out_vec2, vec2 - cirlce[0]);
var dist2 = vec2_length(out_vec2);
// is inside? (dist2 <= radius * radius);
//if(dist2 > EPS) Delta /= sqrt(dist2);
vec2_scale(out_vec2, out_vec2, scale);
vec2_add(out_vec2, cirlce[0], scale);
return out_vec2;
}
/**
* @param {Circle} circle
* @param {Number} mass
*/
function momentOfInertia(circle, mass) {
if (mass == undefined || Number.isNaN(mass) || 'number' !== typeof mass) {
throw new Error("mass is undefined or null")
}
var r = circle[1];
return mass * r * r * 0.5;
}
/**
* @class Circle
*/
var Circle = {
create: create,
fromVec2: fromVec2,
fromSegment2: fromSegment2,
fromRectangle: fromRectangle,
fromTriangle: fromTriangle,
clone: clone,
copy: copy,
translate: translate,
moveTo: moveTo,
distance: distance,
length: length,
area: area,
isVec2Inside: isVec2Inside,
//physics
momentOfInertia: momentOfInertia,
// alias
perimeter: length,
move: moveTo
};
module.exports = Circle;
},{"./rectangle.js":26,"./triangle.js":29,"./vec2.js":30}],6:[function(require,module,exports){
/**
* Stability: 0 (Anything could happen)
*
* This need revision.
* **inside:Boolean** param must be added to all functions
* *Note** this not return the contact points, use intersections for that.
*
* @source http://members.gamedev.net/oliii/satpost/SpherePolygonCollision.cpp
*/
var Vec2 = require("./vec2.js"),
vec2_distance = Vec2.distance,
vec2_distance_sq = Vec2.distanceSq,
vec2_midpoint = Vec2.midPoint,
vec2_$near = Vec2.$near,
vec2_sub = Vec2.sub,
vec2_dot = Vec2.dot,
Segment2 = require("./segment2.js"),
Segment2_$closestPoint = Segment2.$closestPoint,
aux_vec2 = [0, 0],
ca = [0, 0],
ba = [0, 0],
pa = [0, 0],
EPS = Math.EPS = 0.001;
/**
* @param {Number} num
* @param {Number} num2
* @param {Number} dist
*/
function _near(num, num2, dist) {
if (num == undefined || Number.isNaN(num) || 'number' !== typeof num) {
throw new Error("num is undefined or null")
}
if (num2 == undefined || Number.isNaN(num2) || 'number' !== typeof num2) {
throw new Error("num2 is undefined or null")
}
if (dist == undefined || Number.isNaN(dist) || 'number' !== typeof dist) {
throw new Error("dist is undefined or null")
}
return num > num2 - dist && num < num2 + dist;
}
/**
* @param {Number} x1
* @param {Number} y1
* @param {Number} x2
* @param {Number} y2
* @param {Number} x3
* @param {Number} y3
*/
function _rectangle_vec2(x1, y1, x2, y2, x3, y3) {
if (x1 == undefined || Number.isNaN(x1) || 'number' !== typeof x1) {
throw new Error("x1 is undefined or null")
}
if (y1 == undefined || Number.isNaN(y1) || 'number' !== typeof y1) {
throw new Error("y1 is undefined or null")
}
if (x2 == undefined || Number.isNaN(x2) || 'number' !== typeof x2) {
throw new Error("x2 is undefined or null")
}
if (y2 == undefined || Number.isNaN(y2) || 'number' !== typeof y2) {
throw new Error("y2 is undefined or null")
}
if (x3 == undefined || Number.isNaN(x3) || 'number' !== typeof x3) {
throw new Error("x3 is undefined or null")
}
if (y3 == undefined || Number.isNaN(y3) || 'number' !== typeof y3) {
throw new Error("y3 is undefined or null")
}
return (x1 > x3 || x2 < x3 || y1 > y3 || y2 < y3) ? false : true;
}
/**
* @param {AABB2} bb2
* @param {Vec2} vec2
* @return {Boolean}
*/
function bb2_vec2(bb2, vec2) {
if (!Array.isArray(bb2) || bb2[0] == undefined || Number.isNaN(bb2[0]) || 'number' !== typeof bb2[0] || bb2[1] == undefined || Number.isNaN(bb2[1]) || 'number' !== typeof bb2[1] || bb2[2] == undefined || Number.isNaN(bb2[2]) || 'number' !== typeof bb2[2] || bb2[3] == undefined || Number.isNaN(bb2[3]) || 'number' !== typeof bb2[3]) {
throw new Error("invalid AABB2 bb2")
}
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
return _rectangle_vec2(bb2[0], bb2[1], bb2[2], bb2[3], vec2[0], vec2[1]);
}
/**
* @param {Vec2} vec2
* @param {AABB2} bb2
* @return {Boolean}
*/
function vec2_bb2(vec2, bb2) {
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
if (!Array.isArray(bb2) || bb2[0] == undefined || Number.isNaN(bb2[0]) || 'number' !== typeof bb2[0] || bb2[1] == undefined || Number.isNaN(bb2[1]) || 'number' !== typeof bb2[1] || bb2[2] == undefined || Number.isNaN(bb2[2]) || 'number' !== typeof bb2[2] || bb2[3] == undefined || Number.isNaN(bb2[3]) || 'number' !== typeof bb2[3]) {
throw new Error("invalid AABB2 bb2")
}
return _rectangle_vec2(bb2[0], bb2[1], bb2[2], bb2[3], vec2[0], vec2[1]);
}
/**
* @param {Rectangle} rect
* @param {Vec2} vec2
* @return {Boolean}
*/
function rectangle_vec2(rect, vec2) {
if (!Array.isArray(rect) || rect[0][0] == undefined || Number.isNaN(rect[0][0]) || 'number' !== typeof rect[0][0] || rect[0][1] == undefined || Number.isNaN(rect[0][1]) || 'number' !== typeof rect[0][1] || rect[1][0] == undefined || Number.isNaN(rect[1][0]) || 'number' !== typeof rect[1][0] || rect[1][1] == undefined || Number.isNaN(rect[1][1]) || 'number' !== typeof rect[1][1]) {
throw new Error("invalid Rectangle rect")
}
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new Error("invalid Vec2 vec2")
}
var tl = rect[0], br = rect[1];
return _rectangle_vec2(tl[0], tl[1], br[0], br[1], vec2[0], vec2[1]);
}
/**
* @param {Vec2} vec2
* @param {Rectangle} rect
* @return {Boolean}
*/
function vec2_rectangle(vec2, rect) {
if (!Array.isArray(vec2) || vec2[0] == undefined || Number.isNaN(vec2[0]) || 'number' !== typeof vec2[0] || vec2[1] == undefined || Number.isNaN(vec2[1]) || 'number' !== typeof vec2[1]) {
throw new