use oxiproj_core::{Coord, Lp, Operation, ProjResult, Xy};
#[derive(Debug)]
pub struct Pipeline {
pub steps: Vec<crate::pj::Pj>,
}
impl Operation for Pipeline {
fn forward_4d(&self, c: Coord) -> ProjResult<Coord> {
let mut point = c;
for step in &self.steps {
if point.is_error() {
return Ok(Coord::error());
}
point = step.forward_4d(point)?;
}
Ok(point)
}
fn inverse_4d(&self, c: Coord) -> ProjResult<Coord> {
let mut point = c;
for step in self.steps.iter().rev() {
if point.is_error() {
return Ok(Coord::error());
}
point = step.inverse_4d(point)?;
}
Ok(point)
}
fn forward_2d(&self, lp: Lp) -> ProjResult<Xy> {
let c = self.forward_4d(Coord::new(lp.lam, lp.phi, 0.0, 0.0))?;
Ok(c.xy())
}
fn inverse_2d(&self, xy: Xy) -> ProjResult<Lp> {
let c = self.inverse_4d(Coord::new(xy.x, xy.y, 0.0, 0.0))?;
Ok(c.lp())
}
}
#[cfg(test)]
mod tests {
use super::*;
use oxiproj_core::DEG_TO_RAD;
#[test]
fn utm_forward_then_inverse_round_trips() {
let step0 = crate::create::create("+proj=utm +zone=32 +ellps=WGS84").unwrap();
let mut step1 = crate::create::create("+proj=utm +zone=32 +ellps=WGS84").unwrap();
step1.inverted = true;
let pipe = Pipeline {
steps: vec![step0, step1],
};
let input = Coord::new(12.0 * DEG_TO_RAD, 55.0 * DEG_TO_RAD, 0.0, 0.0);
let out = pipe.forward_4d(input).unwrap();
let o = out.v();
assert!((o[0] - 12.0 * DEG_TO_RAD).abs() < 1e-9, "lam got {}", o[0]);
assert!((o[1] - 55.0 * DEG_TO_RAD).abs() < 1e-9, "phi got {}", o[1]);
}
}