81 lines
2.4 KiB
JavaScript
81 lines
2.4 KiB
JavaScript
/**
|
|
* https://github.com/arian/cubic-bezier
|
|
*
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2013 Arian Stolwijk
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* @providesModule bezier
|
|
* @nolint
|
|
*/
|
|
|
|
module.exports = function(x1, y1, x2, y2, epsilon){
|
|
|
|
var curveX = function(t){
|
|
var v = 1 - t;
|
|
return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t;
|
|
};
|
|
|
|
var curveY = function(t){
|
|
var v = 1 - t;
|
|
return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t;
|
|
};
|
|
|
|
var derivativeCurveX = function(t){
|
|
var v = 1 - t;
|
|
return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (- t * t * t + 2 * v * t) * x2;
|
|
};
|
|
|
|
return function(t){
|
|
|
|
var x = t, t0, t1, t2, x2, d2, i;
|
|
|
|
// First try a few iterations of Newton's method -- normally very fast.
|
|
for (t2 = x, i = 0; i < 8; i++){
|
|
x2 = curveX(t2) - x;
|
|
if (Math.abs(x2) < epsilon) return curveY(t2);
|
|
d2 = derivativeCurveX(t2);
|
|
if (Math.abs(d2) < 1e-6) break;
|
|
t2 = t2 - x2 / d2;
|
|
}
|
|
|
|
t0 = 0, t1 = 1, t2 = x;
|
|
|
|
if (t2 < t0) return curveY(t0);
|
|
if (t2 > t1) return curveY(t1);
|
|
|
|
// Fallback to the bisection method for reliability.
|
|
while (t0 < t1){
|
|
x2 = curveX(t2);
|
|
if (Math.abs(x2 - x) < epsilon) return curveY(t2);
|
|
if (x > x2) t0 = t2;
|
|
else t1 = t2;
|
|
t2 = (t1 - t0) * .5 + t0;
|
|
}
|
|
|
|
// Failure
|
|
return curveY(t2);
|
|
|
|
};
|
|
|
|
};
|