如何最大限度地减少绕任意轴旋转三维空间中的一个点的浮点不精确度? [英] How to minimize floating point inaccuracy in rotating a point in 3D space about an arbitrary axis?

查看:182
本文介绍了如何最大限度地减少绕任意轴旋转三维空间中的一个点的浮点不精确度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,可视化翻译和旋转的3D空间。我没有问题的主要代码,但经过几个小时的测试,我发现导致不准确的函数是任意轴上的旋转。

我的对象包含点数组,三个向量是它的局部轴。我使用这些轴的旋转功能。当我的位置在原点时,该函数运行良好,但是一旦该点被转换为原点以外,它将显示稍微错误的旋转,直到该点不在位。



我已经使用这个网站作为我的向导,请跳到页面底部在6.2处看到带有10个参数的函数。在同一页面上,有一个链接来指明流程的示例用法。我已经证实,问题在于这个应用程序的浮点不准确。

我希望旋转的采样点:(0,-9,0)
与旋转轴相交的点:(0,-10,0)
旋转轴的方向矢量:< 1,0,0>
旋转角度:2度b

对于每个循环,当前点被旋转2度,并重复20次。第一次迭代的正确Y值是-9.0006,而在我的情况下,它的值是-8.9945,并持续​​波动,直到第五次或第六次迭代,然后在这些迭代之后显示正确的值



