var bezier = function(mX1, mY1, mX2, mY2) {
this.mX1 = mX1;
this.mY1 = mY1;
this.mX2 = mX1;
this.mY2 = mY2;
return bz.pB(mX1, mY1, mX2, mY2);
}
var bz = bezier.prototype;
// These values are established by empiricism with tests (tradeoff: performance VS precision)
bz.ni = 4; // NEWTON_ITERATIONS
bz.nms = 0.001; // NEWTON_MIN_SLOPE
bz.sp = 0.0000001; // SUBDIVISION_PRECISION
bz.smi = 10, // SUBDIVISION_MAX_ITERATIONS
bz.ksts = 11; // k Spline Table Size
bz.ksss = 1.0 / (bz.ksts - 1.0); // k Sample Step Size
bz.f32as = 'Float32Array' in window; // float32ArraySupported
bz.msv = bz.f32as ? new Float32Array (bz.ksts) : new Array (bz.ksts); // m Sample Values
bz._p = false;
bz.A = function(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; };
bz.B = function(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; };
bz.C = function(aA1) { return 3.0 * aA1; };
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
bz.cB = function(aT, aA1, aA2) { // calc Bezier
return ((bz.A(aA1, aA2)*aT + bz.B(aA1, aA2))*aT + bz.C(aA1))*aT;
};
// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
bz.gS = function (aT, aA1, aA2) { // getSlope
return 3.0 * bz.A(aA1, aA2)*aT*aT + 2.0 * bz.B(aA1, aA2) * aT + bz.C(aA1);
};
bz.bS = function(a, aA, aB) { // binary Subdivide
var x, t, i = 0;
do {
t = aA + (aB - aA) / 2.0;
x = bz.cB(t, bz.mX1, bz.mX2) - a;
if (x > 0.0) {
aB = t;
} else {
aA = t;
}
} while (Math.abs(x) > bz.sp && ++i < bz.smi);
return t;
};
bz.nri = function (aX, agt) { // newton Raphs on Iterate
for (var i = 0; i < bz.ni; ++i) {
var cs = bz.gS(agt, bz.mX1, bz.mX2);
if (cs === 0.0) return agt;
var x = bz.cB(agt, bz.mX1, bz.mX2) - aX;
agt -= x / cs;
}
return agt;
};
bz.csv = function () { // calc Sample Values
for (var i = 0; i < bz.ksts; ++i) {
bz.msv[i] = bz.cB(i * bz.ksss, bz.mX1, bz.mX2);
}
};
bz.gx = function (aX) { //get to X
var is = 0.0, cs = 1, ls = bz.ksts - 1;
for (; cs != ls && bz.msv[cs] <= aX; ++cs) {
is += bz.ksss;
}
--cs;
// Interpolate to provide an initial guess for t
var dist = (aX - bz.msv[cs]) / (bz.msv[cs+1] - bz.msv[cs]),
gt = is + dist * bz.ksss,
ins = bz.gS(gt, bz.mX1, bz.mX2);
if (ins >= bz.nms) {
return bz.nri(aX, gt);
} else if (ins === 0.0) {
return gt;
} else {
return bz.bS(aX, is, is + bz.ksss, bz.mX1, bz.mX2);
}
};
bz.pB = function (mX1, mY1, mX2, mY2) {
bz.mX1 = mX1;
bz.mX2 = mX2;
bz.mY1 = mY1;
bz.mY2 = mY2;
return function(aX) { // process bezier
if (!bz._p) bz.pc();
if (bz.mX1 === bz.mY1 && bz.mX2 === bz.mY2) return aX; // linear
if (aX === 0) return 0;
if (aX === 1) return 1;
return bz.cB(bz.gx(aX), bz.mY1, bz.mY2);
};
};
bz.pc = function() {
bz._p = true;
if (bz.mX1 != bz.mY1 || bz.mX2 != bz.mY2)
bz.csv();
};
BTW: this is the fastest blade in the land in terms of performance.
Thanks for any reply.