struct Chem::Spatial::Quat
- Chem::Spatial::Quat
- Struct
- Value
- Object
Overview
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.
Defined in:
chem/spatial/quat.crConstructors
-
.[](w : Float64, x : Float64, y : Float64, z : Float64) : self
Returns a quaternion with w as the real (scalar) part and x, y, and z as the vector (imaginary) part.
-
.aligning(u : Vec3, to v : Vec3) : self
Returns a quaternion encoding the rotation operation to align u to v.
-
.aligning(u : Tuple(Vec3, Vec3), to v : Tuple(Vec3, Vec3)) : self
Returns a quaternion encoding the rotation to align u[0] to v[0] and u[1] to v[1].
-
.identity : self
Returns the identity quaternion (no rotation).
-
.new(w : Float64, x : Float64, y : Float64, z : Float64)
Creates a new quaternion with w as the real (scalar) part and x, y, and z as the vector (imaginary) part.
-
.rotation(x : Number, y : Number, z : Number) : self
Returns a quaternion encoding the rotation by the Euler angles.
-
.rotation(about rotaxis : Vec3, by theta : Number) : self
Returns a quaternion encoding the rotation about the axis vector rotaxis by theta degrees.
Instance Method Summary
-
#*(rhs : self) : self
Returns the Hamilton product of the quaternion and rhs.
-
#*(rhs : Vec3) : Vec3
Returns the conjugate of rhs by the quaternion.
-
#*(rhs : Number) : self
Returns the element-wise multiplication of the quaternion by rhs.
-
#+(rhs : self) : self
Returns the element-wise addition of the quaternion by rhs.
-
#-(rhs : self) : self
Returns the element-wise subtraction of the quaternion by rhs.
-
#- : self
Returns the negation of the quaternion.
-
#/(rhs : Number) : self
Returns the element-wise division of the quaternion by rhs.
-
#abs : Float64
Returns the absolute value (norm) using the Pythagorean theorem.
-
#abs2 : Float64
Returns the square of the absolute value (norm).
-
#close_to?(rhs : self, delta : Number = Float64::EPSILON) : Bool
Returns
true
if the elements of the quaternions are within delta from each other, elsefalse
. -
#conj : self
Returns the conjugate of the quaternion.
-
#dot(rhs : self) : Float64
Returns the dot product of the quaternion and rhs.
-
#imag : Vec3
Returns the imaginary part of the quaternion.
-
#inv : self
Returns the inverse of the quaternion.
-
#normalize : self
Returns the normalized quaternion of the quaternion.
-
#real : Float64
Returns the real part of the quaternion.
-
#to_mat3 : Mat3
Returns the rotation matrix equivalent to the quaternion.
-
#to_s(io : IO) : Nil
Same as
#inspect(io)
. -
#unit? : Bool
Returns
true
if the quaternion is a unit quaternion, elsefalse
. -
#w : Float64
Real (scalar) part of the quaternion.
-
#x : Float64
X component of the imaginary (vector) part of the quaternion.
-
#y : Float64
Y component of the imaginary (vector) part of the quaternion.
-
#z : Float64
Z component of the imaginary (vector) part of the quaternion.
-
#zero? : Bool
Returns
true
if the quaternion is a zero quaternion, elsefalse
.
Constructor Detail
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).
Returns a quaternion encoding the rotation about the axis vector rotaxis by theta degrees.
Instance Method Detail
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 the element-wise multiplication of the quaternion by rhs.
Returns the element-wise addition of the quaternion by rhs.
Returns the element-wise subtraction of the quaternion by rhs.
Returns the element-wise division of the quaternion by 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