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 a dual quaternion from a transformation matrix.
static auto from(const Quaternion<T>& rotation, const Vector3<T>& translation) -> DualQuaternion<T> new in Git master
Create a dual quaternion from a rotation quaternion and a translation vector.

Constructors, destructors, conversion operators

DualQuaternion() constexpr noexcept
Default constructor.
DualQuaternion(IdentityInitT) explicit constexpr noexcept
Identity constructor.
DualQuaternion(ZeroInitT) explicit constexpr noexcept
Construct a 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 a dual quaternion from a real and a dual part.
DualQuaternion(const Dual<Vector3<T>>& vector, const Dual<T>& scalar) constexpr noexcept
Construct a dual quaternion from dual vector and scalar parts.
DualQuaternion(const Vector3<T>& vector) explicit constexpr noexcept
Construct a dual quaternion from a vector.
template<class U>
DualQuaternion(const DualQuaternion<U>& other) explicit constexpr noexcept
Construct a dual quaternion from another of different type.
template<class U, class = decltype(Implementation::DualQuaternionConverter<T, U>::from(std::declval<U>()))>
DualQuaternion(const U& other) explicit constexpr
Construct a dual quaternion from external representation.
DualQuaternion(const Dual<Quaternion<T>>& other) constexpr noexcept
Copy constructor.
template<class U, class = decltype(Implementation::DualQuaternionConverter<T, U>::to(std::declval<DualQuaternion<T>>()))>
operator U() const explicit constexpr
Convert the 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 a dual quaternion from a 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 a dual quaternion from a rotation quaternion and a 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 a dual quaternion from a real and a 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 a 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 a dual quaternion from a 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 a 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.