gistools/proj/transform/
mod.rs

1/// Stepping Guide
2pub mod step;
3/// Transformer is a tool to convert between projections
4pub mod transformer;
5
6use super::{BaseProjection, Coords, Proj};
7use alloc::{boxed::Box, rc::Rc};
8use core::cell::RefCell;
9use s2json::VectorPoint;
10pub use step::*;
11pub use transformer::*;
12
13/// A Projection Transform Definition
14/// Temporary placeholder
15#[derive(Debug, Clone, PartialEq)]
16pub struct ProjectionTransform {
17    /// Projection guide
18    pub proj: Rc<RefCell<Proj>>,
19    /// mutation method
20    pub method: Step,
21    // These PJs are used for implementing cs2cs style coordinate handling in the 4D API
22    /// Axis swapping if needed
23    pub axisswap: Option<Box<ProjectionTransform>>,
24    /// Cartesian if needed
25    pub cart: Option<Box<ProjectionTransform>>,
26    /// Cartesian to WGS84 if needed
27    pub cart_wgs84: Option<Box<ProjectionTransform>>,
28    /// Helmert if needed
29    pub helmert: Option<Box<ProjectionTransform>>,
30    /// Horizontal grid shift if needed
31    pub hgridshift: Option<Box<ProjectionTransform>>,
32    /// Vertical grid shift if needed
33    pub vgridshift: Option<Box<ProjectionTransform>>,
34}
35impl Default for ProjectionTransform {
36    fn default() -> Self {
37        let proj = Rc::new(RefCell::new(Proj::default()));
38        let method = BaseProjection::new(proj.clone());
39        Self {
40            proj,
41            method: method.into(),
42            axisswap: None,
43            cart: None,
44            cart_wgs84: None,
45            helmert: None,
46            hgridshift: None,
47            vgridshift: None,
48        }
49    }
50}
51impl ProjectionTransform {
52    /// Create the WGS 84 definition
53    pub fn wgs84() -> Self {
54        Self {
55            proj: Rc::new(RefCell::new(Proj::default())),
56            method: BaseProjection::to_step(),
57            axisswap: None,
58            cart: None,
59            cart_wgs84: None,
60            helmert: None,
61            hgridshift: None,
62            vgridshift: None,
63        }
64    }
65}
66
67/// Projection trait to modify a Point's values
68///
69/// You only need to implement `x`, `y`, `z`, and `t`. The rest is for internal use
70pub trait TransformCoordinates: Clone + Default {
71    /// Get Geodetic X coordinates
72    fn x(&self) -> f64;
73    /// Get Geodetic Y coordinates
74    fn y(&self) -> f64;
75    /// Get Geodetic Z coordinates
76    fn z(&self) -> f64;
77    /// Get the temporal coordinate
78    fn t(&self) -> f64;
79    /// Set Geodetic X coordinates
80    fn set_x(&mut self, x: f64);
81    /// Set Geodetic Y coordinates
82    fn set_y(&mut self, y: f64);
83    /// Set Geodetic Z coordinates
84    fn set_z(&mut self, z: f64);
85    /// Set the temporal coordinate
86    fn set_t(&mut self, t: f64);
87
88    // Top level get and set
89    /// Get a coordinate at index
90    fn get(&self, idx: usize) -> f64 {
91        match idx {
92            0 => self.x(),
93            1 => self.y(),
94            2 => self.z(),
95            3 => self.t(),
96            _ => panic!("Invalid index"),
97        }
98    }
99    /// Set a coordinate at index
100    fn set(&mut self, idx: usize, val: f64) {
101        match idx {
102            0 => self.set_x(val),
103            1 => self.set_y(val),
104            2 => self.set_z(val),
105            3 => self.set_t(val),
106            _ => panic!("Invalid index"),
107        }
108    }
109
110    // All X based convenience methods
111
112    /// Get U
113    fn u(&self) -> f64 {
114        self.x()
115    }
116    /// Set U
117    fn set_u(&mut self, u: f64) {
118        self.set_x(u)
119    }
120    /// Get lambda (radial longitude)
121    fn lam(&self) -> f64 {
122        self.x()
123    }
124    /// Set lambda (radial longitude)
125    fn set_lam(&mut self, lam: f64) {
126        self.set_x(lam)
127    }
128    /// Get S (Geodesic length)
129    fn s(&self) -> f64 {
130        self.x()
131    }
132    /// Set S (Geodesic length)
133    fn set_s(&mut self, s: f64) {
134        self.set_x(s)
135    }
136    /// Get Omega (Rotation)
137    fn o(&self) -> f64 {
138        self.x()
139    }
140    /// Set Omega (Rotation)
141    fn set_o(&mut self, o: f64) {
142        self.set_x(o)
143    }
144    /// Get East (Directional coordinate)
145    fn e(&self) -> f64 {
146        self.x()
147    }
148    /// Set East (Directional coordinate)
149    fn set_e(&mut self, e: f64) {
150        self.set_x(e)
151    }
152
153    // All Y based convenience methods
154
155    /// Get V (UV space)
156    fn v(&self) -> f64 {
157        self.y()
158    }
159    /// Set V (UV space)
160    fn set_v(&mut self, v: f64) {
161        self.set_y(v)
162    }
163    /// Get Phi (radial latitude)
164    fn phi(&self) -> f64 {
165        self.y()
166    }
167    /// Set Phi (radial latitude)
168    fn set_phi(&mut self, phi: f64) {
169        self.set_y(phi)
170    }
171    /// Get fwd azi (Geodesic measurement)
172    fn a1(&self) -> f64 {
173        self.y()
174    }
175    /// Set fwd azi (Geodesic measurement)
176    fn set_a1(&mut self, t: f64) {
177        self.set_y(t)
178    }
179    /// Get Phi (Rotations measurement)
180    fn p(&self) -> f64 {
181        self.y()
182    }
183    /// Set Phi (Rotations measurement)
184    fn set_p(&mut self, t: f64) {
185        self.set_y(t)
186    }
187    /// Get North (Directional coordinate)
188    fn n(&self) -> f64 {
189        self.y()
190    }
191    /// Set North (Directional coordinate)
192    fn set_n(&mut self, n: f64) {
193        self.set_y(n)
194    }
195
196    // All Z based convenience methods
197
198    /// Check if Z exists
199    fn has_z(&self) -> bool;
200
201    /// Get W
202    fn w(&self) -> f64 {
203        self.z()
204    }
205    /// Set W
206    fn set_w(&mut self, w: f64) {
207        self.set_z(w)
208    }
209    /// Get rev azi (Geodesic measurement)
210    fn a2(&self) -> f64 {
211        self.z()
212    }
213    /// Set rev azi (Geodesic measurement)
214    fn set_a2(&mut self, a2: f64) {
215        self.set_z(a2)
216    }
217    /// Get Kappa (Rotation)
218    fn k(&self) -> f64 {
219        self.z()
220    }
221    /// Set Kappa (Rotation)
222    fn set_k(&mut self, k: f64) {
223        self.set_z(k)
224    }
225    /// Get Up (Directional coordinate)
226    fn up(&self) -> f64 {
227        self.z()
228    }
229    /// Set Up (Directional coordinate)
230    fn set_up(&mut self, up: f64) {
231        self.set_z(up)
232    }
233}
234
235impl<M: Default + Clone> TransformCoordinates for VectorPoint<M> {
236    fn x(&self) -> f64 {
237        self.x
238    }
239    fn y(&self) -> f64 {
240        self.y
241    }
242    fn z(&self) -> f64 {
243        self.z.unwrap_or(0.)
244    }
245    fn t(&self) -> f64 {
246        0.
247    }
248    fn set_x(&mut self, x: f64) {
249        self.x = x
250    }
251    fn set_y(&mut self, y: f64) {
252        self.y = y
253    }
254    fn set_z(&mut self, z: f64) {
255        self.z = Some(z);
256    }
257    fn set_t(&mut self, t: f64) {
258        self.t = Some(t);
259    }
260
261    fn has_z(&self) -> bool {
262        self.z.is_some()
263    }
264}
265impl TransformCoordinates for Coords {
266    fn x(&self) -> f64 {
267        self.0
268    }
269    fn y(&self) -> f64 {
270        self.1
271    }
272    fn z(&self) -> f64 {
273        self.2
274    }
275    fn t(&self) -> f64 {
276        self.3
277    }
278    fn set_x(&mut self, x: f64) {
279        self.0 = x
280    }
281    fn set_y(&mut self, y: f64) {
282        self.1 = y
283    }
284    fn set_z(&mut self, z: f64) {
285        self.2 = z
286    }
287    fn set_t(&mut self, t: f64) {
288        self.3 = t
289    }
290
291    fn has_z(&self) -> bool {
292        self.z() != 0.
293    }
294}