如何从随机旋转中将变换应用于矩阵

时间:2017-07-06 18:39:58

标签: c# matrix 3d

我的对象是在软件中的不同位置逐步接收4个转换。我们使用CAD引擎库,因此我有自定义对象进行转换。

情况

我需要从一个物体平移和旋转的矩阵中恢复,这样我就可以在旋转后创建一个新的矩阵。

守则(样本)

// create a transformation object, very simple 1 translation and 3 rotations
var  t = new Translation(10, 15, 20)
         * new Rotation(10d.ToRadian(), Vector3D.AxisX)
         * new Rotation(10d.ToRadian(), Vector3D.AxisY)
         * new Rotation(10d.ToRadian(), Vector3D.AxisZ);

// convert to the windows Matrix3D
var m1 = ToWindowsMatrix(t);

// decompose the matrix to get one random possibility of combinaison of rotation x, y and Z to obtain the same result
var rx = Math.Atan2(m1.M32, m1.M33).ToDegree();
var ry = Math.Atan2(-m1.M31, Math.Sqrt(Math.Pow(m1.M32, 2) + Math.Pow(m1.M33, 2))).ToDegree();
var rz = Math.Atan2(m1.M21, m1.M11).ToDegree();

Source for formula to get rotation x,y and z:

// create a transformation object, in the same order, hardcoded translate but use the computed equivalent rotation x,y and z
var  t2 = new Translation(10, 15, 20)
         * new Rotation(rx.ToRadian(), Vector3D.AxisX)
         * new Rotation(ry.ToRadian(), Vector3D.AxisY)
         * new Rotation(rz.ToRadian(), Vector3D.AxisZ);

// convert to the windows Matrix3D
var m2 = ToWindowsMatrix(t2);

问题

如果我拍摄一个3d对象并应用t2的变换,则与t1给出的对象的旋转相比完全偏离。

我绝对需要获得分解值,因为整个系统使用6个参数(原点x,y,z和旋转x,y,z)显示对象,然后创建一个单位矩阵并应用平移和3旋转。 / p>

我已经工作了大约7个小时,我发现如果我只在t1上进行一次轮换,即"旋转X 90"并且在t2上我仍然使用旋转DO匹配的计算值应用所有旋转。所以我觉得转型的顺序需要按照特定的顺序,但我不能改变它。所以这意味着我需要获得旋转x,y和z,以便通过应用Translate * RotX * RotY * RotZ来匹配。

我可能错过了什么?我也发现了一些mathlab样本,但到目前为止公式都是一样的。

1 个答案:

答案 0 :(得分:0)

一段时间后想出如何获得矩阵的XYZ旋转。问题是欧拉角在ZYX旋转中返回。需要执行更多操作才能从中提取XYZ。

public static double[] GetXYZRotation(this Matrix3D matrix)
    {
        // get the euler angles
        var eulerX = Math.Atan2(matrix.M32, matrix.M33).ToDegree();
        var eulerY = Math.Atan2(-matrix.M31, Math.Sqrt(Math.Pow(matrix.M32, 2) + Math.Pow(matrix.M33, 2))).ToDegree();
        var eulerZ = Math.Atan2(matrix.M21, matrix.M11).ToDegree();

        // create transformation of the euler angle to get a matrix. euler rotation is ZYX
        var eulerMatrix = (new Translation(matrix.OffsetX,matrix.OffsetY,matrix.OffsetZ)
              * new Rotation(eulerZ.ToRadian(), Vector3D.AxisZ)
              * new Rotation(eulerY.ToRadian(), Vector3D.AxisY)
              * new Rotation(eulerX.ToRadian(), Vector3D.AxisX)).ToWindowsMatrix();

        // get the Alpha Beta and Gamma of the euler matrix
        var beta = Math.Atan2(eulerMatrix.M13, Math.Sqrt(Math.Pow(eulerMatrix.M11, 2d) + Math.Pow(-eulerMatrix.M12, 2d)));
        var alpha = Math.Atan2(-(eulerMatrix.M23 / Math.Cos(beta)), eulerMatrix.M33 / Math.Cos(beta));
        var gamma = Math.Atan2(-(eulerMatrix.M12 / Math.Cos(beta)), eulerMatrix.M11 / Math.Cos(beta));

        // get the XYZ rotation per euler computed alpha beta gamma
        var rotationX = alpha.ToDegree();
        var rotationY = beta.ToDegree();
        var rotationZ = gamma.ToDegree();

        return new[] { rotationX, rotationY, rotationZ };
    }

所以我需要计算以相反顺序应用欧拉角的矩阵:Z然后是Y然后是X并从那里计算出α,β和Gamma,它们可以检索XYZ旋转值