Class QuaternionRotation

java.lang.Object
org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation
All Implemented Interfaces:
Function<Vector3D,Vector3D>, UnaryOperator<Vector3D>, Transform<Vector3D>, EuclideanTransform<Vector3D>, Rotation3D

public final class QuaternionRotation extends Object implements Rotation3D
Class using a unit-length quaternion to represent rotations in 3-dimensional Euclidean space. The underlying quaternion is in positive polar form: It is normalized and has a non-negative scalar component (w).
See Also:
  • Quaternion
  • Field Details

    • ANTIPARALLEL_DOT_THRESHOLD

      private static final double ANTIPARALLEL_DOT_THRESHOLD
      Threshold value for the dot product of antiparallel vectors. If the dot product of two vectors is less than this value, (adjusted for the lengths of the vectors), then the vectors are considered to be antiparallel (ie, negations of each other).
      See Also:
    • AXIS_ANGLE_SINGULARITY_THRESHOLD

      private static final double AXIS_ANGLE_SINGULARITY_THRESHOLD
      Threshold value used to identify singularities when converting from quaternions to axis angle sequences.
      See Also:
    • IDENTITY_INSTANCE

      private static final QuaternionRotation IDENTITY_INSTANCE
      Instance used to represent the identity rotation, ie a rotation with an angle of zero.
    • quat

      private final org.apache.commons.numbers.quaternion.Quaternion quat
      Unit-length quaternion instance in positive polar form.
  • Constructor Details

    • QuaternionRotation

      private QuaternionRotation(org.apache.commons.numbers.quaternion.Quaternion quat)
      Simple constructor. The given quaternion is converted to positive polar form.
      Parameters:
      quat - quaternion instance
      Throws:
      IllegalStateException - if the the norm of the given components is zero, NaN, or infinite
  • Method Details

    • getQuaternion

      public org.apache.commons.numbers.quaternion.Quaternion getQuaternion()
      Get the underlying quaternion instance.
      Returns:
      the quaternion instance
    • getAxis

      public Vector3D getAxis()
      Get the axis of rotation as a normalized Vector3D. The rotation axis is not well defined when the rotation is the identity rotation, ie it has a rotation angle of zero. In this case, the vector representing the positive x-axis is returned.
      Specified by:
      getAxis in interface Rotation3D
      Returns:
      the axis of rotation
      See Also:
    • getAngle

      public double getAngle()
      Get the angle of rotation in radians. The returned value is in the range 0 through pi.
      Specified by:
      getAngle in interface Rotation3D
      Returns:
      The rotation angle in the range [0, pi].
      See Also:
    • inverse

      public QuaternionRotation inverse()
      Get the inverse of this rotation. The returned rotation has the same rotation angle but the opposite rotation axis. If r.apply(u) is equal to v, then r.negate().apply(v) is equal to u.
      Specified by:
      inverse in interface Rotation3D
      Specified by:
      inverse in interface Transform<Vector3D>
      Returns:
      the negation (inverse) of the rotation
    • apply

      public Vector3D apply(Vector3D v)
      Apply this rotation to the given vector.
      Specified by:
      apply in interface Function<Vector3D,Vector3D>
      Specified by:
      apply in interface Rotation3D
      Parameters:
      v - vector to rotate
      Returns:
      the rotated vector
    • applyVector

      public Vector3D applyVector(Vector3D vec)
      Apply this transform to the given vector, ignoring translations.

      This method can be used to transform vector instances representing displacements between points. For example, if v represents the difference between points p1 and p2, then transform.applyVector(v) will represent the difference between p1 and p2 after transform is applied.

      This method simply calls apply(vec) since rotations treat points and vectors similarly.

      Specified by:
      applyVector in interface EuclideanTransform<Vector3D>
      Parameters:
      vec - the vector to transform
      Returns:
      the new, transformed vector
    • preservesOrientation

      public boolean preservesOrientation()
      Return true if the transform preserves the orientation of the space. For example, in Euclidean 2D space, this will be true for translations, rotations, and scalings but will be false for reflections.

      This method simply returns true since rotations always preserve the orientation of the space.

      Specified by:
      preservesOrientation in interface Transform<Vector3D>
      Returns:
      true if the transform preserves the orientation of the space
      See Also:
    • toMatrix

      public AffineTransformMatrix3D toMatrix()
      Return an AffineTransformMatrix3D representing the same rotation as this instance.
      Returns:
      a transform matrix representing the same rotation as this instance
    • multiply

      Multiply this instance by the given argument, returning the result as a new instance. This is equivalent to the expression t * q where q is the argument and t is this instance.

      Multiplication of quaternions behaves similarly to transformation matrices in regard to the order that operations are performed. For example, if q1 and q2 are unit quaternions, then the quaternion qr = q1*q2 will give the effect of applying the rotation in q2 followed by the rotation in q1. In other words, the rightmost element in the multiplication is applied first.

      Parameters:
      q - quaternion to multiply with the current instance
      Returns:
      the result of multiplying this quaternion by the argument
    • premultiply

      public QuaternionRotation premultiply(QuaternionRotation q)
      Multiply the argument by this instance, returning the result as a new instance. This is equivalent to the expression q * t where q is the argument and t is this instance.

      Multiplication of quaternions behaves similarly to transformation matrices in regard to the order that operations are performed. For example, if q1 and q2 are unit quaternions, then the quaternion qr = q1*q2 will give the effect of applying the rotation in q2 followed by the rotation in q1. In other words, the rightmost element in the multiplication is applied first.

      Parameters:
      q - quaternion to multiply by the current instance
      Returns:
      the result of multiplying the argument by the current instance
    • slerp

      Creates a function that performs a spherical linear interpolation between this instance and the argument.

      The argument to the function returned by this method is the interpolation parameter t. If t = 0, the rotation is equal to this instance. If t = 1, the rotation is equal to the end instance. All other values are interpolated (or extrapolated if t is outside of the [0, 1] range).

      Parameters:
      end - end value of the interpolation
      Returns:
      a function that interpolates between this instance and the argument.
      See Also:
      • Slerp
    • toAxisAngleSequence

      public AxisAngleSequence toAxisAngleSequence(AxisReferenceFrame frame, AxisSequence axes)
      Get a sequence of axis-angle rotations that produce an overall rotation equivalent to this instance.

      In most cases, the returned rotation sequence will be unique. However, at points of singularity (second angle equal to 0 or -pi for Euler angles and +pi/2 or -pi/2 for Tait-Bryan angles), there are an infinite number of possible sequences that produce the same result. In these cases, the result is returned that leaves the last rotation equal to 0 (in the case of a relative reference frame) or the first rotation equal to 0 (in the case of an absolute reference frame).

      Parameters:
      frame - the reference frame used to interpret the positions of the rotation axes
      axes - the sequence of rotation axes
      Returns:
      a sequence of axis-angle rotations equivalent to this rotation
    • toRelativeAxisAngleSequence

      public AxisAngleSequence toRelativeAxisAngleSequence(AxisSequence axes)
      Get a sequence of axis-angle rotations that produce an overall rotation equivalent to this instance. Each rotation axis is interpreted relative to the rotated coordinate frame (ie, intrinsic rotation).
      Parameters:
      axes - the sequence of rotation axes
      Returns:
      a sequence of relative axis-angle rotations equivalent to this rotation
      See Also:
    • toAbsoluteAxisAngleSequence

      public AxisAngleSequence toAbsoluteAxisAngleSequence(AxisSequence axes)
      Get a sequence of axis-angle rotations that produce an overall rotation equivalent to this instance. Each rotation axis is interpreted as part of an absolute, unmoving coordinate frame (ie, extrinsic rotation).
      Parameters:
      axes - the sequence of rotation axes
      Returns:
      a sequence of absolute axis-angle rotations equivalent to this rotation
      See Also:
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • equals

      public boolean equals(Object obj)
      Overrides:
      equals in class Object
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • getAngles

      private double[] getAngles(AxisReferenceFrame frame, AxisSequence axes)
      Get a sequence of angles around the given axes that produce a rotation equivalent to this instance.
      Parameters:
      frame - the reference frame used to define the positions of the axes
      axes - the axis sequence
      Returns:
      a sequence of angles around the given axes that produce a rotation equivalent to this instance
    • getRelativeTaitBryanAngles

      private double[] getRelativeTaitBryanAngles(Vector3D axis1, Vector3D axis2, Vector3D axis3)
      Get a sequence of angles around the given Tait-Bryan axes that produce a rotation equivalent to this instance. The axes are interpreted as being relative to the rotated coordinate frame.
      Parameters:
      axis1 - first Tait-Bryan axis
      axis2 - second Tait-Bryan axis
      axis3 - third Tait-Bryan axis
      Returns:
      a sequence of rotation angles around the relative input axes that produce a rotation equivalent to this instance
    • getAbsoluteTaitBryanAngles

      private double[] getAbsoluteTaitBryanAngles(Vector3D axis1, Vector3D axis2, Vector3D axis3)
      Get a sequence of angles around the given Tait-Bryan axes that produce a rotation equivalent to this instance. The axes are interpreted as being part of an absolute (unmoving) coordinate frame.
      Parameters:
      axis1 - first Tait-Bryan axis
      axis2 - second Tait-Bryan axis
      axis3 - third Tait-Bryan axis
      Returns:
      a sequence of rotation angles around the absolute input axes that produce a rotation equivalent to this instance
    • getRelativeEulerAngles

      private double[] getRelativeEulerAngles(Vector3D axis1, Vector3D axis2)
      Get a sequence of angles around the given Euler axes that produce a rotation equivalent to this instance. The axes are interpreted as being relative to the rotated coordinate frame. Only the first two axes are needed since, by definition, the first Euler angle axis is repeated as the third axis.
      Parameters:
      axis1 - first Euler axis
      axis2 - second Euler axis
      Returns:
      a sequence of rotation angles around the relative input axes that produce a rotation equivalent to this instance
    • getAbsoluteEulerAngles

      private double[] getAbsoluteEulerAngles(Vector3D axis1, Vector3D axis2)
      Get a sequence of angles around the given Euler axes that produce a rotation equivalent to this instance. The axes are interpreted as being part of an absolute (unmoving) coordinate frame. Only the first two axes are needed since, by definition, the first Euler angle axis is repeated as the third axis.
      Parameters:
      axis1 - first Euler axis
      axis2 - second Euler axis
      Returns:
      a sequence of rotation angles around the absolute input axes that produce a rotation equivalent to this instance
    • of

      public static QuaternionRotation of(org.apache.commons.numbers.quaternion.Quaternion quat)
      Create a new instance from the given quaternion. The quaternion is normalized and converted to positive polar form (ie, with w >= 0).
      Parameters:
      quat - the quaternion to use for the rotation
      Returns:
      a new instance built from the given quaternion.
      Throws:
      IllegalStateException - if the the norm of the given components is zero, NaN, or infinite
      See Also:
      • Quaternion.normalize()
      • Quaternion.positivePolarForm()
    • of

      public static QuaternionRotation of(double w, double x, double y, double z)
      Create a new instance from the given quaternion values. The inputs are normalized and converted to positive polar form (ie, with w >= 0).
      Parameters:
      w - quaternion scalar component
      x - first quaternion vectorial component
      y - second quaternion vectorial component
      z - third quaternion vectorial component
      Returns:
      a new instance containing the normalized quaterion components
      Throws:
      IllegalStateException - if the the norm of the given components is zero, NaN, or infinite
      See Also:
      • Quaternion.normalize()
      • Quaternion.positivePolarForm()
    • identity

      public static QuaternionRotation identity()
      Return an instance representing a rotation of zero.
      Returns:
      instance representing a rotation of zero.
    • fromAxisAngle

      public static QuaternionRotation fromAxisAngle(Vector3D axis, double angle)
      Create a new instance representing a rotation of angle radians around axis.

      Rotation direction follows the right-hand rule, meaning that if one places their right hand such that the thumb points in the direction of the vector, the curl of the fingers indicates the direction of rotation.

      Note that the returned quaternion will represent the defined rotation but the values returned by getAxis() and getAngle() may not match the ones given here. This is because the axis and angle are normalized such that the axis has unit length, and the angle lies in the range [0, pi]. Depending on the inputs, the axis may need to be inverted in order for the angle to lie in this range.

      Parameters:
      axis - the axis of rotation
      angle - angle of rotation in radians
      Returns:
      a new instance representing the defined rotation
      Throws:
      IllegalArgumentException - if the given axis cannot be normalized or the angle is NaN or infinite
    • createVectorRotation

      public static QuaternionRotation createVectorRotation(Vector3D u, Vector3D v)
      Return an instance that rotates the first vector to the second.

      Except for a possible scale factor, if the returned instance is applied to vector u, it will produce the vector v. There are an infinite number of such rotations; this method chooses the one with the smallest associated angle, meaning the one whose axis is orthogonal to the (u, v) plane. If u and v are collinear, an arbitrary rotation axis is chosen.

      Parameters:
      u - origin vector
      v - target vector
      Returns:
      a new instance that rotates u to point in the direction of v
      Throws:
      IllegalArgumentException - if either vector has a norm of zero, NaN, or infinity
    • createBasisRotation

      public static QuaternionRotation createBasisRotation(Vector3D u1, Vector3D u2, Vector3D v1, Vector3D v2)
      Return an instance that rotates the basis defined by the first two vectors into the basis defined by the second two.

      The given basis vectors do not have to be directly orthogonal. A right-handed orthonormal basis is created from each pair by normalizing the first vector, making the second vector orthogonal to the first, and then taking the cross product. A rotation is then calculated that rotates the first to the second.

      Parameters:
      u1 - first vector of the source basis
      u2 - second vector of the source basis
      v1 - first vector of the target basis
      v2 - second vector of the target basis
      Returns:
      an instance that rotates the source basis to the target basis
      Throws:
      IllegalArgumentException - if any of the input vectors cannot be normalized or the vectors defining either basis are collinear
    • fromAxisAngleSequence

      public static QuaternionRotation fromAxisAngleSequence(AxisAngleSequence sequence)
      Create a new instance equivalent to the given sequence of axis-angle rotations.
      Parameters:
      sequence - the axis-angle rotation sequence to convert to a quaternion rotation
      Returns:
      instance representing a rotation equivalent to the given axis-angle sequence
    • orthogonalRotationMatrixToQuaternion

      private static QuaternionRotation orthogonalRotationMatrixToQuaternion(double m00, double m01, double m02, double m10, double m11, double m12, double m20, double m21, double m22)
      Create an instance from an orthogonal rotation matrix.
      Parameters:
      m00 - matrix entry m0,0
      m01 - matrix entry m0,1
      m02 - matrix entry m0,2
      m10 - matrix entry m1,0
      m11 - matrix entry m1,1
      m12 - matrix entry m1,2
      m20 - matrix entry m2,0
      m21 - matrix entry m2,1
      m22 - matrix entry m2,2
      Returns:
      an instance representing the same 3D rotation as the given matrix
    • reverseArray

      private static double[] reverseArray(double[] arr)
      Reverse the elements in arr. The array is returned.
      Parameters:
      arr - the array to reverse
      Returns:
      the input array with the elements reversed