Chem::Spatial::Quat
Inherits Struct / Value / Object
The quaternion is a mathematical construct that extends the complex numbers and it is useful to encode three-dimensional rotations. Quats are represented by four numbers (w, x, y, z), where w is considered as the real (scalar) part and x, y, z the imaginary (vector) part. Rotations can be encoded as a unit quaternion using the axis-angle representation, where x, y, z correspond to the rotation axis and w to the rotation angle by the following formula:
q(v, t) = q(w, x, y, z) = q(cos(t/2), sin(t/2)vx, sin(t/2)vy, sin(t/2)vz)
where v is a unit vector and t is the rotation angle. Quats have several useful mathematical properties, e.g., quaternion multiplication can be used to represent a sequence of rotations producing a single quaternion. Indeed, the rotation encoded in the quaternion q can be applied to a ordinary vector p simply by
p* = q * p * q-1
where q-1 is the inverse of q and p* is the rotated vector
(see Quat#* for details).
Examples
q = Quat[1, 2, 3, 4]
q # => [1.0 2.0 3.0 4.0]
q.real # => 1.0
q.imag # => [2.0 3.0 4.0]
q.w # => 1.0
q.x # => 2.0
q.y # => 3.0
q.z # => 4.0
-q # => [-1.0 -2.0 -3.0 -4.0]
q.abs # => 5.477225575051661
q.abs2 # => 30.0
q.conj # => [1.0 -2.0 -3.0 -4.0]
q.inv # => [0.033 -0.067 -0.1 -0.133]
q.normalize # => [0.183 0.365 0.548 0.730]
q.unit? # => false
q.normalize.unit? # => true
q.zero? # => false
q * 2 # => [2.0 4.0 6.0 8.0]
q / 10 # => [0.2 0.4 0.6 0.8]
p = Quat[4, 3, 2, 1]
p + q # => [5.0 5.0 5.0 5.0]
p * q # => [-12.0 16.0 4.0 22.0]
q * p # => [-12.0 6.0 24.0 12.0]
Use the convenience methods to encode rotations.
v = Vec3[1, 2, 3]
q = Quat.aligning v, to: Vec3[1, 0, 0]
q * v # => [3.742 0.0 0.0]
# or
v.transform(q) # => [3.742 0.0 0.0]
(q * v).normalize # => [1.0 0.0 0.0]
q = Quat.rotation Vec3[0, 1, 0], by: 90
q * v # => [3.0 2.0 -1.0]
v * q # => [-3.0 2.0 1.0]
NOTE: Quat multiplication is not commutative: q * v != v * p, the former will apply the rotation encoded in q to v but the
latter will produce the inverse rotation. Use Vec3#transform to
avoid the ambiguity.
Constructors
Returns a quaternion with w as the real (scalar) part and x, y, and z as the vector (imaginary) part.
Returns a quaternion encoding the rotation operation to align u to v.
Returns a quaternion encoding the rotation to align u[0] to v[0] and u[1] to v[1].
First compute the alignment of u[0] to v[0], then the alignment of the transformed u[1] to v[1] on the plane perpendicular to v[0] by taking their projections.
Creates a new quaternion with w as the real (scalar) part and x, y, and z as the vector (imaginary) part.
Returns a quaternion encoding the rotation by the Euler angles.
The rotation rotates x degrees around the X axis, y degrees around the Y axis, and z degrees around the y axis; applied in that order (XYZ).
Instance methods
Returns the conjugate of rhs by the quaternion.
The conjugate of rhs is calculated as p* = q * p * q^-1, where
p is a quaternion whose vector part is rhs and real part
equals zero. Thus, the resulting quaternion is computed using the
Hamilton product and its vector part corresponds to p*. Such
operation can be written as (self * rhs.to_q * inv).imag, but
this method implements an optimized version by using some vector
and quaternion identities. The faster method is taken from this
post of the molecular matters blog.
If the quaternion encodes a rotation about an axis, this effectively applies such rotation to rhs.
Returns true if the elements of the quaternions are within
delta from each other, else false.
Quat[1, 2, 3, 4].close_to?(Quat[1, 2, 3, 4]) # => true
Quat[1, 2, 3, 4].close_to?(Quat[1.001, 1.999, 3.00004, 4], 1e-3) # => true
Quat[1, 2, 3, 4].close_to?(Quat[4, 3, 2, 1]) # => false
Quat[1, 2, 3, 4].close_to?(Quat[1.001, 1.999, 3.00004, 4], 1e-8) # => false