template<class T>
Magnum::Math::DualQuaternion class

Dual quaternion.

Template parameters
T Underlying data type

Represents 3D rotation and translation. Usually denoted as the following in equations, with $ q_0 $ being the real() part and $ q_\epsilon $ the dual() part:

\[ \hat q = q_0 + \epsilon q_\epsilon \]

See Dual and Quaternion for further notation description and 2D and 3D transformations for a brief introduction.

Base classes

template<class T>
class Dual<Quaternion<T>>
Dual number.

Public types

using Type = T
Underlying data type.

Public static functions

static auto rotation(Rad<T> angle, const Vector3<T>& normalizedAxis) -> DualQuaternion<T>
Rotation dual quaternion.
static auto translation(const Vector3<T>& vector) -> DualQuaternion<T>
Translation dual quaternion.
static auto fromMatrix(const Matrix4<T>& matrix) -> DualQuaternion<T>
Create dual quaternion from transformation matrix.
static auto from(const Quaternion<T>& rotation, const Vector3<T>& translation) -> DualQuaternion<T> new in Git master
Create dual quaternion from rotation quaternion and translation vector.

Constructors, destructors, conversion operators

DualQuaternion() constexpr noexcept
Default constructor.
DualQuaternion(IdentityInitT) explicit constexpr noexcept
Identity constructor.
DualQuaternion(ZeroInitT) explicit constexpr noexcept
Construct zero-initialized dual quaternion.
DualQuaternion(Magnum::NoInitT) explicit noexcept
Construct without initializing the contents.
DualQuaternion(const Quaternion<T>& real, const Quaternion<T>& dual = Quaternion<T>({}, T(0))) constexpr noexcept
Construct dual quaternion from real and dual part.
DualQuaternion(const Dual<Vector3<T>>& vector, const Dual<T>& scalar) constexpr noexcept
Construct dual quaternion from dual vector and scalar parts.
DualQuaternion(const Vector3<T>& vector) explicit constexpr noexcept
Construct dual quaternion from vector.
template<class U>
DualQuaternion(const DualQuaternion<U>& other) explicit constexpr noexcept
Construct dual quaternion from another of different type.
template<class U, class V = decltype(Implementation::DualQuaternionConverter<T, U>::from(std::declval<U>()))>
DualQuaternion(const U& other) explicit constexpr
Construct dual quaternion from external representation.
DualQuaternion(const Dual<Quaternion<T>>& other) constexpr noexcept
Copy constructor.
template<class U, class V = decltype(Implementation::DualQuaternionConverter<T, U>::to(std::declval<DualQuaternion<T>>()))>
operator U() const explicit constexpr
Convert dual quaternion to external representation.

Public functions

auto data() -> T*
Raw data.
auto data() const -> const T*
auto isNormalized() const -> bool
Whether the dual quaternion is normalized.
auto rotation() const -> Quaternion<T> constexpr
Rotation part of unit dual quaternion.
auto translation() const -> Vector3<T>
Translation part of unit dual quaternion.
auto toMatrix() const -> Matrix4<T>
Convert dual quaternion to transformation matrix.
auto quaternionConjugated() const -> DualQuaternion<T>
Quaternion-conjugated dual quaternion.
auto dualConjugated() const -> DualQuaternion<T>
Dual-conjugated dual quaternion.
auto conjugated() const -> DualQuaternion<T>
Conjugated dual quaternion.
auto lengthSquared() const -> Dual<T>
Dual quaternion length squared.
auto length() const -> Dual<T>
Dual quaternion length.
auto normalized() const -> DualQuaternion<T>
Normalized dual quaternion (of unit length)
auto inverted() const -> DualQuaternion<T>
Inverted dual quaternion.
auto invertedNormalized() const -> DualQuaternion<T>
Inverted normalized dual quaternion.
auto transformVector(const Vector3<T>& vector) const -> Vector3<T> new in 2020.06
Rotate a vector with a dual quaternion.
auto transformVectorNormalized(const Vector3<T>& vector) const -> Vector3<T> new in 2020.06
Rotate a vector with a normalized dual quaternion.
auto transformPoint(const Vector3<T>& vector) const -> Vector3<T>
Rotate and translate point with dual quaternion.
auto transformPointNormalized(const Vector3<T>& vector) const -> Vector3<T>
Rotate and translate point with normalized dual quaternion.

