earths 0.0.4

High-fidelity Earth simulation engine — orbit, atmosphere, geology, hydrology, biosphere, terrain, lighting, rendering, satellites, and temporal systems with full scientific coupling
Documentation
use crate::temporal::epoch::J2000EPOCH;
use sciforge::hub::prelude::constants::AU;
pub const EARTHAXIALTILTDEG: f64 = 23.4393;
pub struct SolarPosition {
    pub azimuthdeg: f64,
    pub elevationdeg: f64,
    pub distanceau: f64,
    pub direction: [f64; 3],
}
impl SolarPosition {
    pub fn compute(juliandate: f64, latdeg: f64, londeg: f64) -> Self {
        let d = juliandate - J2000EPOCH;
        let meananomaly = (357.5291 + 0.98560028 * d) % 360.0;
        let mrad = meananomaly.to_radians();
        let equationofcenter =
            1.9148 * mrad.sin() + 0.0200 * (2.0 * mrad).sin() + 0.0003 * (3.0 * mrad).sin();
        let lvenus = (3.1761467 + 1021.3285544 * d / 36525.0) % (2.0 * std::f64::consts::PI);
        let ljupiter = (0.599546 + 145.2702853 * d / 36525.0) % (2.0 * std::f64::consts::PI);
        let perturbation = 0.00313 * (2.0 * lvenus - mrad).sin()
            + 0.00178 * (3.0 * mrad).sin()
            + 0.00077 * (ljupiter - mrad).sin();
        let eclipticlon =
            (meananomaly + equationofcenter + perturbation + 180.0 + 102.9372) % 360.0;
        let eclrad = eclipticlon.to_radians();
        let obliquityrad = EARTHAXIALTILTDEG.to_radians();
        let declination = (obliquityrad.sin() * eclrad.sin()).asin();
        let rightascension = (obliquityrad.cos() * eclrad.sin()).atan2(eclrad.cos());
        let siderealtime = (280.16 + 360.9856235 * d + londeg) % 360.0;
        let hourangle = siderealtime.to_radians() - rightascension;
        let latrad = latdeg.to_radians();
        let altitude = (latrad.sin() * declination.sin()
            + latrad.cos() * declination.cos() * hourangle.cos())
        .asin();
        let azimuth = (declination.sin() - altitude.sin() * latrad.sin())
            .atan2(altitude.cos() * latrad.cos());
        let dirx = altitude.cos() * azimuth.sin();
        let diry = altitude.sin();
        let dirz = altitude.cos() * azimuth.cos();
        Self {
            azimuthdeg: azimuth.to_degrees(),
            elevationdeg: altitude.to_degrees(),
            distanceau: 1.0 - 0.0167 * mrad.cos(),
            direction: [dirx, diry, dirz],
        }
    }
    pub fn distancem(&self) -> f64 {
        self.distanceau * AU
    }
    pub fn isabovehorizon(&self) -> bool {
        self.elevationdeg > 0.0
    }
}