use super::error::FeaturesError;
pub const CRS84_URI: &str = "http://www.opengis.net/def/crs/OGC/1.3/CRS84";
pub const EPSG4326_URI: &str = "http://www.opengis.net/def/crs/EPSG/0/4326";
pub const EPSG3857_URI: &str = "http://www.opengis.net/def/crs/EPSG/0/3857";
pub const EPSG4258_URI: &str = "http://www.opengis.net/def/crs/EPSG/0/4258";
pub const EPSG25832_URI: &str = "http://www.opengis.net/def/crs/EPSG/0/25832";
pub const EPSG25833_URI: &str = "http://www.opengis.net/def/crs/EPSG/0/25833";
const EARTH_RADIUS_M: f64 = 6_378_137.0;
const PI: f64 = std::f64::consts::PI;
pub struct CrsTransform;
impl CrsTransform {
pub fn supported_crs_uris() -> Vec<String> {
vec![
CRS84_URI.to_string(),
EPSG4326_URI.to_string(),
EPSG3857_URI.to_string(),
EPSG4258_URI.to_string(),
EPSG25832_URI.to_string(),
EPSG25833_URI.to_string(),
]
}
pub fn bbox_to_wgs84(bbox: [f64; 4], source_crs: &str) -> Result<[f64; 4], FeaturesError> {
match source_crs {
CRS84_URI | EPSG4326_URI | EPSG4258_URI => Ok(bbox),
EPSG3857_URI => {
let lon_min = bbox[0] / EARTH_RADIUS_M * (180.0 / PI);
let lat_min =
(2.0 * (bbox[1] / EARTH_RADIUS_M).exp().atan() - PI / 2.0) * (180.0 / PI);
let lon_max = bbox[2] / EARTH_RADIUS_M * (180.0 / PI);
let lat_max =
(2.0 * (bbox[3] / EARTH_RADIUS_M).exp().atan() - PI / 2.0) * (180.0 / PI);
Ok([lon_min, lat_min, lon_max, lat_max])
}
other => Err(FeaturesError::InvalidCrs(format!(
"CRS not supported for bbox transformation: {other}"
))),
}
}
pub fn is_supported(uri: &str) -> bool {
matches!(
uri,
CRS84_URI | EPSG4326_URI | EPSG3857_URI | EPSG4258_URI | EPSG25832_URI | EPSG25833_URI
)
}
}