Function documentation

template<class T>
static DualQuaternion<T> Magnum::Math::DualQuaternion<T>::rotation(Rad<T> angle, const Vector3<T>& normalizedAxis)

Rotation dual quaternion.

Parameters
angle Rotation angle (counterclockwise)
normalizedAxis Normalized rotation axis

Expects that the rotation axis is normalized.

\[ \hat q = [\boldsymbol a \cdot \sin(\frac{\theta}{2}), \cos(\frac{\theta}{2})] + \epsilon [\boldsymbol 0, 0] \]

For creating a dual quaternion from a rotation Quaternion, use the implicit conversion provided by DualQuaternion(const Quaternion<T>&, const Quaternion<T>&).

template<class T>
static DualQuaternion<T> Magnum::Math::DualQuaternion<T>::translation(const Vector3<T>& vector)

Translation dual quaternion.

Parameters
vector Translation vector
\[ \hat q = [\boldsymbol 0, 1] + \epsilon [\frac{\boldsymbol v}{2}, 0] \]

template<class T>
static DualQuaternion<T> Magnum::Math::DualQuaternion<T>::fromMatrix(const Matrix4<T>& matrix)

Create dual quaternion from transformation matrix.

Expects that the matrix represents rigid transformation.

template<class T>
static DualQuaternion<T> Magnum::Math::DualQuaternion<T>::from(const Quaternion<T>& rotation, const Vector3<T>& translation) new in Git master

Create dual quaternion from rotation quaternion and translation vector.

\[ \hat q = r + \epsilon [\frac{\boldsymbol t}{2}, 0] r \]

template<class T>
Magnum::Math::DualQuaternion<T>::DualQuaternion() constexpr noexcept

Default constructor.

Equivalent to DualQuaternion(IdentityInitT).

template<class T>
Magnum::Math::DualQuaternion<T>::DualQuaternion(IdentityInitT) explicit constexpr noexcept

Identity constructor.

Creates unit dual quaternion.

\[ \hat q = [\boldsymbol 0, 1] + \epsilon [\boldsymbol 0, 0] \]

template<class T>
Magnum::Math::DualQuaternion<T>::DualQuaternion(const Quaternion<T>& real, const Quaternion<T>& dual = Quaternion<T>({}, T(0))) constexpr noexcept

Construct dual quaternion from real and dual part.

\[ \hat q = q_0 + \epsilon q_\epsilon \]

This constructor can be also used to implicitly convert a rotation quaternion to a rotation dual quaternion.

template<class T>
Magnum::Math::DualQuaternion<T>::DualQuaternion(const Dual<Vector3<T>>& vector, const Dual<T>& scalar) constexpr noexcept

Construct dual quaternion from dual vector and scalar parts.

\[ \hat q = [\hat{\boldsymbol v}, \hat s] = [\boldsymbol v_0, s_0] + \epsilon [\boldsymbol v_\epsilon, s_\epsilon] \]

template<class T>
Magnum::Math::DualQuaternion<T>::DualQuaternion(const Vector3<T>& vector) explicit constexpr noexcept

Construct dual quaternion from vector.

To be used in transformations later.

\[ \hat q = [\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0] \]

template<class T> template<class U>
Magnum::Math::DualQuaternion<T>::DualQuaternion(const DualQuaternion<U>& other) explicit constexpr noexcept

Construct dual quaternion from another of different type.

Performs only default casting on the values, no rounding or anything else.

template<class T>
T* Magnum::Math::DualQuaternion<T>::data()

Raw data.

Contrary to what Doxygen shows, returns reference to an one-dimensional fixed-size array of eight elements, i.e. T(&)[8].

template<class T>
const T* Magnum::Math::DualQuaternion<T>::data() const

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<class T>
bool Magnum::Math::DualQuaternion<T>::isNormalized() const

Whether the dual quaternion is normalized.

Dual quaternion is normalized if it has unit length:

\[ |\hat q|^2 = |\hat q| = 1 + \epsilon 0 \]

template<class T>
Quaternion<T> Magnum::Math::DualQuaternion<T>::rotation() const constexpr

Rotation part of unit dual quaternion.

template<class T>
Vector3<T> Magnum::Math::DualQuaternion<T>::translation() const

Translation part of unit dual quaternion.

