easytensor-0.3.1.0: src/Numeric/Quaternion/Class.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
module Numeric.Quaternion.Class
( Quaternion (..)
) where
import Numeric.Matrix (Matrix)
import Numeric.Vector (Vector)
-- | Quaternion operations
class Quaternion t where
-- | Quaternion data type. The ordering of coordinates is @x y z w@,
-- where @w@ is an argument, and @x y z@ are components of a 3D vector
data Quater t
-- | Set the quaternion in format (x,y,z,w)
packQ :: t -> t -> t -> t -> Quater t
-- | Get the values of the quaternion in format (x,y,z,w)
unpackQ :: Quater t -> (t,t,t,t)
-- | Set the quaternion from 3D axis vector and argument
fromVecNum :: Vector t 3 -> t -> Quater t
-- | Set the quaternion from 4D vector in format (x,y,z,w)
fromVec4 :: Vector t 4 -> Quater t
-- | Transform the quaternion to 4D vector in format (x,y,z,w)
toVec4 :: Quater t -> Vector t 4
-- | Get scalar square of the quaternion.
--
-- >> realToFrac (square q) == q * conjugate q
square :: Quater t -> t
-- | Imagine part of quaternion (orientation vector)
im :: Quater t -> Quater t
-- | Real part of the quaternion
re :: Quater t -> Quater t
-- | Get imagenery 3D vector of the quaternion
imVec :: Quater t -> Vector t 3
-- | Real part of the quaternion into number
taker :: Quater t -> t
-- | i-th component
takei :: Quater t -> t
-- | j-th component
takej :: Quater t -> t
-- | k-th component
takek :: Quater t -> t
-- | Conjugate quaternion (negate imaginary part)
conjugate :: Quater t -> Quater t
-- | Rotates and scales vector in 3D using quaternion.
-- Let @q = (cos (a\/2), sin (a\/2) * v)@; then the rotation angle is @a@, and the axis of rotation is @v@.
-- Scaling is proportional to @|v|^2@.
--
-- >>> rotScale q x == q * x * (conjugate q)
rotScale :: Quater t -> Vector t 3 -> Vector t 3
-- | Creates a quaternion @q@ from two vectors @a@ and @b@.
-- @rotScale q a == b@
getRotScale :: Vector t 3 -> Vector t 3 -> Quater t
-- | Creates a rotation versor from an axis vector and an angle in radians.
-- Result is always a unit quaternion (versor).
-- If the argument vector is zero, then result is a real unit quaternion.
axisRotation :: Vector t 3 -> t -> Quater t
-- | Quaternion rotation angle
--
-- >>> q /= 0 ==> axisRotation (imVec q) (qArg q) == signum q
qArg :: Quater t -> t
-- | Create a quaternion from a rotation matrix.
-- Note, that rotations of `q` and `-q` are equivalent, there result of this function may be
-- ambiguious. I decided to force its real part be positive:
--
-- >>> taker (fromMatrix33 m) >= 0
fromMatrix33 :: Matrix t 3 3 -> Quater t
-- | Create a quaternion from a homogenious coordinates trasform matrix.
-- Ignores matrix translation transform.
-- Note, that rotations of `q` and `-q` are equivalent, there result of this function may be
-- ambiguious. I decided to force its real part be positive:
--
-- >>> taker (fromMatrix44 m) >= 0
fromMatrix44 :: Matrix t 4 4 -> Quater t
-- | Create a rotation matrix from a quaternion.
-- Note, that rotations of `q` and `-q` are equivalent, so the following property holds:
--
-- >>> toMatrix33 q == toMatrix33 (-q)
toMatrix33 :: Quater t -> Matrix t 3 3
-- | Create a homogenious coordinates trasform matrix from a quaternion.
-- Translation of the output matrix is zero.
-- Note, that rotations of `q` and `-q` are equivalent, so the following property holds:
--
-- >>> toMatrix44 q == toMatrix44 (-q)
toMatrix44 :: Quater t -> Matrix t 4 4