Skip to main content

RotationMatrix3

Struct RotationMatrix3 

Source
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

Source

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);
Source

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],
]);
Source

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)].

Source

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.

Source

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.

Source

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);
Source

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);
Source

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);
Source

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;
Source

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]
Source

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.

Source

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);
Source

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:

  1. Determinant equals +1 (not -1, which would be a reflection)
  2. 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));
Source

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);
Source

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

Source§

fn clone(&self) -> RotationMatrix3

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RotationMatrix3

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for RotationMatrix3

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Index<(usize, usize)> for RotationMatrix3

Source§

type Output = f64

The returned type after indexing.
Source§

fn index(&self, (row, col): (usize, usize)) -> &f64

Performs the indexing (container[index]) operation. Read more
Source§

impl IndexMut<(usize, usize)> for RotationMatrix3

Source§

fn index_mut(&mut self, (row, col): (usize, usize)) -> &mut f64

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl Mul<&RotationMatrix3> for &RotationMatrix3

Source§

type Output = RotationMatrix3

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &RotationMatrix3) -> RotationMatrix3

Performs the * operation. Read more
Source§

impl Mul<&RotationMatrix3> for RotationMatrix3

Source§

type Output = RotationMatrix3

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &RotationMatrix3) -> RotationMatrix3

Performs the * operation. Read more
Source§

impl Mul<RotationMatrix3> for &RotationMatrix3

Source§

type Output = RotationMatrix3

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: RotationMatrix3) -> RotationMatrix3

Performs the * operation. Read more
Source§

impl Mul<Vector3> for &RotationMatrix3

Source§

type Output = Vector3

The resulting type after applying the * operator.
Source§

fn mul(self, vec: Vector3) -> Vector3

Performs the * operation. Read more
Source§

impl Mul<Vector3> for RotationMatrix3

Source§

type Output = Vector3

The resulting type after applying the * operator.
Source§

fn mul(self, vec: Vector3) -> Vector3

Performs the * operation. Read more
Source§

impl Mul for RotationMatrix3

Source§

type Output = RotationMatrix3

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Self) -> Self

Performs the * operation. Read more
Source§

impl PartialEq for RotationMatrix3

Source§

fn eq(&self, other: &RotationMatrix3) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for RotationMatrix3

Source§

impl StructuralPartialEq for RotationMatrix3

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.