【问题标题】:Algorithm to calculate sphere by revolution has addition error旋转计算球体的算法有加法误差
【发布时间】:2022-01-24 08:00:34
【问题描述】:

我正在尝试通过旋转(旋转)生成一个球体。 我的想法是围绕轴以相等的步长旋转一个点,直到 180 度,这样我就有了一个模板。 然后我将这个模板围绕另一个轴旋转(逐步,最多 360 度)以生成一个球体。 算法如下:

if (o == objeto::SPHERE_P) // if the object type is Template Sphere I will rotate only 180 degrees.
        ang = M_PI;

    Vertices.resize(tamanio);
    int p = 0;
    //
    //Rotamos en función del eje.
    float nrot = 1.0/nr;
    switch (e)
    {
    case eje::AXIS_X:
        for (int i = 0; i <= nr; i++)
            for (int j = 0; j < nv; j++, p++)
            {
                float R = Distancia(plantilla[j], _vertex3f(plantilla[j].x, 0, 0));
                float a = R * cos(i*nrot*ang);
                float b = R * sin(i*nrot*ang);
                    Vertices[p] = _vertex3f(plantilla[j].x, a, b);
            }
        break;
    case eje::AXIS_Y:
        for (int i = 0; i <= nr; i++)
            for (int j = 0; j < nv; j++, p++)
            {
                float R = Distancia(plantilla[j], _vertex3f(0, plantilla[j].y, 0));
                float a = R * cos(i*nrot*ang);
                float b = R * sin(i*nrot*ang);
                Vertices[p] = _vertex3f(a, plantilla[j].y, b);
            }
        break;
    case eje::AXIS_Z:
        for (int i = 0; i <= nr; i++)
            for (int j = 0; j < nv; j++, p++)
            {
                float R = Distancia(plantilla[j], _vertex3f(0, 0, plantilla[j].z));
                float a = R * cos(i*nrot*ang);
                float b = R * sin(i*nrot*ang);
                Vertices[p] = _vertex3f(a, b, plantilla[j].z);
            }
        break;
    }
}
  • nr 是旋转次数。
  • Distancia 是球体半径,或从原点到球体上任意点的距离。
  • ab 是坐标(取决于球体旋转的轴,一个坐标不变)
  • nrot 是 1.0/nr
  • 顶点是一个顶点数组
  • nv 保存顶点数

问题

由于我使用M_PI,球体生成涉及一个微小的数值错误,最终会导致运行时错误。情况是最后一个顶点应该恰好在初始轴上,而不是它的坐标如下图所示: They should be 0,-5,0 这是一个小错误,但足以使我的功能(检查点是否在轴上)失败。 我可以修复它,将顶点坐标四舍五入,但这对我来说感觉像是一项拙劣的工作。

谁能告诉我另一种生成旋转角度的方法,以便我可以毫无错误地生成球体?

谢谢。

【问题讨论】:

  • 欢迎来到浮点表示和截断错误的世界。较新的假设是,在这种情况下,您可以使用比较来实现相等。考虑引入公差。
  • 你的C库是否提供函数sinpi
  • 考虑对称性,只计算0
  • 期望浮点计算准确是错误的。
  • 为什么不迭代度数而不是弧度,然后从中计算弧度?这样,如果您的度数是一个整数,或者至少是一个可以用二进制值准确表示的数字,那么在转换为弧度时会发生唯一的错误,但在求和时不会发生错误。

标签: c++ algorithm math geometry


【解决方案1】:

类似的循环

for (i= 0, th= 0; i <= n; i++, th+= π/n)
    s= sin(th);

不能保证th 的最终值将完全是π,我们甚至可以确定sin(π) = 0 的数值吗?

使用更安全

for (i= 0, th= 0; i <= n; i++, th+= π/n)
    s= i < n ? sin(th) : 0;

(类似地,不要指望经过π/6 的循环恰好产生sin(th) = 0.5。)

【讨论】:

  • 好的,我知道 π/6 不会准确地得出 sin(th) = 0.5,但是没有其他方法可以准确地得出 sin(th) = 0.5?即使不使用 PI?感谢您的反馈
  • @dazckel:我不知道,但这重要吗? en.wikipedia.org/wiki/Niven%27s_theorem
猜你喜欢
  • 2011-07-09
  • 1970-01-01
  • 2018-08-19
  • 1970-01-01
  • 2016-04-15
  • 1970-01-01
  • 1970-01-01
  • 2013-01-09
  • 1970-01-01
相关资源
最近更新 更多