Class QuaternionRotation
- java.lang.Object
-
- org.apache.commons.geometry.euclidean.threed.rotation.QuaternionRotation
-
- All Implemented Interfaces:
java.util.function.Function<Vector3D,Vector3D>
,java.util.function.UnaryOperator<Vector3D>
,Transform<Vector3D>
,EuclideanTransform<Vector3D>
,Rotation3D
public final class QuaternionRotation extends java.lang.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 Summary
Fields Modifier and Type Field Description private static double
ANTIPARALLEL_DOT_THRESHOLD
Threshold value for the dot product of antiparallel vectors.private static double
AXIS_ANGLE_SINGULARITY_THRESHOLD
Threshold value used to identify singularities when converting from quaternions to axis angle sequences.private static QuaternionRotation
IDENTITY_INSTANCE
Instance used to represent the identity rotation, ie a rotation with an angle of zero.private org.apache.commons.numbers.quaternion.Quaternion
quat
Unit-length quaternion instance in positive polar form.
-
Constructor Summary
Constructors Modifier Constructor Description private
QuaternionRotation(org.apache.commons.numbers.quaternion.Quaternion quat)
Simple constructor.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description Vector3D
apply(Vector3D v)
Apply this rotation to the given vector.Vector3D
applyVector(Vector3D vec)
Apply this transform to the given vector, ignoring translations.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.static QuaternionRotation
createVectorRotation(Vector3D u, Vector3D v)
Return an instance that rotates the first vector to the second.boolean
equals(java.lang.Object obj)
static QuaternionRotation
fromAxisAngle(Vector3D axis, double angle)
Create a new instance representing a rotation ofangle
radians aroundaxis
.static QuaternionRotation
fromAxisAngleSequence(AxisAngleSequence sequence)
Create a new instance equivalent to the given sequence of axis-angle rotations.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.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.double
getAngle()
Get the angle of rotation in radians.private double[]
getAngles(AxisReferenceFrame frame, AxisSequence axes)
Get a sequence of angles around the given axes that produce a rotation equivalent to this instance.Vector3D
getAxis()
Get the axis of rotation as a normalizedVector3D
.org.apache.commons.numbers.quaternion.Quaternion
getQuaternion()
Get the underlying quaternion instance.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.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.int
hashCode()
static QuaternionRotation
identity()
Return an instance representing a rotation of zero.QuaternionRotation
inverse()
Get the inverse of this rotation.QuaternionRotation
multiply(QuaternionRotation q)
Multiply this instance by the given argument, returning the result as a new instance.static QuaternionRotation
of(double w, double x, double y, double z)
Create a new instance from the given quaternion values.static QuaternionRotation
of(org.apache.commons.numbers.quaternion.Quaternion quat)
Create a new instance from the given quaternion.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.QuaternionRotation
premultiply(QuaternionRotation q)
Multiply the argument by this instance, returning the result as a new instance.boolean
preservesOrientation()
Return true if the transform preserves the orientation of the space.private static double[]
reverseArray(double[] arr)
Reverse the elements inarr
.java.util.function.DoubleFunction<QuaternionRotation>
slerp(QuaternionRotation end)
Creates a function that performs a spherical linear interpolation between this instance and the argument.AxisAngleSequence
toAbsoluteAxisAngleSequence(AxisSequence axes)
Get a sequence of axis-angle rotations that produce an overall rotation equivalent to this instance.AxisAngleSequence
toAxisAngleSequence(AxisReferenceFrame frame, AxisSequence axes)
Get a sequence of axis-angle rotations that produce an overall rotation equivalent to this instance.AffineTransformMatrix3D
toMatrix()
Return anAffineTransformMatrix3D
representing the same rotation as this instance.AxisAngleSequence
toRelativeAxisAngleSequence(AxisSequence axes)
Get a sequence of axis-angle rotations that produce an overall rotation equivalent to this instance.java.lang.String
toString()
-
-
-
Field Detail
-
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:
- Constant Field Values
-
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:
- Constant Field Values
-
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 Detail
-
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:
java.lang.IllegalStateException
- if the the norm of the given components is zero, NaN, or infinite
-
-
Method Detail
-
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 normalizedVector3D
. 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 interfaceRotation3D
- Returns:
- the axis of rotation
- See Also:
Rotation3D.getAngle()
-
getAngle
public double getAngle()
Get the angle of rotation in radians. The returned value is in the range 0 throughpi
.- Specified by:
getAngle
in interfaceRotation3D
- Returns:
- The rotation angle in the range
[0, pi]
. - See Also:
Rotation3D.getAxis()
-
inverse
public QuaternionRotation inverse()
Get the inverse of this rotation. The returned rotation has the same rotation angle but the opposite rotation axis. Ifr.apply(u)
is equal tov
, thenr.negate().apply(v)
is equal tou
.- Specified by:
inverse
in interfaceRotation3D
- Specified by:
inverse
in interfaceTransform<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 interfacejava.util.function.Function<Vector3D,Vector3D>
- Specified by:
apply
in interfaceRotation3D
- 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 pointsp1
andp2
, thentransform.applyVector(v)
will represent the difference betweenp1
andp2
aftertransform
is applied.This method simply calls
apply(vec)
since rotations treat points and vectors similarly.- Specified by:
applyVector
in interfaceEuclideanTransform<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 interfaceTransform<Vector3D>
- Returns:
- true if the transform preserves the orientation of the space
- See Also:
- Orientation
-
toMatrix
public AffineTransformMatrix3D toMatrix()
Return anAffineTransformMatrix3D
representing the same rotation as this instance.- Returns:
- a transform matrix representing the same rotation as this instance
-
multiply
public QuaternionRotation multiply(QuaternionRotation q)
Multiply this instance by the given argument, returning the result as a new instance. This is equivalent to the expressiont * q
whereq
is the argument andt
is this instance.Multiplication of quaternions behaves similarly to transformation matrices in regard to the order that operations are performed. For example, if
q1
andq2
are unit quaternions, then the quaternionqr = q1*q2
will give the effect of applying the rotation inq2
followed by the rotation inq1
. 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 expressionq * t
whereq
is the argument andt
is this instance.Multiplication of quaternions behaves similarly to transformation matrices in regard to the order that operations are performed. For example, if
q1
andq2
are unit quaternions, then the quaternionqr = q1*q2
will give the effect of applying the rotation inq2
followed by the rotation inq1
. 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
public java.util.function.DoubleFunction<QuaternionRotation> slerp(QuaternionRotation end)
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
. Ift = 0
, the rotation is equal to this instance. Ift = 1
, the rotation is equal to theend
instance. All other values are interpolated (or extrapolated ift
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 axesaxes
- 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:
toAxisAngleSequence(AxisReferenceFrame, AxisSequence)
-
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:
toAxisAngleSequence(AxisReferenceFrame, AxisSequence)
-
hashCode
public int hashCode()
- Overrides:
hashCode
in classjava.lang.Object
-
equals
public boolean equals(java.lang.Object obj)
- Overrides:
equals
in classjava.lang.Object
-
toString
public java.lang.String toString()
- Overrides:
toString
in classjava.lang.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 axesaxes
- 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 axisaxis2
- second Tait-Bryan axisaxis3
- 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 axisaxis2
- second Tait-Bryan axisaxis3
- 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 axisaxis2
- 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 axisaxis2
- 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:
java.lang.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 componentx
- first quaternion vectorial componenty
- second quaternion vectorial componentz
- third quaternion vectorial component- Returns:
- a new instance containing the normalized quaterion components
- Throws:
java.lang.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 ofangle
radians aroundaxis
.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()
andgetAngle()
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 rotationangle
- angle of rotation in radians- Returns:
- a new instance representing the defined rotation
- Throws:
java.lang.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 vectorv
. 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. Ifu
andv
are collinear, an arbitrary rotation axis is chosen.- Parameters:
u
- origin vectorv
- target vector- Returns:
- a new instance that rotates
u
to point in the direction ofv
- Throws:
java.lang.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 basisu2
- second vector of the source basisv1
- first vector of the target basisv2
- second vector of the target basis- Returns:
- an instance that rotates the source basis to the target basis
- Throws:
java.lang.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 entrym0,0
m01
- matrix entrym0,1
m02
- matrix entrym0,2
m10
- matrix entrym1,0
m11
- matrix entrym1,1
m12
- matrix entrym1,2
m20
- matrix entrym2,0
m21
- matrix entrym2,1
m22
- matrix entrym2,2
- Returns:
- an instance representing the same 3D rotation as the given matrix
-
reverseArray
private static double[] reverseArray(double[] arr)
Reverse the elements inarr
. The array is returned.- Parameters:
arr
- the array to reverse- Returns:
- the input array with the elements reversed
-
-