use crate::params::ParamList;
use oxiproj_core::{Ellipsoid, ProjError, ProjResult};
const DEFAULT_A: f64 = 6378137.0;
pub fn setup_ellipsoid(params: &ParamList) -> ProjResult<Ellipsoid> {
if let Some(r) = params.get_f64("R") {
return Ellipsoid::sphere(r);
}
let mut a: Option<f64> = None;
let mut es: Option<f64> = None;
let mut have_baseline = false;
let mut have_shape = false;
if let Some(name) = params.get_str("ellps") {
let base = Ellipsoid::named(name)?;
a = Some(base.a);
es = Some(base.es);
have_baseline = true;
} else if let Some(name) = params.get_str("datum") {
if let Some(d) = oxiproj_core::find_datum(name) {
let base = Ellipsoid::named(d.ellipse_id)?;
a = Some(base.a);
es = Some(base.es);
have_baseline = true;
}
}
if let Some(av) = params.get_f64("a") {
a = Some(av);
}
if let Some(rf) = params.get_f64("rf") {
if rf != 0.0 {
let f = 1.0 / rf;
es = Some(2.0 * f - f * f);
have_shape = true;
}
}
if !have_shape {
if let Some(f) = params.get_f64("f") {
es = Some(2.0 * f - f * f);
have_shape = true;
}
}
if !have_shape {
if let Some(e_s) = params.get_f64("es") {
es = Some(e_s);
have_shape = true;
}
}
if !have_shape {
if let Some(e) = params.get_f64("e") {
es = Some(e * e);
have_shape = true;
}
}
if !have_shape {
if let Some(bv) = params.get_f64("b") {
match a {
Some(av) => {
let f = (av - bv) / av;
es = Some(2.0 * f - f * f);
have_shape = true;
}
None => return Err(ProjError::IllegalArgValue),
}
}
}
if a.is_none() && !have_baseline && !have_shape {
return Ellipsoid::named("WGS84");
}
if a.is_some() && !have_baseline && !have_shape {
es = Some(0.0);
}
let a_final = a.unwrap_or(DEFAULT_A);
let es_final = es.unwrap_or(0.0);
Ellipsoid::from_a_es(a_final, es_final)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::params::parse;
#[test]
fn wgs84_by_ellps() {
let e = setup_ellipsoid(&parse("+ellps=WGS84")).unwrap();
assert_eq!(e.a, 6378137.0);
assert!((e.es - 0.0066943799901413165).abs() < 1e-15);
}
#[test]
fn sphere_by_r() {
let e = setup_ellipsoid(&parse("+R=6371000")).unwrap();
assert_eq!(e.es, 0.0);
assert_eq!(e.a, 6371000.0);
}
#[test]
fn a_and_rf() {
let e = setup_ellipsoid(&parse("+a=6378137 +rf=298.257223563")).unwrap();
let wgs84 = Ellipsoid::named("WGS84").unwrap();
assert!((e.es - wgs84.es).abs() < 1e-12);
}
#[test]
fn datum_resolves_ellipsoid() {
let e = setup_ellipsoid(&parse("+datum=WGS84")).unwrap();
assert_eq!(e.a, 6378137.0);
}
#[test]
fn a_alone_is_sphere() {
let e = setup_ellipsoid(&parse("+a=6378137")).unwrap();
assert_eq!(e.es, 0.0);
}
}