【发布时间】: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 是球体半径,或从原点到球体上任意点的距离。
- a 和 b 是坐标(取决于球体旋转的轴,一个坐标不变)
- nrot 是 1.0/nr
- 顶点是一个顶点数组
- nv 保存顶点数
问题
由于我使用M_PI,球体生成涉及一个微小的数值错误,最终会导致运行时错误。情况是最后一个顶点应该恰好在初始轴上,而不是它的坐标如下图所示:
They should be 0,-5,0
这是一个小错误,但足以使我的功能(检查点是否在轴上)失败。
我可以修复它,将顶点坐标四舍五入,但这对我来说感觉像是一项拙劣的工作。
谁能告诉我另一种生成旋转角度的方法,以便我可以毫无错误地生成球体?
谢谢。
【问题讨论】:
-
欢迎来到浮点表示和截断错误的世界。较新的假设是,在这种情况下,您可以使用比较来实现相等。考虑引入公差。
-
你的C库是否提供函数
sinpi? -
考虑对称性,只计算0
-
期望浮点计算准确是错误的。
-
为什么不迭代度数而不是弧度,然后从中计算弧度?这样,如果您的度数是一个整数,或者至少是一个可以用二进制值准确表示的数字,那么在转换为弧度时会发生唯一的错误,但在求和时不会发生错误。
标签: c++ algorithm math geometry