use bincode::{config, Decode};
use crate::prelude::Constellation;
use core::str::FromStr;
use once_cell::sync::Lazy;
use geo::{Contains, LineString, Point, Polygon};
#[derive(Decode)]
struct SbasPolygon {
name: String,
coordinates: Vec<(f64, f64)>,
}
#[derive(Default, Decode)]
struct SbasMap {
polygons: Vec<SbasPolygon>,
}
static SBAS_POLYGONS: Lazy<SbasMap> = Lazy::new(|| {
let config = config::standard();
let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/sbas_polygons.bin"));
bincode::decode_from_slice(bytes, config)
.unwrap_or_else(|e| {
panic!("corrupt SBAS polygons database: {}", e);
})
.0
});
pub fn sbas_selector(point: Point) -> Option<Constellation> {
for entry in SBAS_POLYGONS.polygons.iter() {
let polygon = Polygon::new(LineString::from(entry.coordinates.clone()), vec![]);
if polygon.contains(&point) {
if let Ok(constellation) = Constellation::from_str(&entry.name) {
return Some(constellation);
}
}
}
None
}
#[cfg(test)]
mod test {
use crate::{prelude::Constellation, sbas::SBAS_POLYGONS, sbas_selector};
use geo::Point;
use std::str::FromStr;
#[test]
fn test_database() {
for entry in SBAS_POLYGONS.polygons.iter() {
assert!(
Constellation::from_str(&entry.name).is_ok(),
"invalid constellation name found \"{}\"",
entry.name
);
}
}
#[test]
fn test_sbas_selector() {
for (lat_ddeg, long_ddeg, expected) in [
(48.808378, 2.38268, Some(Constellation::EGNOS)),
(33.981431, -118.193601, Some(Constellation::WAAS)),
(19.314290, 76.798953, Some(Constellation::GAGAN)),
(-27.579847, 131.334992, Some(Constellation::SPAN)),
(-45.113525, 169.864842, Some(Constellation::SPAN)),
(34.462967, 98.172480, Some(Constellation::GAGAN)),
(37.067846, 128.34, Some(Constellation::KASS)),
(36.081095, 138.274859, Some(Constellation::MSAS)),
(60.004390, 89.090326, Some(Constellation::SDCM)),
(-32.473320, 21.112770, Some(Constellation::ASBAS)),
(-23.216639, -63.170983, None), (-77.490631, 91.435181, None), (-29.349172, 72.773447, None), ] {
assert_eq!(
sbas_selector(Point::new(long_ddeg, lat_ddeg)),
expected,
"invalid results for coordinates lat={}° long={}°",
lat_ddeg,
long_ddeg
);
}
}
}