gistools/proj/project/
goode.rs

1use crate::proj::{
2    CoordinateStep, MollweideProjection, Proj, ProjectCoordinates, SinusoidalProjection,
3    TransformCoordinates,
4};
5use alloc::rc::Rc;
6use core::cell::RefCell;
7use libm::fabs;
8
9const Y_COR: f64 = 0.05280;
10const PHI_LIM: f64 = 0.710_930_781_979_023_6;
11
12/// Goode Homolosine Variables
13#[derive(Debug, Clone, PartialEq)]
14pub struct GoodeData {
15    sinu: SinusoidalProjection,
16    moll: MollweideProjection,
17}
18
19/// Goode Homolosine Projection
20#[derive(Debug, Clone, PartialEq)]
21pub struct GoodeHomolosineProjection {
22    proj: Rc<RefCell<Proj>>,
23    store: RefCell<GoodeData>,
24}
25impl ProjectCoordinates for GoodeHomolosineProjection {
26    fn code(&self) -> i64 {
27        -1
28    }
29    fn name(&self) -> &'static str {
30        "Goode Homolosine"
31    }
32    fn names() -> &'static [&'static str] {
33        &["Goode Homolosine", "goode"]
34    }
35}
36impl CoordinateStep for GoodeHomolosineProjection {
37    fn new(proj: Rc<RefCell<Proj>>) -> Self {
38        proj.borrow_mut().es = 0.;
39        let sinu = SinusoidalProjection::new(proj.clone());
40        let moll = MollweideProjection::new(proj.clone());
41        let store = GoodeData { sinu, moll };
42
43        GoodeHomolosineProjection { proj, store: store.into() }
44    }
45    fn forward<P: TransformCoordinates>(&self, p: &mut P) {
46        goode_s_forward(&self.store.borrow(), p);
47    }
48    fn inverse<P: TransformCoordinates>(&self, p: &mut P) {
49        goode_s_inverse(&self.store.borrow(), p);
50    }
51}
52
53/// Goode Homolosine Spheroidal forward project
54pub fn goode_s_forward<P: TransformCoordinates>(goode: &GoodeData, p: &mut P) {
55    if fabs(p.phi()) <= PHI_LIM {
56        goode.sinu.forward(p);
57    } else {
58        goode.moll.forward(p);
59        p.set_y(p.y() - if p.phi() >= 0. { Y_COR } else { -Y_COR });
60    }
61}
62
63/// Goode Homolosine Spheroidal inverse project
64pub fn goode_s_inverse<P: TransformCoordinates>(goode: &GoodeData, p: &mut P) {
65    if fabs(p.y()) <= PHI_LIM {
66        goode.sinu.inverse(p);
67    } else {
68        p.set_y(if p.y() >= 0. { Y_COR } else { -Y_COR });
69        goode.moll.inverse(p);
70    }
71}