Quaternion Manual

maxon::Quaternion is a MAXON API class used to represent quaternions and deliver standard mathematical operations. Unit quaternions, also known as versors, provide a convenient mathematical notation for representing orientations and rotations of objects in three dimensions. Compared to Euler angles they are simpler to compose and avoid the problem of gimbal lock. Compared to rotation matrices they are more compact, more numerically stable, and may be more efficient.

// This example shows how to use a quaternion to rotate a point in a left-handed coordinate system.
// define the point to rotate
const maxon::Vector point (1, 0, 0);
DiagnosticOutput(diagIDString + "start point: @", point);
// define the rotation angle
const maxon::Float rotAngle(90);
// define the rotation axis
const maxon::Vector rotAxis(0, 0, 1);
// create a quaternion representing the point
const maxon::Quaternion<maxon::Float> quaternionPointA(point, 0);
DiagnosticOutput(diagIDString + "quaternionPointA: @", quaternionPointA);
// create the quaternion represention the rotation (q)
const maxon::Float a = rotAxis.x * sin(maxon::DegToRad(rotAngle/2));
const maxon::Float b = rotAxis.y * sin(maxon::DegToRad(rotAngle/2));
const maxon::Float c = rotAxis.z * sin(maxon::DegToRad(rotAngle/2));
const maxon::Quaternion<maxon::Float> quaternion(a, b, c, d);
DiagnosticOutput(diagIDString + "quaternion: @", quaternion);
// get the conjugated quaternion (q')
const maxon::Quaternion<maxon::Float> quaternionCnj = quaternion.GetConjugate();
DiagnosticOutput(diagIDString + "quaternionCnj: @", quaternionCnj);
// get the rotated point p1 = q * p * q'
const maxon::Quaternion<maxon::Float> quanterionPointARot = quaternion * quaternionPointA * quaternionCnj;
DiagnosticOutput(diagIDString + "quanterionPointARot: @", quanterionPointARot);
// extract the rotation point
const maxon::Vector rotPoint = quanterionPointARot.v;
DiagnosticOutput(diagIDString + "rotated point: @", rotPoint);

# Creation and initialization

A maxon::Quaternion instance can be created on the stack and initialized through the proper method using a numerical data type as template:

// This example allocates a few maxon::Quaternion objects showing the different allocation methods.
// just allocate an zero-valued quaternion object
const maxon::Quaternion<maxon::Float> zeroQuaternion;
// just allocate a quaternion object defining the vectorial part and the real part
const maxon::Vector vectorVal(1.0, 1.0, 0);
const maxon::Float floatVal(1.5);
const maxon::Quaternion<maxon::Float> vectorRealQuaternion(vectorVal, floatVal);
// just allocate a quaternion object defining the four components used to value vectorial and real part
const maxon::Float a = 0.2; // 1st vectorial component
const maxon::Float b = 0.4; // 2nd vectorial component
const maxon::Float c = 0.6; // 3rd vectorial component
const maxon::Float d = 0.8; // this the real part
const maxon::Quaternion<maxon::Float> fourComponentsQuaternion(a, b, c, d);

# Standard operations

The maxon::Quaternion class delivers a set of standard mathematical operators to perform calculation with quaternion. The operators deliver are:

// This example shows how to perform simple mathematical operations between quaternions.
// just allocate a constant quaternion using the four components
const maxon::Quaternion<maxon::Float> quaternionA(1, 0, 0, 12);
DiagnosticOutput(diagIDString + "quaternionA: @", quaternionA);
// just allocate a quaternion equal to the previous one
maxon::Quaternion<maxon::Float> quaternionB = quaternionA;
DiagnosticOutput(diagIDString + "quaternionB: @", quaternionB);
// sum A to B
quaternionB += quaternionA;
DiagnosticOutput(diagIDString + "quaternionB += quaternionA: @", quaternionB);
// subtract A to B
quaternionB -= quaternionA;
DiagnosticOutput(diagIDString + "quaternionB -= quaternionA: @", quaternionB);
// sum A and B
const maxon::Quaternion<maxon::Float> quaternionAsumB = quaternionA + quaternionB;
DiagnosticOutput(diagIDString + "quaternionAsumB : @", quaternionAsumB);
// subtract A and B
const maxon::Quaternion<maxon::Float> quaternionAdifB = quaternionA - quaternionB;
// multiply A and B
const maxon::Quaternion<maxon::Float> quaternionAprdB = quaternionA * quaternionB;
DiagnosticOutput(diagIDString + "quaternionAprdB: @", quaternionAprdB);
// multiply B and A
const maxon::Quaternion<maxon::Float> quaternionBprdA = quaternionB * quaternionA;
DiagnosticOutput(diagIDString + "quaternionBprdA: @", quaternionBprdA);
// scale A by scalar s
const maxon::Float scalar = 2;
const maxon::Quaternion<maxon::Float> quaternionAscaled = quaternionA * scalar;
DiagnosticOutput(diagIDString + "quaternionAscaled: @", quaternionAscaled);

# Get and Set operations

The maxon::Quaternion class is provided with a number of get methods to retrieve useful data from a maxon::Quaternion instance:

