【问题标题】:Quadratic Bezier Curve: Calculate t given x二次贝塞尔曲线:给定 x 计算 t
【发布时间】:2015-01-06 04:02:56
【问题描述】:

美好的一天。我正在使用具有以下配置的二次贝塞尔曲线:

起点 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 的公式?到目前为止,我的 google 搜索技能都失败了。

我认为我的贝塞尔曲线朝右也是值得注意的。

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 因为贝塞尔曲线不是函数,所以一个y 可以有多个x,一个x 坐标可以有多个y
  • 二次贝塞尔曲线是一个(参数)函数,除非它是一条直线,否则它最多与另一条直线相交 2 个点。我在下面给出了与垂直线相交的简单解决方案(x = 常数);没用吗?

标签: math point bezier


【解决方案1】:

问题是你要解决的不是一般的功能

  • 任何t 都只是一对(x,y)
  • 但是对于任何x 都可以有0,1,2,+inft 解决方案

我会反复执行此操作

你已经可以得到任何点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|的所有本地mins

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

  3. 处理所有本地mins

    消除所有具有更大距离然后一些阈值/精度计算y 并用点做你需要的事情......

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

通常使用三次曲线,用它们进行代数运算是一场噩梦。

【讨论】:

    【解决方案2】:

    看看你的伯恩斯坦多项式 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 的解是否存在(即,是实数,而不是复数),以及它们是什么。

    【讨论】:

      【解决方案3】:
      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()
      

      【讨论】:

      • 某种解释会很有帮助。
      猜你喜欢
      • 2011-08-03
      • 1970-01-01
      • 1970-01-01
      • 2011-03-10
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多