use crate::errors::{Error, Result};
use crate::parameters::ParamList;
use crate::proj::ProjData;
use crate::projections::{estmerc, etmerc};
super::projection! { tmerc }
#[derive(Debug, Clone)]
pub(crate) enum Projection {
Exact(etmerc::Projection),
Approx(estmerc::Projection),
}
use Projection::*;
impl Projection {
const ALG_PARAM: &'static str = "algo";
pub fn tmerc(p: &mut ProjData, params: &ParamList) -> Result<Self> {
if p.ellps.is_sphere() || params.check_option("approx")? {
Ok(Approx(estmerc::Projection::estmerc(p, params)?))
} else {
match params.try_value(Self::ALG_PARAM)? {
Some("evenden_snyder") => Ok(Approx(estmerc::Projection::estmerc(p, params)?)),
Some("poder_engsager") | None => Ok(Exact(etmerc::Projection::etmerc(p, params)?)),
Some(_) => Err(Error::InvalidParameterValue(Self::ALG_PARAM)),
}
}
}
pub fn forward(&self, lam: f64, phi: f64, z: f64) -> Result<(f64, f64, f64)> {
match self {
Exact(p) => p.forward(lam, phi, z),
Approx(p) => p.forward(lam, phi, z),
}
}
pub fn inverse(&self, x: f64, y: f64, z: f64) -> Result<(f64, f64, f64)> {
match self {
Exact(p) => p.inverse(x, y, z),
Approx(p) => p.inverse(x, y, z),
}
}
pub const fn has_inverse() -> bool {
true
}
pub const fn has_forward() -> bool {
true
}
}
#[cfg(test)]
mod tests {
use crate::math::consts::EPS_10;
use crate::proj::Proj;
use crate::tests::utils::{test_proj_forward, test_proj_inverse};
#[test]
fn proj_estmerc_ell() {
let p = Proj::from_proj_string("+proj=tmerc +ellps=GRS80 +approx").unwrap();
println!("{:#?}", p.data());
println!("{:#?}", p.projection());
let inputs = [
((2., 1., 0.), (222650.79679577847, 110642.22941192707, 0.)),
((2., -1., 0.), (222650.79679577847, -110642.22941192707, 0.)),
((-2., 1., 0.), (-222650.79679577847, 110642.22941192707, 0.)),
(
(-2., -1., 0.),
(-222650.79679577847, -110642.22941192707, 0.),
),
];
test_proj_forward(&p, &inputs, EPS_10);
test_proj_inverse(&p, &inputs, EPS_10);
}
#[test]
fn proj_estmerc_sph() {
let p = Proj::from_proj_string("+proj=tmerc +R=6400000").unwrap();
println!("{:#?}", p.data());
println!("{:#?}", p.projection());
let inputs = [
((2., 1., 0.), (223413.46640632232, 111769.14504059685, 0.)),
((2., -1., 0.), (223413.46640632232, -111769.14504059685, 0.)),
((-2., 1., 0.), (-223413.46640632208, 111769.14504059685, 0.)),
(
(-2., -1., 0.),
(-223413.46640632208, -111769.14504059685, 0.),
),
];
test_proj_forward(&p, &inputs, EPS_10);
test_proj_inverse(&p, &inputs, EPS_10);
}
}