function bezierInterpolate(x1, y1, x2, y2) {
function bezier(x1, x2) {
const a = 1 - 3 * x2 + 3 * x1,
b = 3 * x2 - 6 * x1,
c = 3 * x1;
return t => ((a * t + b) * t + c) * t;
}
function bezierDerivate(x1, x2) {
const a = 3 - 9 * x2 + 9 * x1,
b = 6 * x2 - 12 * x1,
c = 3 * x1;
return t => (a * t + b) * t + c;
}
function solve(f, fp, y) {
let x = y;
for (let i = 0; i < 100; i++) {
const delta = (y - f(x)) / (fp(x) || epsilon),
absd = abs(delta);
x += absd < 0.1 ? delta : (0.1 * delta) / absd;
if (absd < 1e-9) break;
}
return x < 0 ? 0 : x > 1 ? 1 : x;
}
return x1 === y1 && x2 === y2
? x => x
: (x, debug) => {
if (!debug) {
return bezier(y1, y2)(
solve(bezier(x1, x2), bezierDerivate(x1, x2), x)
);
} else {
const t = solve(bezier(x1, x2), bezierDerivate(x1, x2), x),
y = bezier(y1, y2)(t);
const foundx = bezier(x1, x2)(t),
err = abs(x - foundx);
return {
t,
foundx,
err,
y
};
}
};
}