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
268 lines (235 loc) • 5.49 kB
JavaScript
/**
* Stability: 2 (fixes / performance improvements)
*
* Triangle is represented as a three coordinates array
* [A:Vec2, B:Vec2, C:Vec2]
*/
var Vec2 = require("./vec2.js"),
vec2_midpoint = Vec2.midPoint,
vec2_distance = Vec2.distance,
vec2_pow = Vec2.pow,
vec2_dot = Vec2.dot,
DIV3 = 1 / 3,
ah = [0, 0],
bh = [0, 0],
ch = [0, 0],
dab = [0, 0],
dbc = [0, 0],
dca = [0, 0],
det = 0,
a = 0,
b = 0,
c = 0;
/**
* A(x1, y1), B(x2, y2), C(x3, y3)
* @param {Number} x1
* @param {Number} y1
* @param {Number} x2
* @param {Number} y2
* @param {Number} x3
* @param {Number} y3
* @return {Triangle}
*/
function create(x1, y1, x2, y2, x3, y3) {
var out = [[x1, y1], [x2, y2], [x3, y3], false];
//normalize(out, out);
return out;
}
/**
* @return {Triangle}
*/
function zero() {
return [[0, 0], [0, 0], [0, 0], true];
}
/**
* @param {Triangle} tri
* @return {Triangle}
*/
function clone(tri) {
return [[tri[0][0], tri[0][1]], [tri[1][0], tri[1][1]], [tri[2][0], tri[2][1]], tri[3]];
}
/**
* @param {Triangle} out_tri
* @param {Triangle} tri
* @return {Triangle}
*/
function copy(out_tri, tri) {
out_tri[0][0] = tri[0][0];
out_tri[0][1] = tri[0][1];
out_tri[1][0] = tri[1][0];
out_tri[1][1] = tri[1][1];
out_tri[2][0] = tri[2][0];
out_tri[2][1] = tri[2][1];
out_tri[3] = tri[3];
return out_tri;
}
/**
* @param {Vec2} out_vec2
* @param {Triangle} tri
* @return {Vec2}
*/
function abMidPoint(out_vec2, tri) {
return vec2_midpoint(out_vec2, tri[0], tri[1]);
}
/**
* @param {Vec2} out_vec2
* @param {Triangle} tri
* @return {Vec2}
*/
function bcMidPoint(out_vec2, tri) {
return vec2_midpoint(out_vec2, tri[1], tri[2]);
}
/**
* @param {Vec2} out_vec2
* @param {Triangle} tri
* @return {Vec2}
*/
function caMidPoint(out_vec2, tri) {
return vec2_midpoint(out_vec2, tri[2], tri[0]);
}
/**
* @param {Triangle} out
* @param {Triangle} tri
* @return {Triangle}
*/
function midTriangle(out, tri) {
abMidPoint(out[0], tri);
bcMidPoint(out[1], tri);
caMidPoint(out[2], tri);
return out;
}
/**
* @param {Triangle} tri
* @return {Number}
*/
function perimeter(tri) {
return vec2_distance(tri[0], tri[1]) +
vec2_distance(tri[1], tri[2]) +
vec2_distance(tri[2], tri[0]);
}
/**
* @param {Vec2} out_vec2
* @param {Triangle} tri
* @return {Vec2}
*/
function centroid(out_vec2, tri) {
out_vec2[0] = (tri[0][0] + tri[1][0] + tri[2][0]) * DIV3;
out_vec2[1] = (tri[0][1] + tri[1][1] + tri[2][1]) * DIV3;
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Triangle} tri
* @return {Vec2}
*/
function incenter(out_vec2, tri) {
a = Vec2.distance(tri[1], tri[2]);
b = Vec2.distance(tri[2], tri[0]);
c = Vec2.distance(tri[0], tri[1]);
out_vec2[0] = (a * tri[0][0] + b * tri[1][0] + c * tri[2][0]) * DIV3;
out_vec2[1] = (a * tri[0][1] + b * tri[1][1] + c * tri[2][1]) * DIV3;
return out_vec2;
}
/**
* @param {Vec2} out_vec2
* @param {Triangle} tri
* @return {Vec2}
*/
function circumcenter(out_vec2, tri) {
var bx = tri[1][0] - tri[0][0],
by = tri[1][1] - tri[0][1],
bl = bx * bx + by * by,
cx = tri[2][0] - tri[0][0],
cy = tri[2][1] - tri[0][1],
cl = cx * cx + cy * cy,
d = 2 * (bx * cy - by * cx),
x = cy * bl - by * cl,
y = bx * cl - cx * bl;
out_vec2[0] = x / d + tri[0][0];
out_vec2[1] = y / d + tri[0][1];
return out_vec2;
}
/**
* @param {Triangle} tri
* @return {Number}
*/
function area(tri) {
dab = Vec2.min(dbc, tri[1], tri[0]);
dbc = Vec2.min(dbc, tri[2], tri[0]);
return (dbc[1] * dab[0] - dbc[0] * dab[1]) * 0.5;
}
/**
* @param {Triangle} out
* @param {Triangle} tri
* @param {Vec2} vec2
* @return {Triangle}
*/
function translate(out, tri, vec2) {
out[0][0] = tri[0][0] + vec2[0];
out[0][1] = tri[0][1] + vec2[1];
out[1][0] = tri[1][0] + vec2[0];
out[1][1] = tri[1][1] + vec2[1];
out[2][0] = tri[2][0] + vec2[0];
out[2][1] = tri[2][1] + vec2[1];
return out;
}
var ac = [0, 0],
ab = [0, 0],
av = [0, 0],
dot00,
dot01,
dot02,
dot11,
dot12,
invDenom,
u,
v;
/**
* @param {Triangle} tri
* @param {Vec2} vec2
* @return {Boolean}
*/
function isVec2Inside(tri, vec2) {
// Compute vectors
// ac = C - A
Vec2.sub(ac, tri[2], tri[0]);
// ab = B - A
Vec2.sub(ab, tri[1], tri[0]);
// av = P - A
Vec2.sub(av, vec2, tri[0]);
// Compute dot products
dot00 = vec2_dot(ac, ac)
dot01 = vec2_dot(ac, ab)
dot02 = vec2_dot(ac, av)
dot11 = vec2_dot(ab, ab)
dot12 = vec2_dot(ab, av)
// Compute barycentric coordinates
invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
u = (dot11 * dot02 - dot01 * dot12) * invDenom
v = (dot00 * dot12 - dot01 * dot02) * invDenom
// Check if point is in triangle
return (u >= 0) && (v >= 0) && (u + v < 1);
}
/**
* @class Triangle
*/
var Triangle = {
create: create,
zero: zero,
clone: clone,
copy: copy,
abMidPoint: abMidPoint,
bcMidPoint: bcMidPoint,
caMidPoint: caMidPoint,
midTriangle: midTriangle,
perimeter: perimeter,
centroid: centroid,
incenter: incenter,
circumcenter: circumcenter,
area: area,
translate: translate,
isVec2Inside: isVec2Inside,
// alias
center: centroid,
};
module.exports = Triangle;