#![allow(non_snake_case)]
#![allow(clippy::excessive_precision)]
use const_soft_float::soft_f64::SoftF64;
use geographiclib_rs::Geodesic;
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
pub struct Ellipsoid {
pub A: f64,
pub B: f64,
pub E: f64,
pub F: f64,
}
impl Ellipsoid {
#[must_use]
pub const fn new(semi_major_axis: f64, inverse_flattening: f64) -> Self {
let I = inverse_flattening;
let A = semi_major_axis;
let F = SoftF64(1.0).div(SoftF64(I)).to_f64();
let B = SoftF64(A).sub(SoftF64(A).div(SoftF64(I))).to_f64();
let E = SoftF64(1.0)
.sub(SoftF64(B).powi(2).div(SoftF64(A).powi(2)))
.sqrt()
.to_f64();
Ellipsoid { A, B, E, F }
}
pub const SPHERE: Ellipsoid = Ellipsoid {
A: 6_370_997.0,
B: 6_370_997.0,
E: 0.0,
F: 0.0,
};
pub const WGS84: Ellipsoid = Ellipsoid::new(6_378_137.0, 298.257_223_563);
pub const GRS80: Ellipsoid = Ellipsoid::new(6_378_137.0, 298.257_222_101);
pub const WGS72: Ellipsoid = Ellipsoid::new(6_378_135.0, 298.26);
pub const GRS67: Ellipsoid = Ellipsoid::new(6_378_160.0, 298.247_167_427);
pub const AIRY1830: Ellipsoid = Ellipsoid::new(6_377_563.396, 299.324_964_6);
pub const WGS66: Ellipsoid = Ellipsoid::new(6_378_145.0, 298.25);
pub const WGS60: Ellipsoid = Ellipsoid::new(6_378_165.0, 298.3);
pub const CLARKE1866: Ellipsoid = Ellipsoid::new(6_378_206.4, 294.978_698_2);
}
impl From<Geodesic> for Ellipsoid {
fn from(geod: Geodesic) -> Self {
Ellipsoid {
A: geod.a,
B: geod._b,
E: (1.0 - (geod._b.powi(2) / geod.a.powi(2))).sqrt(),
F: geod.f,
}
}
}
impl From<Ellipsoid> for Geodesic {
fn from(ellps: Ellipsoid) -> Geodesic {
Geodesic::new(ellps.A, ellps.F)
}
}
#[cfg(test)]
mod tests {
use float_cmp::assert_approx_eq;
use geographiclib_rs::Geodesic;
use crate::Ellipsoid;
#[test]
fn into_geod() {
let ref_elps = Ellipsoid::WGS84;
let ref_geod = Geodesic::wgs84();
let con_geod: Geodesic = ref_elps.into();
assert_approx_eq!(f64, ref_elps.A, con_geod.a);
assert_approx_eq!(f64, ref_geod.a, con_geod.a);
assert_approx_eq!(f64, ref_elps.B, con_geod._b);
assert_approx_eq!(f64, ref_geod._b, con_geod._b);
assert_approx_eq!(f64, ref_elps.F, con_geod.f);
assert_approx_eq!(f64, ref_geod.f, con_geod.f);
}
#[test]
fn from_geod() {
let ref_elps = Ellipsoid::WGS84;
let ref_geod = Geodesic::wgs84();
let con_elps: Ellipsoid = ref_geod.into();
assert_approx_eq!(f64, ref_elps.A, con_elps.A);
assert_approx_eq!(f64, ref_geod.a, con_elps.A);
assert_approx_eq!(f64, ref_elps.B, con_elps.B);
assert_approx_eq!(f64, ref_geod._b, con_elps.B);
assert_approx_eq!(f64, ref_elps.F, con_elps.F);
assert_approx_eq!(f64, ref_geod.f, con_elps.F);
}
}