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
pub struct ElevationProvider {
    pub resolution_arcsec: f64,
    pub data: Vec<f64>,
    pub lat_range: (f64, f64),
    pub lon_range: (f64, f64),
    pub rows: usize,
    pub cols: usize,
}
impl ElevationProvider {
    pub fn global(resolution_arcsec: f64) -> Self {
        let effective_res = resolution_arcsec.max(600.0);
        let rows = (180.0 * 3600.0 / effective_res) as usize;
        let cols = (360.0 * 3600.0 / effective_res) as usize;
        let mut data = vec![0.0; rows * cols];
        for r in 0..rows {
            for c in 0..cols {
                let lat = 90.0 - (r as f64 + 0.5) * effective_res / 3600.0;
                let lon = -180.0 + (c as f64 + 0.5) * effective_res / 3600.0;
                data[r * cols + c] = crate::terrain::heightmap::earth_elevation(lat, lon);
            }
        }
        Self {
            resolution_arcsec: effective_res,
            data,
            lat_range: (-90.0, 90.0),
            lon_range: (-180.0, 180.0),
            rows,
            cols,
        }
    }
    pub fn sample(&self, lat_deg: f64, lon_deg: f64) -> f64 {
        let lat_frac = (lat_deg - self.lat_range.0) / (self.lat_range.1 - self.lat_range.0);
        let lon_frac = (lon_deg - self.lon_range.0) / (self.lon_range.1 - self.lon_range.0);
        let row = ((1.0 - lat_frac) * (self.rows - 1) as f64).clamp(0.0, (self.rows - 1) as f64);
        let col = (lon_frac * (self.cols - 1) as f64).clamp(0.0, (self.cols - 1) as f64);
        let r0 = row as usize;
        let c0 = col as usize;
        let r1 = (r0 + 1).min(self.rows - 1);
        let c1 = (c0 + 1).min(self.cols - 1);
        let fr = row.fract();
        let fc = col.fract();
        let v00 = self.data[r0 * self.cols + c0];
        let v01 = self.data[r0 * self.cols + c1];
        let v10 = self.data[r1 * self.cols + c0];
        let v11 = self.data[r1 * self.cols + c1];
        let top = v00 * (1.0 - fc) + v01 * fc;
        let bot = v10 * (1.0 - fc) + v11 * fc;
        top * (1.0 - fr) + bot * fr
    }
    pub fn notable_elevations() -> Vec<(&'static str, f64, f64, f64)> {
        vec![
            ("Mount Everest", 27.9881, 86.9250, 8_848.86),
            ("K2", 35.8808, 76.5153, 8_611.0),
            ("Dead Sea", 31.5, 35.5, -430.5),
            ("Mariana Trench", 11.3493, 142.1996, -10_994.0),
            ("Denali", 63.0695, -151.0074, 6_190.5),
            ("Mount Kilimanjaro", -3.0674, 37.3556, 5_895.0),
        ]
    }
}