use crate::{TransBuild, TransParams};
use oxiproj_core::{Coord, IoUnits, Operation, ProjResult};
#[derive(Debug)]
struct Set {
v: [Option<f64>; 4],
}
impl Set {
fn apply(&self, c: Coord) -> Coord {
let mut a = c.v();
for (i, slot) in self.v.iter().enumerate() {
if let Some(val) = *slot {
a[i] = val;
}
}
Coord::new(a[0], a[1], a[2], a[3])
}
}
impl Operation for Set {
fn forward_4d(&self, c: Coord) -> ProjResult<Coord> {
Ok(self.apply(c))
}
fn inverse_4d(&self, c: Coord) -> ProjResult<Coord> {
Ok(self.apply(c))
}
fn has_inverse(&self) -> bool {
true
}
}
pub fn new(p: &TransParams) -> ProjResult<TransBuild> {
let pa = p.params;
let v = [
pa.get_f64("v_1"),
pa.get_f64("v_2"),
pa.get_f64("v_3"),
pa.get_f64("v_4"),
];
Ok(TransBuild::new(
Box::new(Set { v }),
IoUnits::Whatever,
IoUnits::Whatever,
))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::TransParamLookup;
use oxiproj_core::Ellipsoid;
struct SetV3;
impl TransParamLookup for SetV3 {
fn get_dms(&self, _key: &str) -> Option<f64> {
None
}
fn get_f64(&self, key: &str) -> Option<f64> {
if key == "v_3" {
Some(0.0)
} else {
None
}
}
fn get_int(&self, _key: &str) -> Option<i64> {
None
}
fn get_str(&self, _key: &str) -> Option<&str> {
None
}
fn get_bool(&self, _key: &str) -> bool {
false
}
fn exists(&self, key: &str) -> bool {
key == "v_3"
}
}
#[test]
fn set_v3_overwrites_slot2() {
let ell = Ellipsoid::named("WGS84").unwrap();
let b = new(&TransParams {
ellipsoid: &ell,
params: &SetV3,
registry: None,
})
.unwrap();
let op = b.operation;
let fwd = op.forward_4d(Coord::new(12.0, 55.0, 100.0, 5.0)).unwrap();
assert_eq!(fwd.v(), [12.0, 55.0, 0.0, 5.0]);
let inv = op.inverse_4d(Coord::new(12.0, 55.0, 100.0, 5.0)).unwrap();
assert_eq!(inv.v(), [12.0, 55.0, 0.0, 5.0]);
assert!(op.has_inverse());
}
}