\[ \boldsymbol a = 2 (q_\epsilon q_0^*)_V \]

template<class T>
Matrix4<T> Magnum::Math::DualQuaternion<T>::toMatrix() const

Convert dual quaternion to transformation matrix.

template<class T>
DualQuaternion<T> Magnum::Math::DualQuaternion<T>::quaternionConjugated() const

Quaternion-conjugated dual quaternion.

\[ \hat q^* = q_0^* + q_\epsilon^* \]

template<class T>
DualQuaternion<T> Magnum::Math::DualQuaternion<T>::dualConjugated() const

Dual-conjugated dual quaternion.

\[ \overline{\hat q} = q_0 - \epsilon q_\epsilon \]

template<class T>
DualQuaternion<T> Magnum::Math::DualQuaternion<T>::conjugated() const

Conjugated dual quaternion.

Both quaternion and dual conjugation.

\[ \overline{\hat q^*} = q_0^* - \epsilon q_\epsilon^* = q_0^* + \epsilon [\boldsymbol q_{V \epsilon}, -q_{S \epsilon}] \]

template<class T>
Dual<T> Magnum::Math::DualQuaternion<T>::lengthSquared() const

Dual quaternion length squared.

Should be used instead of length() for comparing dual quaternion length with other values, because it doesn't compute the square root.

\[ |\hat q|^2 = \sqrt{\hat q^* \hat q}^2 = q_0 \cdot q_0 + \epsilon 2 (q_0 \cdot q_\epsilon) \]

template<class T>
Dual<T> Magnum::Math::DualQuaternion<T>::length() const

Dual quaternion length.

See lengthSquared() which is faster for comparing length with other values.

\[ |\hat q| = \sqrt{\hat q^* \hat q} = |q_0| + \epsilon \frac{q_0 \cdot q_\epsilon}{|q_0|} \]

template<class T>
DualQuaternion<T> Magnum::Math::DualQuaternion<T>::normalized() const

Normalized dual quaternion (of unit length)

template<class T>
DualQuaternion<T> Magnum::Math::DualQuaternion<T>::inverted() const

Inverted dual quaternion.

See invertedNormalized() which is faster for normalized dual quaternions.

\[ \hat q^{-1} = \frac{\hat q^*}{|\hat q|^2} \]

template<class T>
DualQuaternion<T> Magnum::Math::DualQuaternion<T>::invertedNormalized() const

Inverted normalized dual quaternion.

Equivalent to quaternionConjugated(). Expects that the quaternion is normalized.

\[ \hat q^{-1} = \frac{\hat q^*}{|\hat q|^2} = \hat q^* \]

template<class T>
Vector3<T> Magnum::Math::DualQuaternion<T>::transformVector(const Vector3<T>& vector) const new in 2020.06

Rotate a vector with a dual quaternion.

Calls Quaternion::transformVector() on the real() part, see its documentation for more information.

template<class T>
Vector3<T> Magnum::Math::DualQuaternion<T>::transformVectorNormalized(const Vector3<T>& vector) const new in 2020.06

Rotate a vector with a normalized dual quaternion.

Calls Quaternion::transformVectorNormalized() on the real() part, see its documentation for more information.

template<class T>
Vector3<T> Magnum::Math::DualQuaternion<T>::transformPoint(const Vector3<T>& vector) const

Rotate and translate point with dual quaternion.

See transformPointNormalized(), which is faster for normalized dual quaternions.

