Safe Haskell | None |
---|

The unit sphere in the space of quaternions has the group structure
SU(2) coming from the quaternion multiplication, which is the double
cover of the group SO(3) of rotations in R^3. Thus, unit quaternions can
be used to encode rotations in 3D, which is a more compact encoding
(4 floats) than a 3x3 matrix; however, there are *two* quaternions
corresponding to each rotation.

See http://en.wikipedia.org/wiki/Quaternion and http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation for more information.

- newtype Quaternion a = Q (Vec4 a)
- newtype UnitQuaternion a = U (Vec4 a)
- type Q = Quaternion
- type U = UnitQuaternion
- unitQ :: Num a => Q a
- zeroQ :: Num a => Q a
- multQ :: Num a => Q a -> Q a -> Q a
- negQ :: Floating a => Q a -> Q a
- normalizeQ :: Floating a => Q a -> Q a
- invQ :: Floating a => Q a -> Q a
- fromQ :: Q a -> Vec4 a
- toQ :: Vec4 a -> Q a
- unitU :: Num a => U a
- multU :: Num a => U a -> U a -> U a
- negU :: Floating a => U a -> U a
- normalizeU :: Floating a => U a -> U a
- invU :: Num a => U a -> U a
- fromU :: Num a => U a -> Vec4 a
- fromU' :: Floating a => U a -> Normal4 a
- mkU :: Floating a => Vec4 a -> U a
- toU :: Floating a => Normal4 a -> U a
- unsafeToU :: Num a => Vec4 a -> U a
- actU :: Num a => U a -> Vec3 a -> Vec3 a
- actU' :: Floating a => U a -> Normal3 a -> Normal3 a
- rotU :: Floating a => Vec3 a -> a -> U a
- rotU' :: Floating a => Normal3 a -> a -> U a
- longSlerpU :: Floating a => a -> U a -> U a -> U a
- slerpU :: (Floating a, Ord a) => a -> U a -> U a -> U a
- rightOrthoU :: Floating a => U a -> Ortho3 a
- leftOrthoU :: Floating a => U a -> Ortho3 a

# types

newtype Quaternion a Source

The type for quaternions.

Typeable1 Quaternion | |

Floating a => DotProd a Quaternion | |

Floating a => Vector a Quaternion | |

Floating a => UnitVector a Quaternion UnitQuaternion | |

Floating a => Interpolate a (Quaternion a) | |

Read a => Read (Quaternion a) | |

Show a => Show (Quaternion a) | |

(Floating a, Storable a) => Storable (Quaternion a) | |

(Floating a, Random a) => Random (Quaternion a) | |

Num a => MultSemiGroup (Quaternion a) | |

Floating a => AbelianGroup (Quaternion a) |

newtype UnitQuaternion a Source

The type for unit quaternions.

Typeable1 UnitQuaternion | |

Floating a => DotProd a UnitQuaternion | |

Floating a => UnitVector a Quaternion UnitQuaternion | |

Read a => Read (UnitQuaternion a) | |

Show a => Show (UnitQuaternion a) | |

(Floating a, Storable a) => Storable (UnitQuaternion a) | |

(Floating a, Ord a, Random a) => Random (UnitQuaternion a) | |

Floating a => MultSemiGroup (UnitQuaternion a) | |

Num a => LeftModule (UnitQuaternion a) (Vec3 a) |

type Q = QuaternionSource

An abbreviated type synonym for quaternions

type U = UnitQuaternionSource

An abbreviated type synonym for unit quaternions

# general quaternions

normalizeQ :: Floating a => Q a -> Q aSource

# unit quaternions

normalizeU :: Floating a => U a -> U aSource

This is no-op, up to numerical imprecision. However, if you multiply together a large number of unit quaternions, it may be a good idea to normalize the end result.

# unit quaternions as rotations

actU :: Num a => U a -> Vec3 a -> Vec3 aSource

The *left* action of unit quaternions on 3D vectors.
That is,

actU q1 $ actU q2 v == actU (q1 `multU` q2) v

rotU :: Floating a => Vec3 a -> a -> U aSource

The quaternion to encode rotation around an axis. Please note
that quaternions act on the *left*, that is

rotU axis1 angl1 *. rotU axis2 angl2 *. v == (rotU axis1 angl1 .*. rotU axis2 angl2) *. v

longSlerpU :: Floating a => a -> U a -> U a -> U aSource

Interpolation of unit quaternions. Note that when applied to rotations,
this may be not what you want, since it is possible that the shortest path
in the space of unit quaternions is not the shortest path in the space of
rotations; see `slerpU`

!

slerpU :: (Floating a, Ord a) => a -> U a -> U a -> U aSource

This is shortest path interpolation in the space of rotations; however
this is achieved by possibly flipping the first endpoint in the space of
quaternions. Thus `slerpU 0.001 q1 q2`

may be very far from `q1`

(and very
close to `negU q1`

) in the space of quaternions (but they are very close
in the space of rotations).

rightOrthoU :: Floating a => U a -> Ortho3 aSource

Makes a rotation matrix (to be multiplied with on the *right*) out of a unit quaternion:

v .* rightOrthoU (rotU axis angl) == v .* rotMatrix3 axis angl

Please note that while these matrices act on the *right*, quaternions act on the *left*; thus

rightOrthoU q1 .*. rightOrthoU q2 == rightOrthoU (q2 .*. q1)

leftOrthoU :: Floating a => U a -> Ortho3 aSource

Makes a rotation matrix (to be multiplied with on the *left*) out of a unit quaternion.

leftOrthoU (rotU axis angl) *. v == v .* rotMatrix3 axis angl