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),
]
}
}