// This example shows how to use the "get" methods provided with maxon::Quaternion.
// just allocate a constant quaternion using the four components
// representing a rotation of 90 deg around Y-axis in left-handed c.sys
const maxon::Quaternion<maxon::Float> quatY90 (0, sin(PI05/2), 0, cos(PI05/2));
// get the rotation matrix associated with the quaternion
const maxon::Matrix rotMat = quatY90.GetMatrix();
// get the axis and rotation angle associated with the quaternion
maxon::Vector rotAxis;
maxon::Float rotAngle;
quatY90.GetAxisRotation(rotAxis, rotAngle) iferr_return;
// get the squared length of the quaternion
const maxon::Float valSqLength = quatY90.GetSquaredLength();
// get the length of the quaternion
const maxon::Float valLength = quatY90.GetLength();
// get the normalized quaternion
// get the inverse quaternion
// get the conjugate quaternion
const maxon::Quaternion<maxon::Float> quatConjugated = quatY90.GetConjugate();
// get the natural log quaternion
// get the exponential equaternion
// get the quaternion elevated to the given power
const maxon::Quaternion<maxon::Float> quatPow = quatY90.GetPow(3.0) iferr_return;
// get the dot product of two quaternion
const maxon::Float valDotProduct = maxon::Quaternion<maxon::Float>::GetDot(quatY90, quatConjugated);
// get the linear interpolation of the given quaternion and the given blend ratio
const maxon::Quaternion<maxon::Float> quatX90 (sin(PI05/2), 0, 0, cos(PI05/2));
// get the spherical linear interpolation of the given quaternion and the given blend ratio
const maxon::Quaternion<maxon::Float> quatSLERP = maxon::Quaternion<maxon::Float>::GetSlerp(quatY90, quatX90, 0.5) iferr_return;
// get the spherical quadrangle interpolation of a sequence of quaternions qi and qi+1 using the passed blend parameter
const maxon::Quaternion<maxon::Float> quatA (1, 0, 0, 1);
const maxon::Quaternion<maxon::Float> quatAp1 (1, 1, 0, 1);
const maxon::Quaternion<maxon::Float> quatB (0, 0, 1, 1);
const maxon::Quaternion<maxon::Float> quatBp1 (0, 1, 1, 1);
// get the inner quaternion from a sequance of quaternions qi-1, qi and qi+1
const maxon::Quaternion<maxon::Float> quatCm1 (-1, 1, 0, 1);
const maxon::Quaternion<maxon::Float> quatC (1, 1, 0, 1);
const maxon::Quaternion<maxon::Float> quatCp1 (2, 1, 0, 1);
const maxon::Quaternion<maxon::Float> quatInner = maxon::Quaternion<maxon::Float>::GetInnerQuaternion(quatCm1, quatC, quatCp1) iferr_return;
// get the spline quaternion from a sequence of quaternions
const maxon::Quaternion<maxon::Float> quatDm1 (0, 0, 0, 1);
const maxon::Quaternion<maxon::Float> quatD (1, 0, 0, 1);
const maxon::Quaternion<maxon::Float> quatDp1 (2, 0, 0, 2);
const maxon::Quaternion<maxon::Float> quatDp2 (3, 0, 0, 2);
const maxon::Quaternion<maxon::Float> quatSpline = maxon::Quaternion<maxon::Float>::GetSpline(quatDm1, quatD, quatDp1, quatDp2, 0.75) iferr_return;

The maxon::Quaternion class is provided with a number of "set" methods to define a maxon::Quaternion instance:

// This example shows how to use the "set" methods provided with maxon::Quaternion.
// allocate a constant transformation matrix representing
// a rotation of 90 deg around Y-axis in left-handed c.sys
const maxon::SqMat3<maxon::Vector> mat3x3(maxon::Vector(0, 0, 1), maxon::Vector(0, 1, 0), maxon::Vector(-1.0, 0.0, 0.0));
// allocate a quaternion and set the values accordingly to the matrix defined
quatA.SetMatrix(mat3x3);
// allocate a Eulerian rotation vector (each component of the vector
// represents a rotation around an axis) represeting a rotation of 90 deg
// around Y-axis in left-handed c.sys
const maxon::Vector rotVet (0.0, PI05, 0.0);
// allocate a quaternion and set the values accordingly to the vector defined
quatB.SetRotation(rotVet);
// allocate a vector representing a rotation axis and value representing the rotation amount
const maxon::Vector rotAxis (0.0, 1.0, 0.0);
const maxon::Float rotAngle(PI05);
// allocate a quaternion and set the values accordingly to the axis and angle defined
quatC.SetAxisRotation(rotAxis, rotAngle);

The maxon::Quaternion class can be used to easily perform a rotation on a geometrical entity.

// allocate a point on X-axis
const maxon::Vector point_on_X (1.0, 0.0, 0.0);
// define the rotation around the Y-axis
const maxon::Vector axis_Y (0.0, 1.0, 0.0);
// define the rotation amount in radians
const maxon::Float rot_angle (PI05);
// allocate and define the quaternion used to rotate the point
rotate_on_Y.SetAxisRotation(axis_Y, rot_angle);
// the new point should now be on the Z-axis
const maxon::Vector point_on_Z = rotate_on_Y.GetMatrix() * point_on_X;

# Conversion

A maxon::Quaternion instance can be converted to maxon::String using:

// This example shows how to convert a maxon::Quaternion to maxon::String.
// just allocate a complex object
const maxon::Quaternion<maxon::Float> quatA(1, 1, 0, 1);
const maxon::String stringQuaternion = quatA.ToString(nullptr);
DiagnosticOutput(diagIDString + "quatA: @", quatA);
DiagnosticOutput(diagIDString + "quatA.ToString(): @", stringQuaternion);

# Utilities

A maxon::Quaternion instance can be read from and written to disk by serializing the data contained using the conventional functions.

// This example shows how to store and retrieve a maxon::Quaternion from a file.
const maxon::Quaternion<maxon::Float> savedQuat(1, 1, 0, 1);
// file URL
const maxon::Url url = (targetFolder + "quaternion.txt"_s)iferr_return;
const maxon::Id fileID("net.maxonexample.quaternion");
// save to file