二次贝塞尔曲线:已知 x 求 t

4

我正在使用以下配置的二次贝塞尔曲线:

起始点P1 =(1,2)
锚点P2 =(1,8)
结束点P3 =(10,8)

我知道,给定t,我可以使用以下方程式解出x和y:

t = 0.5; // given example value
x = (1 - t) * (1 - t) * P1.x + 2 * (1 - t) * t * P2.x + t * t * P3.x;
y = (1 - t) * (1 - t) * P1.y + 2 * (1 - t) * t * P2.y + t * t * P3.y;

其中P1.x是P1的x坐标,以此类推。

我现在尝试的是,给定一个x值,我使用wolframalpha计算t,然后将该t插入y方程式中,得到我的x和y点。

但是,我想自动化查找t和y。我有一个公式可以根据t获取x和y。但是,我没有一个公式可以根据x获取t。我的代数有点生疏,扩展第一个方程以隔离t看起来并不容易。

如何确定一个公式来获取基于x的t? 我的网络搜索技能现在正在失败。

我认为值得注意的是,我的贝塞尔曲线面向右。


由于贝塞尔曲线不是函数,因此您可以有多个 x 对应一个 y,也可以有多个 y 对应一个 x 坐标。 - karatedog
一个二次贝塞尔曲线是一个(参数化的)函数,除非它是一条直线,否则它最多与另一条直线相交于2个点。我在下面给出了针对与垂直线(x = 常数)相交的直接解决方案;它没有起作用吗? - dwn
3个回答

1
问题在于你想要解决的并不是通用函数。
对于任何一个t,只有一个(x,y)对。
但对于任何一个x,可能会有0、1、2或无限多个t的解。
我会逐步进行此操作。
您已经可以获取任何点p(t)=Bezier(t),因此使用迭代t来最小化距离|p(t).x-x|。
  1. for(t=0.0,dt=0.1;t<=1.0;t+=dt)

  2. 寻找所有满足条件 d=|p(t).x-x| 的本地最小值

    d 开始上升时,设置 dt*=-0.1 并停止搜索,如果 |dt|<1e-6 或任何其他阈值,则停止。 如果 t 超出区间 <0,1>,则将解决方案记录到某个列表中。恢复原始的 t,dt 并重置本地最小值搜索变量

  3. 处理所有本地最小值

    消除所有距离大于某个阈值/精度的值,计算 y 并对点进行必要操作...

这种方法比代数方法慢得多,但您可以将其用于任何曲率,而不仅仅是二次曲线。

通常使用三次曲线并在其中进行代数运算是一场噩梦。


0

看看你的伯恩斯坦多项式 B[i];你有...

x = SUM_i ( B[i](t) * P[i].x )

...在哪里...

B[0](t) = t^2 - 2*t + 1
B[1](t) = -2*t^2 + 2*t
B[2](t) = t^2

…因此您可以重新排列(假设我做得正确)…

0 = (P[0].x - 2*P[1].x + P[2].x) * t^2 + (-2*P[0].x + 2*P[1].x) * t + P[0].x - x

现在你应该可以使用二次公式来确定t的解是否存在(即,是实数而非复数),以及它们是什么。

0
import numpy as np
import matplotlib.pyplot as plt
#Control points
p0=(1000,2500); p1=(2000,-1500); p2=(5000,3000)
#x-coordinates to fit
xcoord = [1750., 2750., 3950.,4760., 4900.]

# t variable with as few points as needed, considering accuracy. I found 30 is good enough 
t = np.linspace(0,1,30)

# calculate coordinates of quadratic Bezier curve
x = (1 - t) * (1 - t) * p0[0] + 2 * (1 - t) * t * p1[0] + t * t * p2[0];
y = (1 - t) * (1 - t) * p0[1] + 2 * (1 - t) * t * p1[1] + t * t * p2[1];

# find the closest points to each x-coordinate. Interpolate y-coordinate
ycoord=[]
for ind in xcoord:
    for jnd in range(len(x[:-1])):
        if ind >= x[jnd] and ind <= x[jnd+1]:
            ytemp = (ind-x[jnd])*(y[jnd+1]-y[jnd])/(x[jnd+1]-x[jnd]) + y[jnd]
            ycoord.append(ytemp)


plt.figure()
plt.xlim(0, 6000)
plt.ylim(-2000, 4000)
plt.plot(p0[0],p0[1],'kx', p1[0],p1[1],'kx', p2[0],p2[1],'kx')
plt.plot((p0[0],p1[0]),(p0[1],p1[1]),'k:', (p1[0],p2[0]),(p1[1],p2[1]),'k:')
plt.plot(x,y,'r', x, y, 'k:')
plt.plot(xcoord, ycoord, 'rs')
plt.show()

1
编程相关内容的翻译:请提供需要翻译的具体内容。 - Huey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接