use crate::errors::{Error, Result};
use crate::transform::Direction;
mod catlg;
mod grid;
pub use catlg::{catalog, Catalog, GridRef};
#[cfg(not(target_arch = "wasm32"))]
mod header;
#[cfg(not(target_arch = "wasm32"))]
pub mod files;
use std::ops::ControlFlow;
pub(crate) use grid::Lp;
pub(crate) use grid::{Grid, GridId};
#[derive(Debug, Clone)]
pub struct NadGrids(Vec<GridRef>);
impl PartialEq for NadGrids {
fn eq(&self, other: &Self) -> bool {
self.0.is_empty() && other.0.is_empty()
}
}
impl NadGrids {
pub fn apply_shift(
&self,
dir: Direction,
lam: f64,
phi: f64,
z: f64,
) -> Result<(f64, f64, f64)> {
if self.0.is_empty() {
return Ok((lam, phi, z));
}
let mut iter = self.0.iter();
let mut candidate = iter.find(|g| g.is_root() && g.matches(lam, phi, z));
if let Some(grid) = candidate {
iter.try_fold(grid, |grid, g| {
if !g.is_child_of(grid) {
ControlFlow::Break(())
} else if g.matches(lam, phi, z) {
candidate.replace(g);
ControlFlow::Continue(g)
} else {
ControlFlow::Continue(grid)
}
});
}
match candidate {
Some(g) => g.nad_cvt(dir, lam, phi, z),
None => Err(Error::PointOutsideNadShiftArea),
}
}
pub fn new_grid_transform(names: &str) -> Result<Self> {
let mut v: Vec<GridRef> = vec![];
match names.split(',').try_for_each(|s| {
let s = s.trim();
if s == "@null" || s == "null" {
ControlFlow::Break(true)
} else if let Some(s) = s.strip_prefix('@') {
catalog::find_grids(s, &mut v);
ControlFlow::Continue(())
} else {
if catalog::find_grids(s, &mut v) {
ControlFlow::Continue(())
} else {
ControlFlow::Break(false)
}
}
}) {
ControlFlow::Break(true) => Ok(Self(v)),
ControlFlow::Break(false) => Err(Error::NadGridNotAvailable),
_ => {
if v.is_empty() {
Err(Error::NadGridNotAvailable)
} else {
Ok(Self(v))
}
}
}
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}