use crate::frames::transforms::{mat3_vec3_mul, mean_of_date_to_itrs_matrix};
use crate::time::scales::TimeScales;
const AU_M: f64 = 149_597_870_691.0;
const RE_WGS84_M: f64 = 6_378_137.0;
const D2R: f64 = std::f64::consts::PI / 180.0;
const AS2R: f64 = D2R / 3600.0;
const JD_J2000: f64 = 2_451_545.0;
const DAYS_PER_CENTURY: f64 = 36525.0;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SunMoon {
pub sun: [f64; 3],
pub moon: [f64; 3],
}
fn ast_args(t: f64) -> [f64; 5] {
const FC: [[f64; 5]; 5] = [
[
134.96340251,
1717915923.2178,
31.8792,
0.051635,
-0.00024470,
],
[357.52910918, 129596581.0481, -0.5532, 0.000136, -0.00001149],
[
93.27209062,
1739527262.8478,
-12.7512,
-0.001037,
0.00000417,
],
[
297.85019547,
1602961601.2090,
-6.3706,
0.006593,
-0.00003169,
],
[125.04455501, -6962890.2665, 7.4722, 0.007702, -0.00005939],
];
let mut tt = [0.0_f64; 4];
tt[0] = t;
for i in 1..4 {
tt[i] = tt[i - 1] * t;
}
let mut f = [0.0_f64; 5];
for i in 0..5 {
let mut v = FC[i][0] * 3600.0;
for j in 0..4 {
v += FC[i][j + 1] * tt[j];
}
f[i] = (v * AS2R).rem_euclid(2.0 * std::f64::consts::PI);
}
f
}
pub fn sun_moon_eci(t: f64) -> SunMoon {
let f = ast_args(t);
let eps = 23.439291 - 0.0130042 * t;
let sine = (eps * D2R).sin();
let cose = (eps * D2R).cos();
let ms = 357.5277233 + 35999.05034 * t;
let ls = 280.460
+ 36000.770 * t
+ 1.914666471 * (ms * D2R).sin()
+ 0.019994643 * (2.0 * ms * D2R).sin();
let rs = AU_M
* (1.000140612 - 0.016708617 * (ms * D2R).cos() - 0.000139589 * (2.0 * ms * D2R).cos());
let sinl = (ls * D2R).sin();
let cosl = (ls * D2R).cos();
let sun = [rs * cosl, rs * cose * sinl, rs * sine * sinl];
let lm = 218.32 + 481267.883 * t + 6.29 * f[0].sin() - 1.27 * (f[0] - 2.0 * f[3]).sin()
+ 0.66 * (2.0 * f[3]).sin()
+ 0.21 * (2.0 * f[0]).sin()
- 0.19 * f[1].sin()
- 0.11 * (2.0 * f[2]).sin();
let pm = 5.13 * f[2].sin() + 0.28 * (f[0] + f[2]).sin()
- 0.28 * (f[2] - f[0]).sin()
- 0.17 * (f[2] - 2.0 * f[3]).sin();
let rm = RE_WGS84_M
/ ((0.9508
+ 0.0518 * f[0].cos()
+ 0.0095 * (f[0] - 2.0 * f[3]).cos()
+ 0.0078 * (2.0 * f[3]).cos()
+ 0.0028 * (2.0 * f[0]).cos())
* D2R)
.sin();
let sinlm = (lm * D2R).sin();
let coslm = (lm * D2R).cos();
let sinp = (pm * D2R).sin();
let cosp = (pm * D2R).cos();
let moon = [
rm * cosp * coslm,
rm * (cose * cosp * sinlm - sine * sinp),
rm * (sine * cosp * sinlm + cose * sinp),
];
SunMoon { sun, moon }
}
pub fn sun_moon_ecef(ts: &TimeScales) -> SunMoon {
let jd_tt = ts.jd_tt;
let t = (jd_tt - JD_J2000) / DAYS_PER_CENTURY;
let eci = sun_moon_eci(t);
let r = mean_of_date_to_itrs_matrix(ts);
let sun = mat3_vec3_mul(&r, &eci.sun);
let moon = mat3_vec3_mul(&r, &eci.moon);
SunMoon { sun, moon }
}