lox_frames/transformations/
iau.rs

1// SPDX-FileCopyrightText: 2024 Helge Eichhorn <git@helgeeichhorn.de>
2//
3// SPDX-License-Identifier: MPL-2.0
4
5use crate::transformations::rotations::Rotation;
6use crate::transformations::{TransformProvider, TryTransform};
7use glam::{DMat3, DVec3};
8use lox_bodies::TryRotationalElements;
9use lox_time::Time;
10use lox_time::offsets::TryOffset;
11use lox_time::time_scales::Tdb;
12use lox_time::{julian_dates::JulianDate, time_scales::TimeScale};
13use std::f64::consts::{FRAC_PI_2, TAU};
14
15use crate::frames::{Iau, Icrf};
16
17pub fn icrf_to_iau(
18    right_ascension: f64,
19    declination: f64,
20    rotation_angle: f64,
21    right_ascension_rate: f64,
22    declination_rate: f64,
23    rotation_rate: f64,
24) -> Rotation {
25    let m1 = DMat3::from_rotation_z(-(right_ascension + FRAC_PI_2));
26    let m2 = DMat3::from_rotation_x(-(FRAC_PI_2 - declination));
27    let m3 = DMat3::from_rotation_z(-(rotation_angle % TAU));
28    let m = m3 * m2 * m1;
29    let v = DVec3::new(right_ascension_rate, -declination_rate, rotation_rate);
30    Rotation::new(m).with_angular_velocity(v)
31}
32
33impl<T, Scale, Origin> TryTransform<Icrf, Iau<Origin>, Scale> for T
34where
35    Scale: TimeScale + Copy,
36    Origin: TryRotationalElements + Copy,
37    T: TransformProvider + TryOffset<Scale, Tdb>,
38{
39    type Error = <Self as TryOffset<Scale, Tdb>>::Error;
40
41    fn try_transform(
42        &self,
43        _origin: Icrf,
44        target: Iau<Origin>,
45        time: Time<Scale>,
46    ) -> Result<Rotation, Self::Error> {
47        let seconds = time.try_to_scale(Tdb, self)?.seconds_since_j2000();
48
49        let (right_ascension, declination, rotation_angle) = target.rotational_elements(seconds);
50        let (right_ascension_rate, declination_rate, rotation_rate) =
51            target.rotational_element_rates(seconds);
52        Ok(icrf_to_iau(
53            right_ascension,
54            declination,
55            rotation_angle,
56            right_ascension_rate,
57            declination_rate,
58            rotation_rate,
59        ))
60    }
61}
62
63impl<T, Scale, Origin> TryTransform<Iau<Origin>, Icrf, Scale> for T
64where
65    Scale: TimeScale,
66    Origin: TryRotationalElements,
67    T: TryTransform<Icrf, Iau<Origin>, Scale> + TryOffset<Scale, Tdb>,
68{
69    type Error = <Self as TryTransform<Icrf, Iau<Origin>, Scale>>::Error;
70
71    fn try_transform(
72        &self,
73        origin: Iau<Origin>,
74        target: Icrf,
75        time: Time<Scale>,
76    ) -> Result<Rotation, Self::Error> {
77        Ok(self.try_transform(target, origin, time)?.transpose())
78    }
79}