Javascript 中三次贝塞尔曲线上的点坐标

问题描述 投票:0回答:1

我正在尝试创建一个 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。

有人能看出计算有问题吗?

javascript bezier
1个回答
0
投票

此类贝塞尔曲线涉及三个值:

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];
};
© www.soinside.com 2019 - 2024. All rights reserved.