提问人:Dazckel 提问时间:12/23/2021 最后编辑:zkozaDazckel 更新时间:1/1/2022 访问量:89
通过旋转计算球体的算法有加法误差
Algorithm to calculate sphere by revolution has addition error
问:
我正在尝试通过旋转(旋转)生成一个球体。 我的想法是以相等的步长围绕轴旋转一个点,直到 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 是球体半径,或从原点到球体上任何点的距离。
- a 和 b 是坐标(取决于球体旋转的轴,一个坐标不会改变)
- NROT 为 1.0/NR
- 顶点是一个顶点数组
- nv 保存顶点数
问题
由于我使用 ,球体生成涉及一个微小的数值误差,最终会导致运行时错误。情况是最后一个顶点应该正好在初始轴上,但它的坐标不是如图所示:它们应该是 0,-5,0 这是一个小错误,但足以使我的函数(检查一个点是否在轴上)失败。
我可以修复它,使顶点坐标四舍五入,但这对我来说就像一项拙劣的工作。M_PI
谁能告诉我另一种生成旋转角度的方法,这样我就可以毫无错误地生成球体?
谢谢。
答:
0赞
user1196549
12/23/2021
#1
一个循环,比如
for (i= 0, th= 0; i <= n; i++, th+= π/n)
s= sin(th);
不能保证 will 的最终值是准确的,我们甚至在数值上确定吗?th
π
sin(π) = 0
使用更安全
for (i= 0, th= 0; i <= n; i++, th+= π/n)
s= i < n ? sin(th) : 0;
(同样,不要指望经过的循环会完全产生。π/6
sin(th) = 0.5
评论
0赞
Dazckel
12/23/2021
好的,我知道 π/6 不会产生确切的 sin(th) = 0.5,但是没有其他方法可以精确地获得 sin(th) = 0.5?即使不使用 PI?感谢您的反馈
0赞
12/23/2021
@dazckel:我不知道,但这重要吗?en.wikipedia.org/wiki/Niven%27s_theorem
上一个:OpenGL 改变法线
评论
sinpi