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
pub struct ElevationProvider {
    pub resolutionarcsec: f64,
    pub data: Vec<f64>,
    pub latrange: (f64, f64),
    pub lonrange: (f64, f64),
    pub rows: usize,
    pub cols: usize,
}
impl ElevationProvider {
    pub fn global(resolutionarcsec: f64) -> Self {
        let effectiveres = resolutionarcsec.max(600.0);
        let rows = (180.0 * 3600.0 / effectiveres) as usize;
        let cols = (360.0 * 3600.0 / effectiveres) 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) * effectiveres / 3600.0;
                let lon = -180.0 + (c as f64 + 0.5) * effectiveres / 3600.0;
                data[r * cols + c] = crate::terrain::heightmap::earthelevation(lat, lon);
            }
        }
        Self {
            resolutionarcsec: effectiveres,
            data,
            latrange: (-90.0, 90.0),
            lonrange: (-180.0, 180.0),
            rows,
            cols,
        }
    }
    pub fn sample(&self, latdeg: f64, londeg: f64) -> f64 {
        let latfrac = (latdeg - self.latrange.0) / (self.latrange.1 - self.latrange.0);
        let lonfrac = (londeg - self.lonrange.0) / (self.lonrange.1 - self.lonrange.0);
        let row = ((1.0 - latfrac) * (self.rows - 1) as f64).clamp(0.0, (self.rows - 1) as f64);
        let col = (lonfrac * (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 notableelevations() -> Vec<(&'static str, f64, f64, f64)> {
        vec![
            ("Mount Everest", 27.9881, 86.9250, 8848.86),
            ("K2", 35.8808, 76.5153, 8611.0),
            ("Dead Sea", 31.5, 35.5, -430.5),
            ("Mariana Trench", 11.3493, 142.1996, -10994.0),
            ("Denali", 63.0695, -151.0074, 6190.5),
            ("Mount Kilimanjaro", -3.0674, 37.3556, 5895.0),
        ]
    }
}