earths 0.0.1

High-fidelity Earth simulation engine — orbit, atmosphere, geology, hydrology, biosphere, terrain, lighting, rendering, satellites, and temporal systems with full scientific coupling
Documentation
use crate::lighting::solar_position::SolarPosition;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum DaylightState {
    Day,
    CivilTwilight,
    NauticalTwilight,
    AstronomicalTwilight,
    Night,
}
pub struct DayNightCycle {
    pub julian_date: f64,
}
impl DayNightCycle {
    pub fn new(julian_date: f64) -> Self {
        Self { julian_date }
    }
    pub fn state_at(&self, lat_deg: f64, lon_deg: f64) -> DaylightState {
        let sun = SolarPosition::compute(self.julian_date, lat_deg, lon_deg);
        match sun.elevation_deg {
            e if e > 0.0 => DaylightState::Day,
            e if e > -6.0 => DaylightState::CivilTwilight,
            e if e > -12.0 => DaylightState::NauticalTwilight,
            e if e > -18.0 => DaylightState::AstronomicalTwilight,
            _ => DaylightState::Night,
        }
    }
    pub fn terminator_points(&self, num_points: usize) -> Vec<[f64; 2]> {
        let mut points = Vec::with_capacity(num_points);
        for i in 0..num_points {
            let lon = -180.0 + 360.0 * i as f64 / num_points as f64;
            let mut lat_low = -90.0_f64;
            let mut lat_high = 90.0_f64;
            for _ in 0..30 {
                let lat_mid = (lat_low + lat_high) / 2.0;
                let sun = SolarPosition::compute(self.julian_date, lat_mid, lon);
                if sun.elevation_deg > 0.0 {
                    lat_low = lat_mid;
                } else {
                    lat_high = lat_mid;
                }
            }
            points.push([(lat_low + lat_high) / 2.0, lon]);
        }
        points
    }
    pub fn ambient_light(&self, lat_deg: f64, lon_deg: f64) -> f64 {
        let sun = SolarPosition::compute(self.julian_date, lat_deg, lon_deg);
        let e = sun.elevation_deg;
        if e > 10.0 {
            1.0
        } else if e > 0.0 {
            0.5 + 0.5 * (e / 10.0) * (e / 10.0)
        } else if e > -6.0 {
            0.5 * (10.0_f64).powf(e / 6.0)
        } else if e > -12.0 {
            0.05 * (10.0_f64).powf((e + 6.0) / 6.0)
        } else if e > -18.0 {
            0.005 * (10.0_f64).powf((e + 12.0) / 6.0)
        } else {
            0.001
        }
    }
}