Graphics 计算曲面的地平线?

Graphics 计算曲面的地平线?,graphics,3d,points,bezier,geometry-surface,Graphics,3d,Points,Bezier,Geometry Surface,我需要找到两个可视地平线的点,一个曲面 我有: 四个角点的XYZ 2个曲边bezier点的XYZ 我需要计算: 水平点的XY 地平线点的XYZ 首先,您必须将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 i

我需要找到两个可视地平线的点,一个曲面

我有:

  • 四个角点的XYZ
  • 2个曲边bezier点的XYZ
我需要计算:

  • 水平点的XY
  • 地平线点的XYZ

首先,您必须将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、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;
}
int getquadraicroots(浮点A、浮点B、浮点C、浮点*根)
{
if((C<-FLT_ε)| |(C>FLT_ε))
{
浮点数d,p;
//它是一个立方体:
p=B*B-4.0f*C*A;
d=0.5f/C;
如果(p>=0)
{
p=(浮动)sqrt(p);
if((p<-FLT_ε)| |(p>FLT_ε))
{
//两个单根:
根[0]=(-B+p)*d;
根[1]=(-B-p)*d;
返回2;
} 
//一个双根:
根[0]=-B*d;
返回1;
}否则{
//无根:
返回0;
}
} 
//它是线性的:
if((B<-FLT_ε)| |(B>FLT_ε))
{
//一个单根:
根[0]=-A/B;
返回1;
}
//它是常数,所以…没有根。
返回0;
}

非常感谢您的大力帮助,我只想知道如何“将贝塞尔曲线从贝塞尔表示(X,Y为3点)转换为多项式”这是否适用于二次贝塞尔方程,因为它将返回线性导数?或者我应该试着把我的二次贝塞尔转换成三次贝塞尔吗?再次感谢您难以置信的帮助。任何一种解决方案都有效。我只需要建立二次贝塞尔的一阶导数。这会给你一个像a*t+b=0这样的方程,它更容易解。我真的理解了为什么你的解不起作用。请你帮我把这个问题重新发上来好吗:讨论继续在
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;
}