c - 是否有一个用于 3d 旋转且舍入误差最小的简单 C 库?

标签 c algorithm rotation linear-algebra

在 3d 中简单地实现 vector 旋转会产生巨大的舍入误差,尤其是在围绕不同轴执行多次旋转时。 simple 1-axis example显示了基本问题。我有一个代码,我在其中围绕 x 轴和 y 轴旋转点几次。在某些情况下,我在小数点后第二位出现错误(例如, vector 的长度在旋转前为 1,旋转后为 0.9)。我对相对错误很满意 < 1e-5 .

void Rotate_x(double data[3], double agl) {
    agl *= M_PI/180.0;
    double c = cos(agl);    double s = sin(agl);
    double tmp_y = c*data[1] - s*data[2];
    double tmp_z = s*data[1] + c*data[2];
    data[1] = tmp_y;        data[2] = tmp_z;
}

有人能给我指点一个库或一些代码,它能以最小的误差围绕坐标轴旋转点吗?

我发现的所有东西都是臃肿的线性代数库,对我的目的来说太过分了。

编辑: 我去了long double精度和 combined rotations以改善错误。对于 double ,我并不完全满意(1e-3 最坏情况下的相对误差)。这是最简单的解决方案,它工作正常。仍然不介意一个不错的库,它可以准确地进行常规 double 旋转。

最佳答案

  1. 更好的精度变量是不够的

    • 您需要更精确的 sin、cos 函数来提高准确性
    • 所以通过泰勒级数展开自己的函数
    • 并使用它...然后比较结果
    • 并增加多项式阶数,直到准确率停止上升或再次开始下降
  2. 如果您对同一数据应用许多转换

    • 然后创建累积变换矩阵
    • 然后检查它是否正交/正交
    • 如果没有则修复(使用叉积)
    • 我将其用于 3D 渲染对象矩阵(随着时间的推移有许多累积变换)
    • 但在您的情况下,这也会增加错误(如果在校正过程中选择了错误的轴顺序)
    • 这更适合确保对象随着时间的推移保持相同的大小/形状......

[edit1] 测试

  • 我把你的代码放到 Borland BDS2006 上编译成 win32 应用程序
  • 结果是:
  • 原始:(0.0000000000000000000,1.0000000000000000000,0.0000000000000000000)
  • 旋转:(0.0000000000000000000,0.9999999999999998890,-0.0000000000000000273)
  • 也不要忘记如果你的罪过,因为采用弧度(对于 C/C++ 通常)然后将其添加到 Rotate
  • agl*=M_PI/180.0;
  • 您使用的是什么编译器/平台?

这是我的旋转的样子

void Rotate(double *data,double agl)
    {
    agl*=M_PI/180.0;
    double c = cos(agl);    double s = sin(agl);
    double tmp_y = c*data[1] - s*data[2];
    double tmp_z = s*data[1] + c*data[2];
    data[1] = tmp_y; data[2] = tmp_z;
    }

[edit2] 32/64 位比较

[double] //64bit floating point
(0.0000000000000000000,1.0000000000000000000,0.0000000000000000000)
(0.0000000000000000000,0.9999999999999998890,-0.0000000000000000273)
[float] //32bit floating point
(0.0000000000000000000,1.0000000000000000000,0.0000000000000000000)
(0.0000000000000000000,0.9999999403953552246,-0.0000000146747787255)

关于c - 是否有一个用于 3d 旋转且舍入误差最小的简单 C 库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24756354/

相关文章:

algorithm - 从复杂性类别计算时间

c++ - 简单程序生成二维城市的算法?

java - java中如何让相机朝它所面对的方向移动?

c - 将 bool 数组的最后一个元素设置为位字段中的最高有效位

c - 如何使用 -std=gnu99 编译 Linux 内核模块?

c++ - 如何使用 win32 从多线程上下文初始化线程原语?

algorithm - 二分查找运行时间上限 : Recurrence Relation

c - 如何设计一个函数来识别 "+IPD,"何时从UART到达?

ios - Spritekit 约束 zRotation

ios - UITableView 在旋转时自动布局调整大小