use crate::consts::methods;
use crate::model::Parameter;
use crate::params::ParamMapping;
pub struct MethodMapping {
wkt2_name: &'static str,
epsg_code: &'static str,
wkt1_name: &'static str,
proj_name: &'static str,
proj_aux: &'static str,
param_mapping: &'static [&'static ParamMapping],
}
impl MethodMapping {
pub fn proj_name(&self) -> &'static str {
self.proj_name
}
pub fn proj_aux(&self) -> &'static str {
self.proj_aux
}
pub fn find_proj_param(&self, p: &Parameter) -> Option<&ParamMapping> {
if p.name.is_empty() {
None
} else if let Some(auth) = &p.authority {
if auth.name == "EPSG" {
self.param_mapping
.iter()
.find(|pp| !pp.proj_name.is_empty() && pp.epsg_code == auth.code)
} else {
None
}
} else {
self.param_mapping.iter().find(|pp| {
pp.wkt2_name.eq_ignore_ascii_case(p.name)
|| pp.wkt1_name.eq_ignore_ascii_case(p.name)
})
}
.copied()
}
}
macro_rules! method {
{$wkt2:ident, $wkt1_name:expr, $proj_name:expr, $proj_aux:expr,
$mapping:expr} => {
MethodMapping {
wkt2_name: methods::$wkt2.name,
epsg_code: methods::$wkt2.code,
wkt1_name: $wkt1_name,
proj_name: $proj_name,
proj_aux: $proj_aux,
param_mapping: $mapping,
}
};
}
mod parameters {
use crate::params::{self, ParamMapping};
pub const NAT_ORIGIN: [&ParamMapping; 4] = [
¶ms::LATITUDE_NAT_ORIGIN,
¶ms::LONGITUDE_NAT_ORIGIN,
¶ms::FALSE_EASTING,
¶ms::FALSE_NORTHING,
];
pub const LONG_NAT_ORIGIN: [&ParamMapping; 3] = [
¶ms::LONGITUDE_NAT_ORIGIN,
¶ms::FALSE_EASTING,
¶ms::FALSE_NORTHING,
];
pub const NAT_ORIGIN_SCALE_K: [&ParamMapping; 5] = [
¶ms::LATITUDE_NAT_ORIGIN,
¶ms::LONGITUDE_NAT_ORIGIN,
¶ms::SCALE_FACTOR_K,
¶ms::FALSE_EASTING,
¶ms::FALSE_NORTHING,
];
pub const LCC_1SP: [&ParamMapping; 5] = [
¶ms::LAT_LCC_1SP,
¶ms::LONGITUDE_NAT_ORIGIN,
¶ms::SCALE_FACTOR,
¶ms::FALSE_EASTING,
¶ms::FALSE_NORTHING,
];
pub const LCC_2SP: [&ParamMapping; 6] = [
¶ms::LATITUDE_FALSE_ORIGIN,
¶ms::LONGITUDE_FALSE_ORIGIN,
¶ms::LATITUDE_1ST_STD_PARALLEL,
¶ms::LATITUDE_2ND_STD_PARALLEL,
¶ms::FALSE_EASTING_ORIGIN,
¶ms::FALSE_NORTHING_ORIGIN,
];
pub const LCC_2SP_MICHIGAN: [&ParamMapping; 7] = [
¶ms::LATITUDE_FALSE_ORIGIN,
¶ms::LONGITUDE_FALSE_ORIGIN,
¶ms::LATITUDE_1ST_STD_PARALLEL,
¶ms::LATITUDE_2ND_STD_PARALLEL,
¶ms::FALSE_EASTING_ORIGIN,
¶ms::FALSE_NORTHING_ORIGIN,
¶ms::ELLIPSOID_SCALE_FACTOR,
];
pub const AEA: [&ParamMapping; 6] = [
¶ms::LAT_FALSE_ORIGIN_LAT_OF_CENTER,
¶ms::LONG_FALSE_ORIGIN_LONG_OF_CENTER,
¶ms::LATITUDE_1ST_STD_PARALLEL,
¶ms::LATITUDE_2ND_STD_PARALLEL,
¶ms::FALSE_EASTING_ORIGIN,
¶ms::FALSE_NORTHING_ORIGIN,
];
pub const LAEA: [&ParamMapping; 4] = [
¶ms::LAT_NAT_LAT_CENTER,
¶ms::LONG_NAT_LONG_CENTER,
¶ms::FALSE_EASTING,
¶ms::FALSE_NORTHING,
];
pub const MERC_1SP: [&ParamMapping; 5] = [
¶ms::LAT_MERC_1SP,
¶ms::LONGITUDE_NAT_ORIGIN,
¶ms::SCALE_FACTOR_K,
¶ms::FALSE_EASTING,
¶ms::FALSE_NORTHING,
];
pub const MERC_2SP: [&ParamMapping; 4] = [
¶ms::LAT_1ST_PARALLEL_LAT_TS,
¶ms::LONGITUDE_NAT_ORIGIN,
¶ms::FALSE_EASTING,
¶ms::FALSE_NORTHING,
];
pub const POLAR_STEREO: [&ParamMapping; 4] = [
¶ms::LAT_STD_PARALLEL,
¶ms::LONG_ORIGIN,
¶ms::FALSE_EASTING,
¶ms::FALSE_NORTHING,
];
pub const OBLIQUE_STEREO: [&ParamMapping; 5] = [
¶ms::LATITUDE_NAT_ORIGIN,
¶ms::LONGITUDE_NAT_ORIGIN,
¶ms::SCALE_FACTOR_K,
¶ms::FALSE_EASTING,
¶ms::FALSE_NORTHING,
];
}
pub const METHOD_MAPPINGS: [MethodMapping; 19] = [
method! {TRANSVERSE_MERCATOR, "Transverse_Mercator", "tmerc", "", ¶meters::NAT_ORIGIN_SCALE_K},
method! {TRANSVERSE_MERCATOR_SOUTH_ORIENTATED, "Transverse_Mercator_South_Orientated", "tmerc", "+axis=wsu",
¶meters::NAT_ORIGIN_SCALE_K},
method! {ALBERS_EQUAL_AREA, "Albers_Conic_Equal_Area", "aea", "", ¶meters::AEA},
method! {LAMBERT_CONIC_CONFORMAL_1SP, "Lambert_Conformal_Conic_1SP", "lcc", "", ¶meters::LCC_1SP},
method! {LAMBERT_CONIC_CONFORMAL_2SP, "Lambert_Conformal_Conic_2SP", "lcc", "",
¶meters::LCC_2SP},
method! {LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN, "", "lcc", "", ¶meters::LCC_2SP_MICHIGAN},
method! {LAMBERT_CONIC_CONFORMAL_2SP_BELGIUM, "Lambert_Conformal_Conic_2SP_Belgium", "lcc", "",
¶meters::LCC_2SP},
method! {LAMBERT_AZIMUTHAL_EQUAL_AREA, "Lambert_Azimuthal_Equal_Area", "laea", "", ¶meters::LAEA},
method! {LAMBERT_AZIMUTHAL_EQUAL_AREA_SPHERICAL, "Lambert_Azimuthal_Equal_Area", "laea", "+R_A",
¶meters::LAEA},
method! {MERCATOR_VARIANT_A, "Mercator_1SP", "merc", "", ¶meters::MERC_1SP},
method! {MERCATOR_VARIANT_B, "Mercator_2SP", "merc", "", ¶meters::MERC_2SP},
method! {POPULAR_VISUALISATION_PSEUDO_MERCATOR, "Popular_Visualisation_Pseudo_Mercator", "webmerc", "",
¶meters::NAT_ORIGIN},
method! {PROJ_WKT2_NAME_MOLLWEIDE, "Mollweide", "moll", "", ¶meters::LONG_NAT_ORIGIN},
method! {PROJ_WKT2_NAME_WAGNER_IV, "Wagner_IV", "wag4", "", ¶meters::LONG_NAT_ORIGIN},
method! {PROJ_WKT2_NAME_WAGNER_V, "Wagner_V", "wag5", "", ¶meters::LONG_NAT_ORIGIN},
method! {OBLIQUE_STEREOGRAPHIC, "Oblique_Stereographic", "sterea", "",
¶meters::OBLIQUE_STEREO},
method! {POLAR_STEREOGRAPHIC_VARIANT_A, "Polar_Stereographic", "stere", "", ¶meters::OBLIQUE_STEREO},
method! {POLAR_STEREOGRAPHIC_VARIANT_B, "Polar_Stereographic", "stere", "", ¶meters::POLAR_STEREO},
method! {PROJ_WKT2_NAME_METHOD_STEREOGRAPHIC, "Stereographic", "stere", "", ¶meters::OBLIQUE_STEREO},
];
use crate::model::Method;
pub fn find_method_mapping(me: &Method) -> Option<&'static MethodMapping> {
if me.name.is_empty() {
None
} else if let Some(auth) = &me.authority {
METHOD_MAPPINGS
.iter()
.find(|m| auth.name == "EPSG" && m.epsg_code == auth.code)
} else {
METHOD_MAPPINGS.iter().find(|m| {
m.wkt2_name.eq_ignore_ascii_case(me.name) || m.wkt1_name.eq_ignore_ascii_case(me.name)
})
}
}