Skip to main content

lox_frames/iers/
ecliptic.rs

1// SPDX-FileCopyrightText: 2025 Helge Eichhorn <git@helgeeichhorn.de>
2//
3// SPDX-License-Identifier: MPL-2.0
4
5use fast_polynomial::poly_array;
6use lox_test_utils::ApproxEq;
7use lox_time::{Time, julian_dates::JulianDate, time_scales::Tt};
8use lox_units::Angle;
9
10use crate::iers::ReferenceSystem;
11
12impl ReferenceSystem {
13    /// Returns the mean obliquity of the ecliptic for the given IERS convention.
14    pub fn mean_obliquity(&self, time: Time<Tt>) -> MeanObliquity {
15        match self {
16            ReferenceSystem::Iers1996 | ReferenceSystem::Iers2003(_) => {
17                MeanObliquity::iau1980(time)
18            }
19            ReferenceSystem::Iers2010 => MeanObliquity::iau2006(time),
20        }
21    }
22}
23
24/// Mean obliquity of the ecliptic.
25#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, ApproxEq)]
26pub struct MeanObliquity(pub Angle);
27
28impl MeanObliquity {
29    /// Returns the mean obliquity of the ecliptic based on the IAU1980 precession model.
30    pub fn iau1980(time: Time<Tt>) -> Self {
31        let t = time.centuries_since_j2000();
32
33        Self(Angle::arcseconds(poly_array(
34            t,
35            &[84381.448, -46.8150, -0.00059, 0.001813],
36        )))
37    }
38
39    /// Returns the mean obliquity of the ecliptic based on the IAU2006 precession model.
40    pub fn iau2006(time: Time<Tt>) -> Self {
41        let t = time.centuries_since_j2000();
42
43        Self(Angle::arcseconds(poly_array(
44            t,
45            &[
46                84381.406,
47                -46.836769,
48                -0.0001831,
49                0.00200340,
50                -0.000000576,
51                -0.0000000434,
52            ],
53        )))
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use lox_test_utils::assert_approx_eq;
60
61    use super::*;
62
63    #[test]
64    fn test_mean_obliquity_iers1996() {
65        let time = Time::from_two_part_julian_date(Tt, 2400000.5, 54388.0);
66        let exp = MeanObliquity(Angle::new(0.409_075_134_764_381_6));
67        let act = ReferenceSystem::Iers1996.mean_obliquity(time);
68        assert_approx_eq!(act, exp, rtol <= 1e-14);
69    }
70
71    #[test]
72    fn test_mean_obliquity_iers2010() {
73        let time = Time::from_two_part_julian_date(Tt, 2400000.5, 54388.0);
74        let exp = MeanObliquity(Angle::new(0.409_074_922_938_725_8));
75        let act = ReferenceSystem::Iers2010.mean_obliquity(time);
76        assert_approx_eq!(act, exp, rtol <= 1e-14);
77    }
78}