使用haskell将矩阵分解为缩放,旋转和平移

时间:2017-06-05 14:47:21

标签: haskell matrix linear-algebra

我正在尝试使用haskell将矩阵分解为3x3旋转矩阵,缩放矢量和平移矢量。我正在使用linear包中的矩阵。遗憾的是,该软件包仅导出用于从缩放,旋转和平移制作矩阵的函数,而不是从矩阵中提取矩阵。因此,我决定编写一个函数来自己完成。

但是,即使我使用的矩阵没有缩放,我的函数也会返回V3 1.0 1.0 1.0以外的缩放矢量。

import qualified Linear.Matrix     as LA
import qualified Linear.V4         as LA
import qualified Linear.V3         as LA
import qualified Linear.Vector     as LA
import qualified Linear.Quaternion as LA

import Control.Lens hiding (deep)

...

decomposeMatrix :: LA.M44 Double -> (LA.M33 Double, LA.V3 Double, LA.V3 Double)
decomposeMatrix m = (rot, scale, trans)
    where trans = (m ^.LA.column LA._w ^. LA._xyz)
          scale = LA.V3 sx sy sz
          sx    = vecLength (m ^.(LA.column LA._x) ^. LA._xyz)
          sy    = vecLength (m ^.(LA.column LA._y) ^. LA._xyz)
          sz    = vecLength (m ^.(LA.column LA._z) ^. LA._xyz)
          rot   = LA.V3 ((m ^. (LA.column LA._x) ^.LA._xyz) LA.^/ sx)
                        ((m ^. (LA.column LA._y) ^.LA._xyz) LA.^/ sy)
                        ((m ^. (LA.column LA._z) ^.LA._xyz) LA.^/ sz)

vecLength :: LA.V3 Double -> Double
vecLength (LA.V3 a b c) = sqrt (a*a + b*b + c*c)

以下是我在ghci中运行此函数的方法:

decomposeMatrix $ LA.mkTransformation (LA.Quaternion 1 (LA.V3 1 2 3)) $ LA.V3 1 2 3

这就是我得到的结果(格式化,以便您可以更容易地阅读):

(V3 (V3 (-0.9259259259259259) 0.37037037037037035 7.407407407407407e-2)
    (V3 (-8.444006618414981e-2) (-0.8021806287494233) 0.5910804632890487) 
    (V3 0.5965499862718936 0.5965499862718936 (-0.5368949876447042)),
V3 27.0 23.68543856465402 16.76305461424021,
V3 1.0 2.0 3.0)

提前致谢。

1 个答案:

答案 0 :(得分:2)

你的decomposeMatrix函数看起来很好(除了旋转矩阵是你想要的转换)。

最大的问题是您的测试用例:您使用的四元数(LA.Quarternion 1 (LA.V3 1 2 3)不是单位四元数,因此LA.mkTransformation不能构建纯粹的旋转。它构建了旋转和缩放的组合。试试这个例子:

decomposeMatrix $ LA.mkTransformation (LA.axisAngle (LA.V3 1 2 3) 1) 
                $ LA.V3 1 2 3

使用LA.axisAngle构建一个单位四元数,表示来自矢量和角度的纯旋转,它将按预期工作。