2017-06-05 14 views
1

Ich versuche eine Matrix in eine 3x3-Rotationsmatrix, einen Skalierungsvektor und einen Translationsvektor unter Verwendung von Haskell zu zerlegen. Ich verwende die Matrix aus dem linear Paket. Leider exportiert das Paket nur Funktionen, um eine Matrix aus Skalierung, Rotation und Translation zu erstellen und nicht aus einer Matrix zu extrahieren. Daher habe ich beschlossen, eine Funktion zu schreiben, um es selbst zu machen.Zerlegung einer Matrix in Skalierung, Rotation und Translation mit Haskell

Auch wenn ich Matrizen ohne Skalierung verwende, gibt meine Funktion einen anderen Skalierungsvektor als V3 1.0 1.0 1.0 zurück.

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) 

Hier ist, wie ich diese Funktion im GHCI leite:

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

Und das ist, was ich als das Ergebnis erhalten (formatiert, so dass Sie es leichter lesen):

(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) 

Vielen Dank im Voraus.

Antwort

2

Ihre decomposeMatrix Funktion scheint in Ordnung zu sein (außer die Rotationsmatrix ist von dem was Sie wollen transponiert).

Das große Problem ist Ihr Testfall: die Quaternion, die Sie verwenden (LA.Quarternion 1 (LA.V3 1 2 3) ist keine Einheit Quaternion, so LA.mkTransformation baut keine reine Rotation. Es baut eine Kombination aus Rotation und Skalierung auf. Versuchen das Beispiel:

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

die LA.axisAngle verwendet eine Einheit Quaternion bauen eine reine Rotation von einem Vektor und Winkel darstellt, und es wird wie erwartet.

Verwandte Themen