pub use lcc::{Params as LccParams, Projection as Lcc};
pub use merc::{Params as MercParams, Projection as Merc};
pub trait Project {
fn forward(&self, xy: &(f64, f64)) -> Result<(f64, f64), &'static str>;
fn inverse(&self, xy: &(f64, f64)) -> Result<(f64, f64), &'static str>;
fn a(&self) -> &f64;
fn lam0(&self) -> &f64;
fn project(&self, xy: &(f64, f64), inverse: bool) -> Result<(f64, f64), &'static str> {
if inverse {
let &(x, y) = xy;
let x = x / self.a();
let y = y / self.a();
let (lambda, phi) = self.inverse(&(x, y))?;
let lambda = helpers::normalize_longitude(lambda + self.lam0());
Ok((lambda, phi))
} else {
let &(lambda, phi) = xy;
let lambda = helpers::normalize_longitude(lambda - self.lam0());
let (x, y) = self.forward(&(lambda, phi))?;
let x = x * self.a();
let y = y * self.a();
Ok((x, y))
}
}
}
#[cfg(feature = "gridpoints-proj")]
pub(crate) trait OsgeoProj {
fn proj_args(&self) -> String;
}
pub struct StereParams {
pub ellipsoid: Ellipsoid,
pub lat_ts: f64,
pub lat_0: f64,
pub lon_0: f64,
}
#[cfg(feature = "gridpoints-proj")]
impl OsgeoProj for StereParams {
fn proj_args(&self) -> String {
let Self {
ellipsoid: Ellipsoid { a, b, .. },
lat_ts,
lat_0,
lon_0,
} = self;
format!("+a={a} +b={b} +proj=stere +lat_ts={lat_ts} +lat_0={lat_0} +lon_0={lon_0}")
}
}
pub struct Ellipsoid {
pub a: f64,
pub b: f64,
pub e: f64,
pub e_sq: f64,
}
impl Ellipsoid {
pub fn from_a_and_b(a: f64, b: f64) -> Self {
let f = (a - b) / a;
let e_sq = 2. * f - f * f;
let e = e_sq.sqrt();
Self { a, b, e, e_sq }
}
}
mod helpers;
mod lcc;
mod merc;