无需猜测或蛮力即可获得贝塞尔曲线上的一个点
get a point on a bezier curve without guessing or brute force
我最初想使用四个点(因为贝塞尔曲线是用 4 个点定义的),但这迫使我强制定位,所以我尝试了一种不同的方法,我现在需要帮助:
我有一个起点 P0、一个终点 P1 和斜率 m0 和 m1,它们应该给我 start/end 斜率来计算它们之间的贝塞尔曲线。
曲线应该是函数的形式(三阶),因为我需要得到给定点 x 的高度 y。
使用 HTML5Canvas 我可以毫无问题地绘制贝塞尔曲线并使用此功能
这允许我计算任何给定的点,给定我可以获得曲线中心点的方式的百分比。但我不需要它取决于 t 而是取决于 x 的 y,所以不是曲线的一半而是 P0 和 P1 之间 x 距离的一半。
可视化图像:
左边是我能算出来的,右边是我需要的。
我一直在尝试计算给定两个点 P0、P1 以及斜率 m0、m1 的三次函数,这导致四个方程我似乎无法仅用变量来求解输入。我还尝试使用上述函数使用 x 值(已知)计算 t,但那里也没有骰子。
我需要避免对这些计算使用近似值或昂贵的循环,因为它们每秒对许多对象执行多次,因此 this answer 对我来说不可行。
感谢任何帮助。
我在从事的项目中遇到了同样的问题。我不知道从 x
获取 y
坐标的公式,我怀疑你会遇到这条路线的麻烦,因为贝塞尔曲线最多可以有 3 个点相同的 x 值。
我会推荐使用 BezierEasing 库,它专为这个用例设计并使用各种性能增强技术来尽可能快地进行查找:https://github.com/gre/bezier-easing
为了解决这个问题,你需要用幂多项式形式重写贝塞尔方程
X(t) = t^3 * (P3.X-3*P2.X+3*P1.X-P0.X) +
t^2 * (3*P0.X + 6*P1.X+3*P2.X) +
t * (3*P1.X - 3P2.X) +
P0.X
if X(t) = P0.X*(1-ratio) + P3.X*ratio
then
let d = ratio * (P0.X - P3.X)
并求解 cubic equation 未知 t
a*t^3 + b*t^2 + c*t + d = 0
JS code here
然后将计算的t
参数(最多可能有三个解)应用于Y分量并得到点坐标。请注意,公式是封闭的(没有循环)并且应该足够快
感谢之前回答的每个人,这些通常都是很好的解决方案。
在我的例子中,我可以 100% 确定我可以将曲线转换为三次函数,使用 the result of this calculation.
作为贝塞尔曲线的近似值
因为我可以控制我的点,我可以强制 P0 在 x=0 上,这简化了线性系统的计算,从而使我可以更容易地计算三次函数,如下所示:
let startPoint: Utils.Vector2 = new Utils.Vector2(0, 100);
let endPoint: Utils.Vector2 = new Utils.Vector2(100, 100);
let a: number, b: number, c: number, d: number;
function calculateFunction() {
let m0: number = 0;
let m1: number = 0;
a = (-endPoint.x * (m0 + m1) - 2 * startPoint.y + 2 * endPoint.y) / -Math.pow(endPoint.x, 3);
b = (m1 - m0 - 3 * a * Math.pow(endPoint.x, 2)) / (2 * endPoint.x);
c = m0;
d = startPoint.y;
}
我最初想使用四个点(因为贝塞尔曲线是用 4 个点定义的),但这迫使我强制定位,所以我尝试了一种不同的方法,我现在需要帮助:
我有一个起点 P0、一个终点 P1 和斜率 m0 和 m1,它们应该给我 start/end 斜率来计算它们之间的贝塞尔曲线。
曲线应该是函数的形式(三阶),因为我需要得到给定点 x 的高度 y。
使用 HTML5Canvas 我可以毫无问题地绘制贝塞尔曲线并使用此功能
这允许我计算任何给定的点,给定我可以获得曲线中心点的方式的百分比。但我不需要它取决于 t 而是取决于 x 的 y,所以不是曲线的一半而是 P0 和 P1 之间 x 距离的一半。
可视化图像:
左边是我能算出来的,右边是我需要的。
我一直在尝试计算给定两个点 P0、P1 以及斜率 m0、m1 的三次函数,这导致四个方程我似乎无法仅用变量来求解输入。我还尝试使用上述函数使用 x 值(已知)计算 t,但那里也没有骰子。
我需要避免对这些计算使用近似值或昂贵的循环,因为它们每秒对许多对象执行多次,因此 this answer 对我来说不可行。
感谢任何帮助。
我在从事的项目中遇到了同样的问题。我不知道从 x
获取 y
坐标的公式,我怀疑你会遇到这条路线的麻烦,因为贝塞尔曲线最多可以有 3 个点相同的 x 值。
我会推荐使用 BezierEasing 库,它专为这个用例设计并使用各种性能增强技术来尽可能快地进行查找:https://github.com/gre/bezier-easing
为了解决这个问题,你需要用幂多项式形式重写贝塞尔方程
X(t) = t^3 * (P3.X-3*P2.X+3*P1.X-P0.X) +
t^2 * (3*P0.X + 6*P1.X+3*P2.X) +
t * (3*P1.X - 3P2.X) +
P0.X
if X(t) = P0.X*(1-ratio) + P3.X*ratio
then
let d = ratio * (P0.X - P3.X)
并求解 cubic equation 未知 t
a*t^3 + b*t^2 + c*t + d = 0
JS code here
然后将计算的t
参数(最多可能有三个解)应用于Y分量并得到点坐标。请注意,公式是封闭的(没有循环)并且应该足够快
感谢之前回答的每个人,这些通常都是很好的解决方案。
在我的例子中,我可以 100% 确定我可以将曲线转换为三次函数,使用 the result of this calculation.
作为贝塞尔曲线的近似值因为我可以控制我的点,我可以强制 P0 在 x=0 上,这简化了线性系统的计算,从而使我可以更容易地计算三次函数,如下所示:
let startPoint: Utils.Vector2 = new Utils.Vector2(0, 100);
let endPoint: Utils.Vector2 = new Utils.Vector2(100, 100);
let a: number, b: number, c: number, d: number;
function calculateFunction() {
let m0: number = 0;
let m1: number = 0;
a = (-endPoint.x * (m0 + m1) - 2 * startPoint.y + 2 * endPoint.y) / -Math.pow(endPoint.x, 3);
b = (m1 - m0 - 3 * a * Math.pow(endPoint.x, 2)) / (2 * endPoint.x);
c = m0;
d = startPoint.y;
}