3

我需要找到一个曲面的视觉地平线的 2 个点。

我有:

  • 4 个角点的 XYZ
  • 2 个弯曲边缘贝塞尔点的 XYZ

我需要计算:

  • 水平点的 XY
  • 水平点的 XYZ
4

1 回答 1

4

首先,您必须将 3D 贝塞尔曲线转换为 2D。如果我没记错的话,就像投影 3D 点进行渲染一样投影曲线就足够了。

之后,您必须找到曲线的极值。

一个小方法:

将贝塞尔曲线从贝塞尔表示转换为形式的多项式

  x(t) = a*t^3 + b*t^2 + c*t + d
  y(t) = e*t^3 + f*t^2 + g*t + g

  Here t is your interpolation variable that goes from 0 to 1.
  a to d are the coefficients for the curve along the x-axis
  e to g are the coefficients for the curve along the y-axis.

现在您构建曲线的第一个推导(很简单,因为它是一个多项式)。这会给你一个二次方程。求解这些根并丢弃所有在 0..1 范围之外的根。再次找到根很容易,因为它只是一个二次多项式。

你怎么有一堆根。将所有这些重新插入原始贝塞尔曲线,评估它们的位置,你会得到一堆点。极值——如果存在的话——将在这些点之间。

现在您所要做的就是搜索具有最高(或最低-不知道您的坐标系如何)y坐标的那个。

请注意,您可能根本没有得到极值。如果您的贝塞尔曲线是例如直线,就会发生这种情况。在这些情况下,您可能还希望在极值搜索中包含第一个和最后一个贝塞尔控制点。


编辑:

您已经问过如何将贝塞尔曲线变成多项式。好吧,你从正常的贝塞尔曲线方程开始:

 x(t) = x0 * (1-t)³ + 3*x1*(1-t)²*t + 3*x2*(1-t)*t² +x3*t³

(x0 到 x3 是曲线的四个控制点的 x 值)。

然后你将所有项一个接一个地相乘,并按 t 的幂对它们进行排序。不幸的是,我没有在我正在写的计算机上运行我的数学包,而且我懒得在纸上做:-) 所以如果有人运行 mathlab,你能编辑这个答案并添加扩展版本?

无论如何,由于您对多项式并不真正感兴趣,而只是它的导数,所以事情会容易一些。您可以直接获取系数(此处仅显示 x):

A = 3.0f*(x[1] - x[0]);
B = 6.0f*(x[2] - 2.0f*x[1] + x[0]);
C = 3.0f*(x[3] - 3.0f*x[2] + 3.0f *x[1] - x[0]);

使用这三个值 (A,B,C),一阶导数的多项式如下所示:

  x(t) = A*t^2 + B*t + C

现在将 A、B 和 C 插入二次多项式的根求解器中,就完成了。作为参考,我使用下面的求解器 C 代码:

int GetQuadraticRoots (float A, float B, float C, float *roots)
{
  if ((C < -FLT_EPSILON) || (C > FLT_EPSILON))
  {
    float d,p;
    // it is a cubic:
    p = B*B - 4.0f * C*A;
    d = 0.5f / C;
    if (p>=0)
    {
      p = (float) sqrt(p);
      if ((p < -FLT_EPSILON) || (p > FLT_EPSILON))
      {
        // two single roots:
        roots[0] = (-B + p)*d;
        roots[1] = (-B - p)*d;
        return 2;
      } 
      // one double root:
      roots[0] = -B*d;
      return 1;
    } else {
      // no roots:
      return 0;
    }
  } 
  // it is linear:
  if ((B < -FLT_EPSILON) || (B > FLT_EPSILON))
  {
    // one single root:
    roots[0] = -A/B;
    return 1;
  }
  // it is constant, so .. no roots.
  return 0;
}
于 2009-02-21T18:00:08.097 回答