\[ v' = \hat q v \overline{\hat q^{-1}} = \hat q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^{-1}} \]

template<class T>
Vector3<T> Magnum::Math::DualQuaternion<T>::transformPointNormalized(const Vector3<T>& vector) const

Rotate and translate point with normalized dual quaternion.

Faster alternative to transformPoint(), expects that the dual quaternion is normalized.

\[ v' = \hat q v \overline{\hat q^{-1}} = \hat q v \overline{\hat q^*} = \hat q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^*} \]

template<class T> template<class T>
DualQuaternion<T> sclerp(const DualQuaternion<T>& normalizedA, const DualQuaternion<T>& normalizedB, const T t)

Screw linear interpolation of two dual quaternions.

Parameters
normalizedA First dual quaternion
normalizedB Second dual quaternion
t Interpolation phase (from range $ [0; 1] $ )

Expects that both dual quaternions are normalized. If the real parts are the same or one is a negation of the other, returns the DualQuaternion::rotation() (real) part combined with interpolated DualQuaternion::translation():

\[ \begin{array}{rcl} d & = & q_{A_0} \cdot q_{B_0} \\[5pt] {\hat q}_{ScLERP} & = & 2 \left[(1 - t)(q_{A_\epsilon} q_{A_0}^*)_V + t (q_{B_\epsilon} q_{B_0}^*)_V \right] q_A, ~ {\color{m-primary} \text{if} ~ d \ge 1} \end{array} \]

otherwise, the interpolation is performed as:

\[ \begin{array}{rcl} l + \epsilon m & = & \hat q_A^* \hat q_B \\[5pt] \frac{\hat a} 2 & = & \arccos \left( l_S \right) - \epsilon m_S \frac 1 {|\boldsymbol{l}_V|} \\[5pt] \hat {\boldsymbol n} & = & \boldsymbol n_0 + \epsilon \boldsymbol n_\epsilon, ~~~~~~~~ \boldsymbol n_0 = \boldsymbol{l}_V \frac 1 {|\boldsymbol{l}_V|}, ~~~~~~~~ \boldsymbol n_\epsilon = \left(\boldsymbol{m}_V - {\boldsymbol n}_0 \frac {a_\epsilon} 2 l_S \right)\frac 1 {|\boldsymbol{l}_V|} \\[5pt] {\hat q}_{ScLERP} & = & \hat q_A (\hat q_A^* \hat q_B)^t = \hat q_A \left[ \hat {\boldsymbol n} \sin \left( t \frac {\hat a} 2 \right), \cos \left( t \frac {\hat a} 2 \right) \right] \end{array} \]

Note that this function does not check for shortest path interpolation, see sclerpShortestPath() for an alternative.

template<class T> template<class T>
DualQuaternion<T> sclerpShortestPath(const DualQuaternion<T>& normalizedA, const DualQuaternion<T>& normalizedB, const T t)

Screw linear shortest-path interpolation of two dual quaternions.

Parameters
normalizedA First dual quaternion
normalizedB Second dual quaternion
t Interpolation phase (from range $ [0; 1] $ )

Unlike sclerp(const DualQuaternion<T>&, const DualQuaternion<T>&, T) this function interpolates on the shortest path. Expects that both dual quaternions are normalized. If the real parts are the same or one is a negation of the other, returns the DualQuaternion::rotation() (real) part combined with interpolated DualQuaternion::translation():

\[ \begin{array}{rcl} d & = & q_{A_0} \cdot q_{B_0} \\[5pt] {\hat q}_{ScLERP} & = & 2 \left((1 - t)(q_{A_\epsilon} q_{A_0}^*)_V + t (q_{B_\epsilon} q_{B_0}^*)_V \right) (q_{A_0} + \epsilon [\boldsymbol{0}, 0]), ~ {\color{m-primary} \text{if} ~ d \ge 1} \end{array} \]

otherwise, the interpolation is performed as:

\[ \begin{array}{rcl} l + \epsilon m & = & \begin{cases} \phantom{-}\hat q_A^* \hat q_B, & d \ge 0 \\ -\hat q_A^* \hat q_B, & d < 0 \\ \end{cases} \\[15pt] \frac{\hat a} 2 & = & \arccos \left( l_S \right) - \epsilon m_S \frac 1 {|\boldsymbol{l}_V|} \\[5pt] \hat {\boldsymbol n} & = & \boldsymbol n_0 + \epsilon \boldsymbol n_\epsilon, ~~~~~~~~ \boldsymbol n_0 = \boldsymbol{l}_V \frac 1 {|\boldsymbol{l}_V|}, ~~~~~~~~ \boldsymbol n_\epsilon = \left(\boldsymbol{m}_V - {\boldsymbol n}_0 \frac {a_\epsilon} 2 l_S \right)\frac 1 {|\boldsymbol{l}_V|} \\[5pt] {\hat q}_{ScLERP} & = & \hat q_A (\hat q_A^* \hat q_B)^t = \hat q_A \left[ \hat {\boldsymbol n} \sin \left( t \frac {\hat a} 2 \right), \cos \left( t \frac {\hat a} 2 \right) \right] \end{array} \]

template<class T> template<class T>
Debug& operator<<(Debug& debug, const DualQuaternion<T>& value)

Debug output operator.