pub struct Versor(/* private fields */);Expand description
A unit Quaternion that represents a 3D rotation.
Versor represents a 3D rotation with a unit quaternion. Rotation follows the Hamilton
convention.
§Constructing a Versor:
The default Versor is the identity:
use hoomd_vector::Versor;
let v = Versor::default();
assert_eq!(*v.get(), [1.0, 0.0, 0.0, 0.0].into());Create a Versor that rotates by an angle about an axis:
use hoomd_vector::Versor;
use std::f64::consts::PI;
let v = Versor::from_axis_angle([0.0, 1.0, 0.0].try_into()?, PI / 2.0);
assert_eq!(
*v.get(),
[(PI / 4.0).cos(), 0.0, (PI / 4.0).sin(), 0.0].into()
);Create a Versor by normalizing a Quaternion:
use hoomd_vector::{Quaternion, Versor};
let q = Quaternion::from([3.0, 0.0, 0.0, 4.0]);
let v = q.to_versor()?;
assert_eq!(*v.get(), [3.0 / 5.0, 0.0, 0.0, 4.0 / 5.0].into());Create a random Versor:
use hoomd_vector::Versor;
use rand::{RngExt, SeedableRng, rngs::StdRng};
let mut rng = StdRng::seed_from_u64(1);
let v: Versor = rng.random();§Operations using Versor
Rotate a Cartesian<3> by a Versor:
use approxim::assert_relative_eq;
use hoomd_vector::{Cartesian, Rotate, Rotation, Versor};
use std::f64::consts::PI;
let a = Cartesian::from([-1.0, 0.0, 0.0]);
let v = Versor::from_axis_angle([0.0, 0.0, 1.0].try_into()?, PI / 2.0);
let b = v.rotate(&a);
assert_relative_eq!(b, [0.0, -1.0, 0.0].into());Combine two rotations together:
use hoomd_vector::{Rotation, Versor};
use std::f64::consts::PI;
let a = Versor::from_axis_angle([1.0, 0.0, 1.0].try_into()?, PI / 2.0);
let b = Versor::from_axis_angle([0.0, 0.0, 1.0].try_into()?, PI / 4.0);
let c = a.combine(&b);Implementations§
Source§impl Versor
impl Versor
Sourcepub fn from_axis_angle(axis: Unit<Cartesian<3>>, angle: f64) -> Self
pub fn from_axis_angle(axis: Unit<Cartesian<3>>, angle: f64) -> Self
Sourcepub fn normalized(self) -> Self
pub fn normalized(self) -> Self
Normalize the versor.
Nominally, all Versor instances retain a unit norm. Due to limited
floating point precision, this assumption may not hold after repeated
operations. Normalize versors when needed to correct this issue.
§Example
use hoomd_vector::Versor;
use std::f64::consts::PI;
let a = Versor::from_axis_angle([0.0, 1.0, 0.0].try_into()?, PI / 2.0);
let b = a.normalized();Sourcepub fn get(&self) -> &Quaternion
pub fn get(&self) -> &Quaternion
Get the unit quaternion.
Sourcepub fn arc_distance(&self, other: &Self) -> f64
pub fn arc_distance(&self, other: &Self) -> f64
A metric quantifying the angle (in radians) of the spherical arc separating two Versors.
$d : \mathbb{H} \times \mathbb{H} \to \mathbb{R}^+, \quad d(q_0, q_1) = \arccos(|q_0 \cdot q_1|)$
This value always lies in the range $[0, \pi]$, and is symmetric: while there
are multiple arcs separating a pair of quaternions, this metric always chooses
the shortest.
Sourcepub fn half_euclidean_norm_squared(&self, other: &Self) -> f64
pub fn half_euclidean_norm_squared(&self, other: &Self) -> f64
A fast metric on Versors representing elements of SO(3).
$d : \mathbb{H} \times \mathbb{H} \to \mathbb{R}^+, \quad d(q_0, q_1) = 1 - |q_0 \cdot q_1 |$
This has less geometric meaning than the arc_distance metric. However, it
is much faster while still obeying the triangle inequality and the axiom
$d(q_0, q_1) = d(q_1, q_0)$. This metric always lies in the range
$[0, 1]$, and is symmetric such that $d(q, q)$ = $d(q, -q)$.
Trait Implementations§
Source§impl AbsDiffEq for Versor
impl AbsDiffEq for Versor
Source§fn default_epsilon() -> Self::Epsilon
fn default_epsilon() -> Self::Epsilon
Source§fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool
Source§fn abs_diff_ne(&self, other: &Rhs, epsilon: Self::Epsilon) -> bool
fn abs_diff_ne(&self, other: &Rhs, epsilon: Self::Epsilon) -> bool
AbsDiffEq::abs_diff_eq.Source§impl<'de> Deserialize<'de> for Versor
impl<'de> Deserialize<'de> for Versor
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl Distribution<Versor> for StandardUniform
impl Distribution<Versor> for StandardUniform
Source§impl From<Versor> for RotationMatrix<3>
impl From<Versor> for RotationMatrix<3>
Source§fn from(versor: Versor) -> RotationMatrix<3>
fn from(versor: Versor) -> RotationMatrix<3>
Construct a rotation matrix equivalent to this versor’s rotation.
When rotating many vectors by the same Versor, improve performance
by converting to a matrix first and applying that matrix to the vectors.
§Example
use approxim::assert_relative_eq;
use hoomd_vector::{Cartesian, Rotate, RotationMatrix, Versor};
use std::f64::consts::PI;
let a = Cartesian::from([-1.0, 0.0, 0.0]);
let v = Versor::from_axis_angle([0.0, 0.0, 1.0].try_into()?, PI / 2.0);
let matrix = RotationMatrix::from(v);
let b = matrix.rotate(&a);
assert_relative_eq!(b, [0.0, -1.0, 0.0].into());Source§impl RelativeEq for Versor
impl RelativeEq for Versor
Source§fn default_max_relative() -> Self::Epsilon
fn default_max_relative() -> Self::Epsilon
Source§fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool
fn relative_eq( &self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool
Source§fn relative_ne(
&self,
other: &Rhs,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool
fn relative_ne( &self, other: &Rhs, epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool
RelativeEq::relative_eq.Source§impl Rotate<Cartesian<3>> for Versor
impl Rotate<Cartesian<3>> for Versor
Source§fn rotate(&self, vector: &Cartesian<3>) -> Cartesian<3>
fn rotate(&self, vector: &Cartesian<3>) -> Cartesian<3>
Rotate a Cartesian<3> by a Versor
\mathbf{q} \vec{a} \mathbf{q}^*§Example
use approxim::assert_relative_eq;
use hoomd_vector::{Cartesian, Rotate, Rotation, Versor};
use std::f64::consts::PI;
let a = Cartesian::from([-1.0, 0.0, 0.0]);
let v = Versor::from_axis_angle([0.0, 0.0, 1.0].try_into()?, PI / 2.0);
let b = v.rotate(&a);
assert_relative_eq!(b, [0.0, -1.0, 0.0].into());Source§type Matrix = RotationMatrix<3>
type Matrix = RotationMatrix<3>
Source§impl Rotation for Versor
impl Rotation for Versor
Source§fn combine(&self, other: &Self) -> Self
fn combine(&self, other: &Self) -> Self
Combine two rotations.
The resulting versor is obtained by quaternion multiplication.
\mathbf{q}_{ab} = \mathbf{q}_a \mathbf{q}_b§Example
use hoomd_vector::{Rotation, Versor};
let q_a = Versor::from_axis_angle([0.0, 1.0, 0.0].try_into()?, 1.5);
let q_b = Versor::from_axis_angle([1.0, 0.0, 0.0].try_into()?, 0.125);
let q_ab = q_a.combine(&q_b);