//! CONUS grid at 0.125° resolution. 1:1 port of //! `lib/microwaveprop/propagation/grid.ex`. pub const LAT_MIN: f64 = 25.0; pub const LAT_MAX: f64 = 50.0; pub const LON_MIN: f64 = -125.0; pub const LON_MAX: f64 = -66.0; pub const STEP: f64 = 0.125; #[derive(Debug, Clone, Copy, PartialEq)] pub struct GridSpec { pub lon_start: f64, pub lon_count: usize, pub lon_step: f64, pub lat_start: f64, pub lat_count: usize, pub lat_step: f64, } pub fn wgrib2_grid_spec() -> GridSpec { let lon_count = ((LON_MAX - LON_MIN) / STEP).round() as usize + 1; let lat_count = ((LAT_MAX - LAT_MIN) / STEP).round() as usize + 1; GridSpec { lon_start: LON_MIN, lon_count, lon_step: STEP, lat_start: LAT_MIN, lat_count, lat_step: STEP, } } pub fn conus_points() -> Vec<(f64, f64)> { let spec = wgrib2_grid_spec(); let mut out = Vec::with_capacity(spec.lat_count * spec.lon_count); for j in 0..spec.lat_count { let lat = round3(spec.lat_start + j as f64 * spec.lat_step); for i in 0..spec.lon_count { let lon = round3(spec.lon_start + i as f64 * spec.lon_step); out.push((lat, lon)); } } out } /// Matches Elixir's `Float.round(x, 3)` — banker's rounding isn't used, /// half-away-from-zero is. For grid coords this matches BEAM's behavior /// for the values we care about (no exact half cases). pub fn round3(x: f64) -> f64 { (x * 1000.0).round() / 1000.0 } #[cfg(test)] mod tests { use super::*; #[test] fn grid_spec_matches_elixir() { let spec = wgrib2_grid_spec(); // Elixir: lon_count = round((-66 - -125) / 0.125) + 1 = 473 // lat_count = round((50 - 25) / 0.125) + 1 = 201 assert_eq!(spec.lon_count, 473); assert_eq!(spec.lat_count, 201); assert_eq!(spec.lon_start, -125.0); assert_eq!(spec.lat_start, 25.0); assert_eq!(spec.lon_step, 0.125); assert_eq!(spec.lat_step, 0.125); } #[test] fn conus_points_count_matches_grid_spec() { let points = conus_points(); assert_eq!(points.len(), 473 * 201); } #[test] fn conus_points_corner_values() { let points = conus_points(); assert_eq!(points[0], (25.0, -125.0)); assert_eq!(points[points.len() - 1], (50.0, -66.0)); } }