我正在尝试创建一个 JS 函数,该函数将在给定 X 坐标的情况下返回三次贝塞尔曲线上的 Y 坐标。这是我所拥有的:
function pointOnBezier(t, p0, p1, p2, p3) {
var x = Math.pow(1-t,3) * p0[0] + 3 * t * Math.pow(1 - t, 2) * p1[0] + 3 * t * t * (1 - t) * p2[0] + t * t * t * p3[0];
var y = Math.pow(1-t,3) * p0[1] + 3 * t * Math.pow(1 - t, 2) * p1[1] + 3 * t * t * (1 - t) * p2[1] + t * t * t * p3[1];
return [x, y];
}
console.log(0.25, pointOnBezier(0.25, [0,0], [0.5, 0.5], [0.5, 0.5], [1.0, 1.0]));
console.log(0.5, pointOnBezier(0.5, [0,0], [0.5, 0.5], [0.5, 0.5], [1.0, 1.0]));
console.log(0.75, pointOnBezier(0.75, [0,0], [0.5, 0.5], [0.5, 0.5], [1.0, 1.0]));
我包含了三个测试值。如果运行代码,t=0.25 和 t=0.75 的预期结果是值 0.25 和 0.75,但它返回 0.3 和 0.7。
有人能看出计算有问题吗?
此类贝塞尔曲线涉及三个值:
t
是函数的输入,x
和y
是输出。
对于给定的 x
值,您的代码返回 y
和 t
的值,但没有理由 t
会以任何明显的方式与 x
相关。
一般来说,从
x
(你的代码)获取y
和t
很容易,但从y
获取x
比较复杂。唯一的方法是通过二分搜索:尝试一些 t
的值,直到足够接近所需的 x
,这也会为您提供您正在寻找的 y
。
示例代码(未经测试并假设贝塞尔曲线正在增加):
const EPSILON = 0.00001;
const getY = (x, p0, p1, p2, p3) => {
let minT = 0;
let maxT = 1;
while (maxT - minT > EPSILON) {
const t = (minT + maxT) / 2;
const newX = pointOnBezier(t, p0, p1, p2, p3)[0];
if (newX > x) {
maxT = t;
} else {
minT = t;
}
}
return pointOnBezier(minT, p0, p1, p2, p3)[1];
};