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::jupitercloudtop(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 notablefeatures() -> Vec<(&'static str, f64, f64, f64)> {
vec![
("Great Red Spot", -22.0, 295.0, 8000.0),
("Oval BA", -33.0, 107.0, 4000.0),
("North Polar Vortex", 85.0, 0.0, 2000.0),
("South Polar Cyclone", -85.0, 0.0, 2500.0),
("Equatorial Plume", 7.0, 180.0, 1500.0),
]
}
}