这里是旋转函数,注意 Point 是要旋转的点, AxisPoint 是与旋转轴相交的点, AxisDirection 是平行于旋转轴的方向矢量,而是要旋转的角度量:

  private static Vector3d RotateArbitrary(Vector3d Point,Vector3d AxisPoint,Vector3d AxisDirection,double Degrees)
{
return new Vector3d(
((AxisPoint.X *(Math.Pow (AxisDirection.Y,2)+ Math.Pow(AxisDirection.Z,2)) - AxisDirection.X *(AxisPoint.Y * AxisDirection.Y + AxisPoint.Z * AxisDirection.Z - AxisDirection.X * Point.X - AxisDirection .Y * Point.Y - AxisDirection.Z * Poin (MathHelper.DegreesToRadians(Degrees)))+ Point.X * Math.Cos(MathHelper.DegreesToRadians(Degrees))+(-AxisPoint.Z * AxisDirection.Y + AxisPoint.Y * Math.Cos(MathHelper.DegreesToRadians AxisDirection.Z - AxisDirection.Z * Point.Y + AxisDirection.Y * Point.Z)* Math.Sin(MathHelper.DegreesToRadians(Degrees))),
((AxisPoint.X *(Math.Pow(AxisDirection .X,2)+ Math.Pow(AxisDirection.Z,2)) - AxisDirection.Y *(AxisPoint.X * AxisDirection.X + AxisPoint.Z * AxisDirection.Z - AxisDirection.X * Point.X - AxisDirection.Y * Point.Y - AxisDirection.Z * Point.Z))*(1 - Math.Cos(MathHelper.DegreesToRadians(Degrees)))+ Point.Y * Math.Cos(MathHelper.DegreesToRadians(Degrees))+(AxisPoint。 Z * AxisDirection.X - AxisPoint.X * AxisDirection.Z + AxisDirection.Z * Point.X - AxisDirection.X * Point.Z)* Math.Sin(MathHelper.DegreesToRadians(Degrees))),
(( AxisPoint.X *(Math.Pow(AxisDirection.X,2)+ Math.Pow(AxisDirection.Y,2)) - AxisDirection.Z *(AxisPoint.X * AxisDirection.X + AxisPoi nt.Y * AxisDirection.Y - AxisDirection.X * Point.X - AxisDirection.Y * Point.Y - AxisDirection.Z * Point.Z))*(1 - Math.Cos(MathHelper.DegreesToRadians(Degrees)))+ Point.Z * Math.Cos(MathHelper.DegreesToRadians(Degrees))+(-AxisPoint.Y * AxisDirection.X + AxisPoint.X * AxisDirection.Y - AxisDirection.Y * Point.X + AxisDirection.X * Point.Y) * Math.Sin(MathHelper.DegreesToRadians(Degrees)))
);
}

我已经尝试了float和double数据类型,结果仍然是同样的,任何你可以提供的解决方案,甚至是旋转方法的改变,我都是开放的。请帮忙。

解决方案

由于我搜索了很长的网页,我终于得出了应该使用四元数的结论。使用当前的方法,我发现浮点变量的过度操作会增加循环错误。使用Quaternions更简单,更清洁。

这里是代码,如果有人感兴趣的话:

  private static Vector3 RotateArbitrary(Vector3 Point,Vector3 AxisPoint,Vector3 AxisDirection,float Radians)
{
return Vector3.Add(Vector3.Transform(Vector3.Subtract(Point,AxisPoint),Quaternion) FromAxisAngle(AxisDirection,Radians)),AxisPoint);

$ / code>

请注意,Point已经被首先转换成AxisPoint在这样,旋转就可以完成了。然后将结果转换为原始位置。


I have a program which visualizes translation and rotation on a 3D space. I have no problem with the main code but after hours of testing i found out that the function which causes inaccuracies is the rotation on arbitrary axis.

My object contains array of points, and three vectors which is its local axes. I use rotation function with these axes. The function works well when my position is at the origin, but once the point is translated to other than the origin it shows slightly wrong rotation until the point is out of place.

I have used this website as my guide, please jump to the bottom of the page at 6.2 and see the function with 10 parameters. On the same page, there's a link to a sample usage of the process. I have confirmed that the problem lies with floating-point inaccuracy with this application.

The sample point I wish to rotate: ( 0, -9, 0) The point that intersects the axis of rotation: ( 0, -10, 0) The direction vector of the axis of rotation: < 1, 0, 0> The angle of rotation: 2 degrees

For each loop, the current point is rotated by 2 degrees, and is repeated 20 times. The correct Y value for the first iteration is -9.0006, while in my case it gives -8.9945 and continuously fluctuates until the 5th or 6th iteration, then the correct value shows after those iterations.

Here's the rotation function, take note that Point is the point you wish to rotate, AxisPoint is the point that intersects the axis of rotation, AxisDirection is the direction vector parallel to the axis of rotation, and Degrees is the amount of angle to rotate:

private static Vector3d RotateArbitrary(Vector3d Point, Vector3d AxisPoint, Vector3d AxisDirection, double Degrees)
    {
        return new Vector3d(
            ((AxisPoint.X * (Math.Pow(AxisDirection.Y, 2) + Math.Pow(AxisDirection.Z, 2)) - AxisDirection.X * (AxisPoint.Y * AxisDirection.Y + AxisPoint.Z * AxisDirection.Z - AxisDirection.X * Point.X - AxisDirection.Y * Point.Y - AxisDirection.Z * Point.Z)) * (1 - Math.Cos(MathHelper.DegreesToRadians(Degrees))) + Point.X * Math.Cos(MathHelper.DegreesToRadians(Degrees)) + (-AxisPoint.Z * AxisDirection.Y + AxisPoint.Y * AxisDirection.Z - AxisDirection.Z * Point.Y + AxisDirection.Y * Point.Z) * Math.Sin(MathHelper.DegreesToRadians(Degrees))),
            ((AxisPoint.X * (Math.Pow(AxisDirection.X, 2) + Math.Pow(AxisDirection.Z, 2)) - AxisDirection.Y * (AxisPoint.X * AxisDirection.X + AxisPoint.Z * AxisDirection.Z - AxisDirection.X * Point.X - AxisDirection.Y * Point.Y - AxisDirection.Z * Point.Z)) * (1 - Math.Cos(MathHelper.DegreesToRadians(Degrees))) + Point.Y * Math.Cos(MathHelper.DegreesToRadians(Degrees)) + (AxisPoint.Z * AxisDirection.X - AxisPoint.X * AxisDirection.Z + AxisDirection.Z * Point.X - AxisDirection.X * Point.Z) * Math.Sin(MathHelper.DegreesToRadians(Degrees))),
            ((AxisPoint.X * (Math.Pow(AxisDirection.X, 2) + Math.Pow(AxisDirection.Y, 2)) - AxisDirection.Z * (AxisPoint.X * AxisDirection.X + AxisPoint.Y * AxisDirection.Y - AxisDirection.X * Point.X - AxisDirection.Y * Point.Y - AxisDirection.Z * Point.Z)) * (1 - Math.Cos(MathHelper.DegreesToRadians(Degrees))) + Point.Z * Math.Cos(MathHelper.DegreesToRadians(Degrees)) + (-AxisPoint.Y * AxisDirection.X + AxisPoint.X * AxisDirection.Y - AxisDirection.Y * Point.X + AxisDirection.X * Point.Y) * Math.Sin(MathHelper.DegreesToRadians(Degrees)))
            );
    }

I have already tried both float and double data type, the result is still the same, any solutions you can offer, even a change in method of rotation, I'm all open. Please help.

解决方案

Due to my lengthy web searches, I finally arrived to the conclusion that I should use Quaternions. Using the current method, I found out that excessive operations on floating point variables will increase round errors. Using Quaternions was simpler and cleaner.

Here's the code if anyone is interested:

private static Vector3 RotateArbitrary(Vector3 Point, Vector3 AxisPoint, Vector3 AxisDirection, float Radians)
        {
            return Vector3.Add(Vector3.Transform(Vector3.Subtract(Point, AxisPoint), Quaternion.FromAxisAngle(AxisDirection, Radians)), AxisPoint);
        }

Take note that the the Point was translated first such that the AxisPoint is at the origin, with that, rotations can be done. The result is then translated to its original position.

这篇关于如何最大限度地减少绕任意轴旋转三维空间中的一个点的浮点不精确度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