pub struct RotationMatrix3 { /* private fields */ }Expand description
A 3x3 rotation matrix for coordinate frame transformations.
This type represents proper rotation matrices (orthogonal with determinant +1). All angles are in radians. The matrix uses row-major storage.
§Construction
use celestial_core::RotationMatrix3;
// Start with identity and build up rotations
let mut m = RotationMatrix3::identity();
m.rotate_z(0.1); // Rotate 0.1 radians about Z
m.rotate_x(0.05); // Then rotate 0.05 radians about X
// Or construct directly from elements
let m = RotationMatrix3::from_array([
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
]);Implementations§
Source§impl RotationMatrix3
impl RotationMatrix3
Sourcepub fn identity() -> Self
pub fn identity() -> Self
Creates the 3x3 identity matrix.
The identity matrix leaves any vector unchanged when applied. It serves as the starting point for building up rotation sequences.
use celestial_core::RotationMatrix3;
let m = RotationMatrix3::identity();
let v = [1.0, 2.0, 3.0];
let result = m.apply_to_vector(v);
assert_eq!(result, v);Sourcepub fn from_array(elements: [[f64; 3]; 3]) -> Self
pub fn from_array(elements: [[f64; 3]; 3]) -> Self
Creates a rotation matrix from a 3x3 array of elements.
The array is interpreted as row-major: elements[i][j] is row i, column j.
This does not validate that the matrix is a proper rotation. Use
is_rotation_matrix to check if needed.
use celestial_core::RotationMatrix3;
// A rotation by 90 degrees about Z
let m = RotationMatrix3::from_array([
[0.0, 1.0, 0.0],
[-1.0, 0.0, 0.0],
[0.0, 0.0, 1.0],
]);Sourcepub fn get(&self, row: usize, col: usize) -> f64
pub fn get(&self, row: usize, col: usize) -> f64
Returns the element at the specified row and column.
Indices are 0-based. Panics if row >= 3 or col >= 3.
You can also use indexing syntax: matrix[(row, col)].
Sourcepub fn set(&mut self, row: usize, col: usize, value: f64)
pub fn set(&mut self, row: usize, col: usize, value: f64)
Sets the element at the specified row and column.
Indices are 0-based. Panics if row >= 3 or col >= 3.
You can also use indexing syntax: matrix[(row, col)] = value.
Sourcepub fn elements(&self) -> &[[f64; 3]; 3]
pub fn elements(&self) -> &[[f64; 3]; 3]
Returns a reference to the underlying 3x3 array.
Useful when you need direct access to all elements, for example when passing to external APIs or serialization.
Sourcepub fn rotate_x(&mut self, phi: f64)
pub fn rotate_x(&mut self, phi: f64)
Applies a rotation about the X-axis to this matrix (in place).
The rotation angle phi is in radians. Positive angles rotate counterclockwise
when looking from the positive X-axis toward the origin (ERFA convention).
This modifies self to become Rx(phi) * self, where Rx is the standard
X-axis rotation matrix:
Rx(phi) = | 1 0 0 |
| 0 cos(phi) sin(phi)|
| 0 -sin(phi) cos(phi)|In astronomy, X-axis rotations appear in frame bias corrections and some nutation models.
use celestial_core::RotationMatrix3;
use std::f64::consts::FRAC_PI_2;
let mut m = RotationMatrix3::identity();
m.rotate_x(FRAC_PI_2); // 90 degrees
// [0, 1, 0] rotates to [0, 0, -1]
let v = m.apply_to_vector([0.0, 1.0, 0.0]);
assert!(v[0].abs() < 1e-15);
assert!(v[1].abs() < 1e-15);
assert!((v[2] + 1.0).abs() < 1e-15);Sourcepub fn rotate_z(&mut self, psi: f64)
pub fn rotate_z(&mut self, psi: f64)
Applies a rotation about the Z-axis to this matrix (in place).
The rotation angle psi is in radians. Positive angles rotate counterclockwise
when looking from the positive Z-axis toward the origin (ERFA convention).
This modifies self to become Rz(psi) * self, where Rz is the standard
Z-axis rotation matrix:
Rz(psi) = | cos(psi) sin(psi) 0 |
|-sin(psi) cos(psi) 0 |
| 0 0 1 |Z-axis rotations are ubiquitous in astronomy. Earth rotation about its axis, precession in right ascension, and rotations in longitude all use Rz.
use celestial_core::RotationMatrix3;
use std::f64::consts::FRAC_PI_2;
let mut m = RotationMatrix3::identity();
m.rotate_z(FRAC_PI_2); // 90 degrees
// [1, 0, 0] rotates to [0, -1, 0]
let v = m.apply_to_vector([1.0, 0.0, 0.0]);
assert!(v[0].abs() < 1e-15);
assert!((v[1] + 1.0).abs() < 1e-15);
assert!(v[2].abs() < 1e-15);Sourcepub fn rotate_y(&mut self, theta: f64)
pub fn rotate_y(&mut self, theta: f64)
Applies a rotation about the Y-axis to this matrix (in place).
The rotation angle theta is in radians. Positive angles rotate counterclockwise
when looking from the positive Y-axis toward the origin (ERFA convention).
This modifies self to become Ry(theta) * self, where Ry is the standard
Y-axis rotation matrix:
Ry(theta) = | cos(theta) 0 -sin(theta) |
| 0 1 0 |
| sin(theta) 0 cos(theta) |Y-axis rotations appear in obliquity of the ecliptic and some precession models.
use celestial_core::RotationMatrix3;
use std::f64::consts::FRAC_PI_2;
let mut m = RotationMatrix3::identity();
m.rotate_y(FRAC_PI_2); // 90 degrees
// [0, 0, 1] rotates to [-1, 0, 0]
let v = m.apply_to_vector([0.0, 0.0, 1.0]);
assert!((v[0] + 1.0).abs() < 1e-15);
assert!(v[1].abs() < 1e-15);
assert!(v[2].abs() < 1e-15);Sourcepub fn multiply(&self, other: &Self) -> Self
pub fn multiply(&self, other: &Self) -> Self
Multiplies this matrix by another, returning the product.
Matrix multiplication is not commutative: A * B is generally different
from B * A. The result represents the composition of two rotations where
other is applied first, then self.
You can also use the * operator: a * b or &a * &b.
use celestial_core::RotationMatrix3;
let mut rx = RotationMatrix3::identity();
rx.rotate_x(0.1);
let mut rz = RotationMatrix3::identity();
rz.rotate_z(0.2);
// First rotate by X, then by Z
let combined = rz.multiply(&rx);
// Equivalent using operator:
let combined_op = rz * rx;Sourcepub fn apply_to_vector(&self, vector: [f64; 3]) -> [f64; 3]
pub fn apply_to_vector(&self, vector: [f64; 3]) -> [f64; 3]
Applies this rotation matrix to a 3D vector.
Computes the standard matrix-vector product M * v. For coordinate
transformations, this rotates the position vector from one frame to another.
You can also use the * operator with Vector3:
matrix * vector.
use celestial_core::RotationMatrix3;
let mut m = RotationMatrix3::identity();
m.rotate_z(std::f64::consts::FRAC_PI_2); // 90 degrees
let v = [1.0, 0.0, 0.0];
let rotated = m.apply_to_vector(v);
// Result is approximately [0, -1, 0]Sourcepub fn determinant(&self) -> f64
pub fn determinant(&self) -> f64
Computes the determinant of this matrix.
For a proper rotation matrix, the determinant is always +1. A determinant of -1 indicates a reflection (improper rotation). Values far from +/-1 indicate the matrix is not orthogonal.
Used internally by is_rotation_matrix.
Sourcepub fn transpose(&self) -> Self
pub fn transpose(&self) -> Self
Returns the transpose of this matrix.
For a rotation matrix, the transpose equals the inverse. This provides a numerically stable way to compute the reverse transformation without general matrix inversion.
use celestial_core::RotationMatrix3;
let mut m = RotationMatrix3::identity();
m.rotate_z(0.5);
m.rotate_x(0.3);
let m_inv = m.transpose();
// Applying m then m_inv returns to the original
let v = [1.0, 2.0, 3.0];
let rotated = m.apply_to_vector(v);
let restored = m_inv.apply_to_vector(rotated);
assert!((restored[0] - v[0]).abs() < 1e-14);
assert!((restored[1] - v[1]).abs() < 1e-14);
assert!((restored[2] - v[2]).abs() < 1e-14);Sourcepub fn is_rotation_matrix(&self, tolerance: f64) -> bool
pub fn is_rotation_matrix(&self, tolerance: f64) -> bool
Checks whether this matrix is a valid rotation matrix within a tolerance.
A proper rotation matrix must satisfy two conditions:
- Determinant equals +1 (not -1, which would be a reflection)
- The matrix is orthogonal:
M * M^T = I
Due to floating-point arithmetic, these conditions are checked within the specified tolerance.
use celestial_core::RotationMatrix3;
let mut m = RotationMatrix3::identity();
m.rotate_z(0.5);
m.rotate_x(0.3);
assert!(m.is_rotation_matrix(1e-14));
// A scaling matrix is not a rotation
let scaled = RotationMatrix3::from_array([
[2.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
]);
assert!(!scaled.is_rotation_matrix(1e-14));Sourcepub fn max_difference(&self, other: &Self) -> f64
pub fn max_difference(&self, other: &Self) -> f64
Returns the maximum absolute difference between corresponding elements.
Useful for comparing matrices, especially when testing against reference implementations like ERFA.
use celestial_core::RotationMatrix3;
let a = RotationMatrix3::identity();
let b = RotationMatrix3::from_array([
[1.0, 0.001, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
]);
let diff = a.max_difference(&b);
assert!((diff - 0.001).abs() < 1e-15);Sourcepub fn transform_spherical(&self, ra: f64, dec: f64) -> (f64, f64)
pub fn transform_spherical(&self, ra: f64, dec: f64) -> (f64, f64)
Transforms spherical coordinates (RA, Dec or longitude, latitude) through this rotation matrix.
This is the common operation for coordinate frame transformations in astronomy. The input angles are in radians:
ra: Right ascension or longitude (azimuthal angle from X toward Y)dec: Declination or latitude (elevation from the XY plane)
Internally, this converts to a unit Cartesian vector, applies the rotation, and converts back to spherical coordinates.
The output RA is in the range (-pi, pi]. The output Dec is in [-pi/2, pi/2].
use celestial_core::RotationMatrix3;
use std::f64::consts::FRAC_PI_4;
// Rotate the equatorial coordinate system by 45 degrees in RA
let mut m = RotationMatrix3::identity();
m.rotate_z(FRAC_PI_4);
let (ra, dec) = (0.0, 0.0); // Point on equator at RA=0
let (new_ra, new_dec) = m.transform_spherical(ra, dec);
// RA shifted by -45 degrees (rotation convention), Dec unchanged
assert!((new_ra + FRAC_PI_4).abs() < 1e-14);
assert!(new_dec.abs() < 1e-14);Trait Implementations§
Source§impl Clone for RotationMatrix3
impl Clone for RotationMatrix3
Source§fn clone(&self) -> RotationMatrix3
fn clone(&self) -> RotationMatrix3
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for RotationMatrix3
impl Debug for RotationMatrix3
Source§impl Display for RotationMatrix3
impl Display for RotationMatrix3
Source§impl Mul<&RotationMatrix3> for &RotationMatrix3
impl Mul<&RotationMatrix3> for &RotationMatrix3
Source§type Output = RotationMatrix3
type Output = RotationMatrix3
* operator.Source§fn mul(self, rhs: &RotationMatrix3) -> RotationMatrix3
fn mul(self, rhs: &RotationMatrix3) -> RotationMatrix3
* operation. Read moreSource§impl Mul<&RotationMatrix3> for RotationMatrix3
impl Mul<&RotationMatrix3> for RotationMatrix3
Source§type Output = RotationMatrix3
type Output = RotationMatrix3
* operator.Source§fn mul(self, rhs: &RotationMatrix3) -> RotationMatrix3
fn mul(self, rhs: &RotationMatrix3) -> RotationMatrix3
* operation. Read moreSource§impl Mul<RotationMatrix3> for &RotationMatrix3
impl Mul<RotationMatrix3> for &RotationMatrix3
Source§type Output = RotationMatrix3
type Output = RotationMatrix3
* operator.Source§fn mul(self, rhs: RotationMatrix3) -> RotationMatrix3
fn mul(self, rhs: RotationMatrix3) -> RotationMatrix3
* operation. Read more