pub struct Rotation3 { /* private fields */ }Expand description
A 3x3 rotation matrix for orientation transforms.
Internally stores row-major data as [[f64; 3]; 3].
This is a pure mathematical operator with no frame semantics—
frame tagging is handled by the caller.
§Conventions
- Right-handed coordinate system assumed.
- Matrix applied as
y = R * x(column vector convention). - Transpose of a rotation matrix is its inverse.
§Example
use affn::Rotation3;
use qtty::angular::Radians;
use std::f64::consts::FRAC_PI_2;
// Rotate 90° around the Z axis
let rot = Rotation3::rz(Radians::new(FRAC_PI_2));
let x_axis = [1.0, 0.0, 0.0];
let rotated = rot.apply_array(x_axis);
// X-axis becomes Y-axis (within numerical tolerance)
assert!((rotated[0]).abs() < 1e-10);
assert!((rotated[1] - 1.0).abs() < 1e-10);
assert!((rotated[2]).abs() < 1e-10);Implementations§
Source§impl Rotation3
impl Rotation3
Sourcepub const fn from_matrix_unchecked(m: [[f64; 3]; 3]) -> Self
pub const fn from_matrix_unchecked(m: [[f64; 3]; 3]) -> Self
Creates a rotation matrix from raw row-major data without validation.
§Arguments
m: A 3x3 array in row-major order wherem[row][col].
§Safety (logical)
m must be an orthogonal matrix with det = +1 (a proper rotation).
No validation is performed. Passing an invalid matrix produces a mathematically
incoherent Rotation3 whose composition and inversion will silently propagate
garbage values, and Rotation3 * Direction<F> will manufacture a Direction
whose norm is not 1.
Sourcepub fn try_from_matrix(m: [[f64; 3]; 3]) -> Option<Self>
pub fn try_from_matrix(m: [[f64; 3]; 3]) -> Option<Self>
Creates a rotation matrix from raw row-major data, validating orthogonality.
Returns None if m is not a proper rotation matrix (i.e., Mᵀ·M is not
close to the identity within tolerance 1e-7, or det(M) is not close to +1).
§Arguments
m: A 3x3 array in row-major order wherem[row][col].
Sourcepub fn from_axis_angle(axis: [f64; 3], angle: Radians) -> Self
pub fn from_axis_angle(axis: [f64; 3], angle: Radians) -> Self
Sourcepub fn from_euler_xyz(x: Radians, y: Radians, z: Radians) -> Self
pub fn from_euler_xyz(x: Radians, y: Radians, z: Radians) -> Self
Creates a rotation from Euler angles (XYZ convention).
Applies rotations in order: X, then Y, then Z. Internally uses a fused constructor to avoid intermediate matrices.
§Arguments
x: Rotation around X axis.y: Rotation around Y axis.z: Rotation around Z axis.
Sourcepub fn from_euler_zxz(z1: Radians, x: Radians, z2: Radians) -> Self
pub fn from_euler_zxz(z1: Radians, x: Radians, z2: Radians) -> Self
Creates a rotation from Euler angles (ZXZ convention).
This is the classical astronomical convention used in precession. Applies rotations in order: first Z, then X, then Z. Internally uses a fused constructor to avoid intermediate matrices.
§Arguments
z1: First rotation around Z axis.x: Rotation around X axis.z2: Second rotation around Z axis.
Sourcepub fn rx(angle: Radians) -> Self
pub fn rx(angle: Radians) -> Self
Creates a rotation around the X axis from a typed Radians angle.
Sourcepub fn ry(angle: Radians) -> Self
pub fn ry(angle: Radians) -> Self
Creates a rotation around the Y axis from a typed Radians angle.
Sourcepub fn rz(angle: Radians) -> Self
pub fn rz(angle: Radians) -> Self
Creates a rotation around the Z axis from a typed Radians angle.
Sourcepub fn transpose(&self) -> Self
pub fn transpose(&self) -> Self
Returns the transpose (inverse) of this rotation.
For rotation matrices, transpose equals inverse.
Sourcepub fn compose(&self, other: &Self) -> Self
pub fn compose(&self, other: &Self) -> Self
Composes two rotations: self * other.
The result applies other first, then self.
Sourcepub fn apply_array(&self, v: [f64; 3]) -> [f64; 3]
pub fn apply_array(&self, v: [f64; 3]) -> [f64; 3]
Applies this rotation to a raw [f64; 3] array.
Computes R * v where v is treated as a column vector.
Sourcepub fn apply_vec<F1, F2, U>(&self, v: Vector<F1, U>) -> Vector<F2, U>
pub fn apply_vec<F1, F2, U>(&self, v: Vector<F1, U>) -> Vector<F2, U>
Applies this rotation to a typed Vector, changing its reference frame.
Rotates the vector’s components and re-tags the result with frame F2.
The unit U is unchanged. This is a zero-overhead operation: the matrix
multiplication uses the same path as [apply_array], with a frame tag
change at compile time.
§Example
use affn::{Rotation3, cartesian::Displacement};
use affn::frames::ReferenceFrame;
use qtty::unit::Kilometer;
use std::f64::consts::FRAC_PI_2;
#[derive(Debug, Copy, Clone)] struct FrameA;
#[derive(Debug, Copy, Clone)] struct FrameB;
impl ReferenceFrame for FrameA { fn frame_name() -> &'static str { "A" } }
impl ReferenceFrame for FrameB { fn frame_name() -> &'static str { "B" } }
let rot = Rotation3::rz(qtty::angular::Radians::new(FRAC_PI_2));
let v = Displacement::<FrameA, Kilometer>::new(1.0, 0.0, 0.0);
let rotated: Displacement<FrameB, Kilometer> = rot.apply_vec(v);
assert!((rotated.x().value() - 0.0).abs() < 1e-10);
assert!((rotated.y().value() - 1.0).abs() < 1e-10);Sourcepub const fn as_matrix(&self) -> &[[f64; 3]; 3]
pub const fn as_matrix(&self) -> &[[f64; 3]; 3]
Returns the underlying matrix as a row-major array.
Sourcepub fn fused_rx_rz(a: Radians, b: Radians) -> Self
pub fn fused_rx_rz(a: Radians, b: Radians) -> Self
Constructs the rotation Rx(a) · Rz(b) directly.
Faster than Rotation3::rx(a) * Rotation3::rz(b) because it avoids
the intermediate 3×3 matrix multiply and computes each element
from trig products.
§Arguments
a: Angle for the X rotation (applied second / left factor).b: Angle for the Z rotation (applied first / right factor).
Sourcepub fn fused_rz_rx(a: Radians, b: Radians) -> Self
pub fn fused_rz_rx(a: Radians, b: Radians) -> Self
Constructs the rotation Rz(a) · Rx(b) directly.
Faster than Rotation3::rz(a) * Rotation3::rx(b) because it avoids
the intermediate 3×3 matrix multiply.
§Arguments
a: Angle for the Z rotation (applied second / left factor).b: Angle for the X rotation (applied first / right factor).
Sourcepub fn fused_rx_rz_rx(a: Radians, b: Radians, c: Radians) -> Self
pub fn fused_rx_rz_rx(a: Radians, b: Radians, c: Radians) -> Self
Constructs the rotation Rx(a) · Rz(b) · Rx(c) directly.
Used in nutation: N = Rx(ε+Δε) · Rz(Δψ) · Rx(−ε).
Computes the 9 elements from 3 sin/cos pairs and their products, avoiding 2 intermediate matrix multiplications.
§Arguments
a: Angle for the outer X rotation (left).b: Angle for the Z rotation (middle).c: Angle for the inner X rotation (right).
Sourcepub fn fused_rz_ry_rz(a: Radians, b: Radians, c: Radians) -> Self
pub fn fused_rz_ry_rz(a: Radians, b: Radians, c: Radians) -> Self
Constructs the rotation Rz(a) · Ry(b) · Rz(c) directly.
Used in Meeus precession: P = Rz(z) · Ry(−θ) · Rz(ζ).
§Arguments
a: Angle for the outer Z rotation (left).b: Angle for the Y rotation (middle).c: Angle for the inner Z rotation (right).
Sourcepub fn fused_rx_rz_rx_rz(a: Radians, b: Radians, c: Radians, d: Radians) -> Self
pub fn fused_rx_rz_rx_rz(a: Radians, b: Radians, c: Radians, d: Radians) -> Self
Constructs the Fukushima-Williams rotation Rx(a) · Rz(b) · Rx(c) · Rz(d) directly.
This is the standard form for IAU 2006 precession and precession-nutation matrices. In the SOFA convention (translated to standard rotations):
P = Rx(ε_A) · Rz(ψ̄) · Rx(−φ̄) · Rz(−γ̄)This fused constructor computes all 9 matrix elements directly from 4 sin/cos pairs, avoiding 3 intermediate matrix multiplications. Provides a ~45% speedup over the sequential composition.
§Arguments
a: Angle for the outer X rotation (left, e.g., ε_A).b: Angle for the first Z rotation (e.g., ψ̄).c: Angle for the inner X rotation (e.g., −φ̄).d: Angle for the innermost Z rotation (e.g., −γ̄).
Trait Implementations§
Source§impl<F: ReferenceFrame> Mul<Direction<F>> for Rotation3
Rotation3 * Direction<F> — rotates a unit direction, preserving frame.
impl<F: ReferenceFrame> Mul<Direction<F>> for Rotation3
Rotation3 * Direction<F> — rotates a unit direction, preserving frame.
Translations do not apply to directions; only rotation changes their orientation. The result is guaranteed to remain a unit vector because rotation preserves norms.
Source§impl<F, U> Mul<Vector<F, U>> for Rotation3where
F: ReferenceFrame,
U: Unit,
Rotation3 * Vector<F, U> — rotates a free vector, preserving frame and unit.
impl<F, U> Mul<Vector<F, U>> for Rotation3where
F: ReferenceFrame,
U: Unit,
Rotation3 * Vector<F, U> — rotates a free vector, preserving frame and unit.
Translations do not apply to free vectors (they are translation-invariant),
so this is only implemented for Rotation3.