247 lines
5.0 KiB
JavaScript
247 lines
5.0 KiB
JavaScript
'use strict';
|
|
|
|
var Point = require('./types/Point');
|
|
var attrRegexps = {};
|
|
|
|
function getAttrRegexp(attrName) {
|
|
if (attrRegexps[attrName]) {
|
|
return attrRegexps[attrName];
|
|
}
|
|
|
|
attrRegexps[attrName] = new RegExp(' ' + attrName + '="((?:\\\\(?=")"|[^"])+)"', 'i');
|
|
return attrRegexps[attrName];
|
|
}
|
|
|
|
function setHtmlAttribute(html, attrName, value) {
|
|
var attr = ' ' + attrName + '="' + value + '"';
|
|
|
|
if (html.indexOf(' ' + attrName + '="') === -1) {
|
|
html = html.replace(/<[a-z]+/i, function(beginning) { return beginning + attr; });
|
|
} else {
|
|
html = html.replace(getAttrRegexp(attrName), attr);
|
|
}
|
|
|
|
return html;
|
|
}
|
|
|
|
function fixed(number) {
|
|
return number.toFixed(3).replace('.000', '');
|
|
}
|
|
|
|
function mod(a, n) {
|
|
return a >= n ? a % n : a>=0 ? a : n-1-(-1-a) % n;
|
|
}
|
|
|
|
function xprod(p1, p2) {
|
|
return p1.x * p2.y - p1.y * p2.x;
|
|
}
|
|
|
|
function cyclic(a, b, c) {
|
|
if (a <= c) {
|
|
return (a <= b && b < c);
|
|
} else {
|
|
return (a <= b || b < c);
|
|
}
|
|
}
|
|
|
|
function sign(i) {
|
|
return i > 0 ? 1 : i < 0 ? -1 : 0;
|
|
}
|
|
|
|
function quadform(Q, w) {
|
|
var v = new Array(3), i, j, sum;
|
|
|
|
v[0] = w.x;
|
|
v[1] = w.y;
|
|
v[2] = 1;
|
|
sum = 0.0;
|
|
|
|
for (i=0; i<3; i++) {
|
|
for (j=0; j<3; j++) {
|
|
sum += v[i] * Q.at(i, j) * v[j];
|
|
}
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
function interval(lambda, a, b) {
|
|
var res = new Point();
|
|
|
|
res.x = a.x + lambda * (b.x - a.x);
|
|
res.y = a.y + lambda * (b.y - a.y);
|
|
return res;
|
|
}
|
|
|
|
function dorth_infty(p0, p2) {
|
|
var r = new Point();
|
|
|
|
r.y = sign(p2.x - p0.x);
|
|
r.x = -sign(p2.y - p0.y);
|
|
|
|
return r;
|
|
}
|
|
|
|
function ddenom(p0, p2) {
|
|
var r = dorth_infty(p0, p2);
|
|
|
|
return r.y * (p2.x - p0.x) - r.x * (p2.y - p0.y);
|
|
}
|
|
|
|
function dpara(p0, p1, p2) {
|
|
var x1, y1, x2, y2;
|
|
|
|
x1 = p1.x - p0.x;
|
|
y1 = p1.y - p0.y;
|
|
x2 = p2.x - p0.x;
|
|
y2 = p2.y - p0.y;
|
|
|
|
return x1 * y2 - x2 * y1;
|
|
}
|
|
|
|
function cprod(p0, p1, p2, p3) {
|
|
var x1, y1, x2, y2;
|
|
|
|
x1 = p1.x - p0.x;
|
|
y1 = p1.y - p0.y;
|
|
x2 = p3.x - p2.x;
|
|
y2 = p3.y - p2.y;
|
|
|
|
return x1 * y2 - x2 * y1;
|
|
}
|
|
|
|
function iprod(p0, p1, p2) {
|
|
var x1, y1, x2, y2;
|
|
|
|
x1 = p1.x - p0.x;
|
|
y1 = p1.y - p0.y;
|
|
x2 = p2.x - p0.x;
|
|
y2 = p2.y - p0.y;
|
|
|
|
return x1*x2 + y1*y2;
|
|
}
|
|
|
|
function iprod1(p0, p1, p2, p3) {
|
|
var x1, y1, x2, y2;
|
|
|
|
x1 = p1.x - p0.x;
|
|
y1 = p1.y - p0.y;
|
|
x2 = p3.x - p2.x;
|
|
y2 = p3.y - p2.y;
|
|
|
|
return x1 * x2 + y1 * y2;
|
|
}
|
|
|
|
function ddist(p, q) {
|
|
return Math.sqrt((p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y));
|
|
}
|
|
|
|
module.exports = {
|
|
luminance: function (r, g, b) {
|
|
return Math.round(0.2126 * r + 0.7153 * g + 0.0721 * b);
|
|
},
|
|
|
|
between: function(val, min, max) {
|
|
return val >= min && val <= max;
|
|
},
|
|
|
|
clamp: function(val, min, max) {
|
|
return Math.min(max, Math.max(min, val));
|
|
},
|
|
|
|
isNumber: function(val) {
|
|
return typeof val === 'number';
|
|
},
|
|
|
|
setHtmlAttr: setHtmlAttribute,
|
|
|
|
/**
|
|
* Generates path instructions for given curve
|
|
*
|
|
* @param {Curve} curve
|
|
* @param {Number} [scale]
|
|
* @returns {string}
|
|
*/
|
|
renderCurve: function(curve, scale) {
|
|
scale = scale || 1;
|
|
|
|
var startingPoint = curve.c[(curve.n - 1) * 3 + 2];
|
|
|
|
var path = 'M '
|
|
+ fixed(startingPoint.x * scale) + ' '
|
|
+ fixed(startingPoint.y * scale) + ' ';
|
|
|
|
curve.tag.forEach(function(tag, i) {
|
|
var i3 = i * 3;
|
|
var p0 = curve.c[i3];
|
|
var p1 = curve.c[i3 + 1];
|
|
var p2 = curve.c[i3 + 2];
|
|
|
|
if (tag === "CURVE") {
|
|
path += 'C ';
|
|
path += fixed(p0.x * scale) + ' ' + fixed(p0.y * scale) + ', ';
|
|
path += fixed(p1.x * scale) + ' ' + fixed(p1.y * scale) + ', ';
|
|
path += fixed(p2.x * scale) + ' ' + fixed(p2.y * scale) + ' ';
|
|
} else if (tag === "CORNER") {
|
|
path += 'L ';
|
|
path += fixed(p1.x * scale) + ' ' + fixed(p1.y * scale) + ' ';
|
|
path += fixed(p2.x * scale) + ' ' + fixed(p2.y * scale) + ' ';
|
|
}
|
|
});
|
|
|
|
return path;
|
|
},
|
|
|
|
bezier: function bezier(t, p0, p1, p2, p3) {
|
|
var s = 1 - t, res = new Point();
|
|
|
|
res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x;
|
|
res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y;
|
|
|
|
return res;
|
|
},
|
|
|
|
tangent: function tangent(p0, p1, p2, p3, q0, q1) {
|
|
var A, B, C, a, b, c, d, s, r1, r2;
|
|
|
|
A = cprod(p0, p1, q0, q1);
|
|
B = cprod(p1, p2, q0, q1);
|
|
C = cprod(p2, p3, q0, q1);
|
|
|
|
a = A - 2 * B + C;
|
|
b = -2 * A + 2 * B;
|
|
c = A;
|
|
|
|
d = b * b - 4 * a * c;
|
|
|
|
if (a===0 || d<0) {
|
|
return -1.0;
|
|
}
|
|
|
|
s = Math.sqrt(d);
|
|
|
|
r1 = (-b + s) / (2 * a);
|
|
r2 = (-b - s) / (2 * a);
|
|
|
|
if (r1 >= 0 && r1 <= 1) {
|
|
return r1;
|
|
} else if (r2 >= 0 && r2 <= 1) {
|
|
return r2;
|
|
} else {
|
|
return -1.0;
|
|
}
|
|
},
|
|
|
|
mod: mod,
|
|
xprod: xprod,
|
|
cyclic: cyclic,
|
|
sign: sign,
|
|
quadform: quadform,
|
|
interval: interval,
|
|
dorth_infty: dorth_infty,
|
|
ddenom: ddenom,
|
|
dpara: dpara,
|
|
cprod: cprod,
|
|
iprod: iprod,
|
|
iprod1: iprod1,
|
|
ddist: ddist
|
|
}; |