gistools/proj/project/
goode.rs1use 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#[derive(Debug, Clone, PartialEq)]
14pub struct GoodeData {
15 sinu: SinusoidalProjection,
16 moll: MollweideProjection,
17}
18
19#[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
53pub 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
63pub 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}