gistools/proj/transform/
step.rs

1use super::TransformCoordinates;
2use crate::proj::{
3    ALBERS_EQUAL_AREA, AZIMUTHAL_EQUIDISTANT, AiryProjection, AlbersConicEqualAreaProjection,
4    AxisSwapConverter, AzimuthalEquidistantProjection, BONNE, BaseProjection, BonneProjection,
5    CASSINI, CartesianConverter, CassiniProjection, EQUAL_EARTH, EQUIDISTANT_CONIC,
6    EQUIDISTANT_CYLINDRICAL, EckertVIProjection, EqualAreaCylindricalProjection,
7    EqualEarthProjection, EquidistantConicProjection, EquidistantCylindricalProjection,
8    ExtendedTransverseMercatorProjection, GaussSchreiberTransverseMercatorProjection,
9    GeneralSinusoidalSeriesProjection, GeocentricConverter, GeocentricLatitudeConverter,
10    GnomonicProjection, GoodeHomolosineProjection, HOTINE_OBLIQUE_MERCATOR_VARIANT_A,
11    HOTINE_OBLIQUE_MERCATOR_VARIANT_B, HotineObliqueMercatorVariantAProjection,
12    HotineObliqueMercatorVariantBProjection, KROVAK, KROVAK_MODIFIED,
13    KROVAK_MODIFIED_NORTH_ORIENTED, KROVAK_NORTH_ORIENTED, KrovakModifiedNorthOrientedProjection,
14    KrovakModifiedProjection, KrovakNorthOrientedProjection, KrovakProjection, LABORDE,
15    LAMBERT_AZIMUTHAL_EQUAL_AREA, LAMBERT_AZIMUTHAL_EQUAL_AREA_SPHERICAL,
16    LAMBERT_CONFORMAL_CONIC_1SP, LAMBERT_CONFORMAL_CONIC_2SP, LabordeProjection,
17    LambertAzimuthalEqualAreaProjection, LambertAzimuthalEqualAreaSphericalProjection,
18    LambertConformalConic1SPProjection, LambertConformalConic2SPProjection,
19    LambertConformalConicAlternativeProjection, LambertEqualAreaConicProjection, MERCATOR,
20    McBrydeThomasFlatPolarSinusoidalProjection, MercatorProjection, Method,
21    MillerCylindricalProjection, MollweideProjection, NewZealandMapGridProjection,
22    OBLIQUE_STEREOGRAPHIC, ORTHOGRAPHIC, OblatedEqualAreaProjection,
23    ObliqueCylindricalEqualAreaProjection, ObliqueStereographicAlternativeProjection,
24    OrthographicProjection, POLAR_STEREOGRAPHIC_VARIANT_A, POLAR_STEREOGRAPHIC_VARIANT_B,
25    POLAR_STEREOGRAPHIC_VARIANT_C, POLYCONIC, PolarStereographicVariantAProjection,
26    PolarStereographicVariantBProjection, PolarStereographicVariantCProjection,
27    PolyconicProjection, Proj, ProjectCoordinates, RobinsonProjection, SOMERC,
28    SinusoidalProjection, StereographicProjection, SwissOblMercatorProjection, TRANSVERSE_MERCATOR,
29    TRANSVERSE_MERCATOR_SOUTH_ORIENTATED, TransverseCentralCylindricalProjection,
30    TransverseCylindricalEqualArealProjection, TransverseMercatorProjection,
31    TransverseMercatorSouthOrientedProjection, UniversalTransverseMercatorProjection,
32    VanDerGrintenIProjection, WEB_MERCATOR, WagnerIVProjection, WagnerVProjection,
33    WebMercatorProjection,
34};
35use alloc::{boxed::Box, rc::Rc};
36use core::cell::RefCell;
37
38macro_rules! dispatch_step {
39    ($self:ident, $point:ident, $method:ident, [ $($variant:ident),* ]) => {
40        match $self {
41            $(
42                Step::$variant(inner) => inner.$method($point),
43            )*
44        }
45    };
46}
47macro_rules! match_projections {
48    ($name:expr, $proj:expr, [
49        $( ($variant:ident, $projection:ty) ),* $(,)?
50    ]) => {{
51        $(
52            if <$projection>::names().contains(&$name) {
53                return Some(Step::$variant(Box::new(<$projection>::new($proj))));
54            }
55        )*
56        None
57    }};
58}
59
60macro_rules! match_ids {
61    ($id:expr, $proj:expr, [
62        $( ($const_id:ident, $variant:ident, $projection:ty) ),* $(,)?
63    ]) => {{
64        match $id {
65            $(
66                $const_id => Some(Step::$variant(Box::new(<$projection>::new($proj)))),
67            )*
68            _ => None,
69        }
70    }};
71}
72
73macro_rules! dispatch_name {
74    ($self:ident, [ $($variant:ident),* ]) => {
75        match $self {
76            $(
77                Step::$variant(inner) => inner.name(),
78            )*
79        }
80    };
81}
82
83/// Conversion/Transform/Projection step
84#[derive(Debug, Clone, PartialEq)]
85pub enum Step {
86    // CONVERTERS
87    /// Axis Swapping
88    AxisSwap(Box<AxisSwapConverter>),
89    /// Cartesian
90    Cartesian(Box<CartesianConverter>),
91    /// Geocentric Latitude
92    GeoLat(Box<GeocentricLatitudeConverter>),
93    /// Geocentric
94    Geocentric(Box<GeocentricConverter>),
95
96    // PROJECTIONS
97    /// Albers Conic Equal Area Projection
98    Aea(Box<AlbersConicEqualAreaProjection>),
99    /// Azimuthal Equidistant Projection
100    Aeqd(Box<AzimuthalEquidistantProjection>),
101    /// Airy Projection
102    Airy(Box<AiryProjection>),
103    /// Base Projection
104    Base(Box<BaseProjection>),
105    /// BonneProjection
106    Bonne(Box<BonneProjection>),
107    /// Cassini Projection
108    Cass(Box<CassiniProjection>),
109    /// Equal Area Cylindrical Projection
110    Cea(Box<EqualAreaCylindricalProjection>),
111    /// Eckert VI Projection
112    Eck6(Box<EckertVIProjection>),
113    /// Equidistant Cylindrica Projection
114    Eqc(Box<EquidistantCylindricalProjection>),
115    /// Equidistant Conic rojection
116    Eqdc(Box<EquidistantConicProjection>),
117    /// Equal Earth Projection
118    Eqearth(Box<EqualEarthProjection>),
119    /// Extended Transverse Mercator Projection
120    Etmerc(Box<ExtendedTransverseMercatorProjection>),
121    /// General Sinusoidal Series Projection
122    GnSinu(Box<GeneralSinusoidalSeriesProjection>),
123    /// Gnomonic Projection
124    Gnom(Box<GnomonicProjection>),
125    /// Goode Homolosine Projection
126    Goode(Box<GoodeHomolosineProjection>),
127    /// Gauss Schreiber Transverse Mercator Projection
128    Gstmerc(Box<GaussSchreiberTransverseMercatorProjection>),
129    /// Hotine Oblique Mercator Variant A Projection
130    HotineA(Box<HotineObliqueMercatorVariantAProjection>),
131    /// Hotine Oblique Mercator Variant B Projection
132    HotineB(Box<HotineObliqueMercatorVariantBProjection>),
133    /// Krovak Projection
134    Krovak(Box<KrovakProjection>),
135    /// Krovak North Oriented Projection
136    KrovakNO(Box<KrovakNorthOrientedProjection>),
137    /// Krovak Modified Projection
138    KrovakM(Box<KrovakModifiedProjection>),
139    /// Krovak Modified North Oriented Projection
140    KrovakMNO(Box<KrovakModifiedNorthOrientedProjection>),
141    /// Laborde Projection
142    Labrd(Box<LabordeProjection>),
143    /// Lambert Azimuthal Equal Area Projection
144    Laea(Box<LambertAzimuthalEqualAreaProjection>),
145    /// Lambert Azimuthal Equal Area Spherical Projection
146    LaeaS(Box<LambertAzimuthalEqualAreaSphericalProjection>),
147    /// Lambert Equal Area Conic Projection
148    Leac(Box<LambertEqualAreaConicProjection>),
149    /// Lambert Conformal Conic 1SP Projection
150    Lcc1SP(Box<LambertConformalConic1SPProjection>),
151    /// Lambert Conformal Conic 2SP Projection
152    Lcc2SP(Box<LambertConformalConic2SPProjection>),
153    /// Lambert Conformal Conic Alternative Projection
154    LccA(Box<LambertConformalConicAlternativeProjection>),
155    /// McBryde Thomas Flat Polar Sinusoidal Projection
156    MBTfps(Box<McBrydeThomasFlatPolarSinusoidalProjection>),
157    /// Mercator Projection
158    Merc(Box<MercatorProjection>),
159    /// Miller Cylindrical Projection
160    Mill(Box<MillerCylindricalProjection>),
161    /// Mollweide Projection
162    Moll(Box<MollweideProjection>),
163    /// New Zealand Map Grid Projection
164    Nzmg(Box<NewZealandMapGridProjection>),
165    /// Oblique Cylindrical Equal Area Projection
166    Ocea(Box<ObliqueCylindricalEqualAreaProjection>),
167    /// Oblated Equal Area Projection
168    Oea(Box<OblatedEqualAreaProjection>),
169    /// Orthographic Projection
170    Ortho(Box<OrthographicProjection>),
171    /// Polar Stereographic Variant A Projection
172    PSterA(Box<PolarStereographicVariantAProjection>),
173    /// Polar Stereographic Variant B Projection
174    PSterB(Box<PolarStereographicVariantBProjection>),
175    /// Polar Stereographic Variant C Projection
176    PSterC(Box<PolarStereographicVariantCProjection>),
177    /// Polyconic Projection
178    Poly(Box<PolyconicProjection>),
179    /// Robinson Projection
180    Robin(Box<RobinsonProjection>),
181    /// Sinusoidal Projection
182    Sinu(Box<SinusoidalProjection>),
183    /// Swiss OblMercator Projection
184    Somerc(Box<SwissOblMercatorProjection>),
185    /// Stereographic Projection
186    Stere(Box<StereographicProjection>),
187    /// Oblique Stereographic Alternative Projection
188    Sterea(Box<ObliqueStereographicAlternativeProjection>),
189    /// Transverse CentralCylindrical Projection
190    Tcc(Box<TransverseCentralCylindricalProjection>),
191    /// Transverse Cylindrical Equal Areal Projection
192    Tcea(Box<TransverseCylindricalEqualArealProjection>),
193    /// Transverse Mercator Projection
194    Tmerc(Box<TransverseMercatorProjection>),
195    /// Transverse Mercator South Oriented Projection
196    TmercSO(Box<TransverseMercatorSouthOrientedProjection>),
197    /// Universal Transverse Mercator Projection
198    Utm(Box<UniversalTransverseMercatorProjection>),
199    /// Van Der Grinten (I) Projection
200    Vandg(Box<VanDerGrintenIProjection>),
201    /// Wagner IV Projection
202    WagIV(Box<WagnerIVProjection>),
203    /// Wagner V Projection
204    WagV(Box<WagnerVProjection>),
205    /// WebMercatorProjection
206    WebMerc(Box<WebMercatorProjection>),
207}
208impl Step {
209    /// Check if there is another step that has the same name
210    pub fn same_step(&self, other: &Step) -> bool {
211        self.name() == other.name()
212    }
213    /// Get the name of the step
214    pub fn name(&self) -> &str {
215        dispatch_name!(
216            self,
217            [
218                AxisSwap, Cartesian, GeoLat, Geocentric, Aea, Aeqd, Airy, Base, Bonne, Cass, Cea,
219                Eck6, Eqc, Eqdc, Eqearth, Etmerc, Gnom, GnSinu, Goode, Gstmerc, HotineA, HotineB,
220                Krovak, KrovakNO, KrovakM, KrovakMNO, Labrd, Laea, LaeaS, Leac, Lcc1SP, Lcc2SP,
221                LccA, MBTfps, Merc, Mill, Moll, Nzmg, Ocea, Oea, Ortho, PSterA, PSterB, PSterC,
222                Poly, Robin, Sinu, Somerc, Stere, Sterea, Tcc, Tcea, Tmerc, TmercSO, Utm, Vandg,
223                WagIV, WagV, WebMerc
224            ]
225        )
226    }
227    /// forward conversion
228    pub fn forward<P: TransformCoordinates>(&self, point: &mut P) {
229        dispatch_step!(
230            self,
231            point,
232            forward,
233            [
234                AxisSwap, Cartesian, GeoLat, Geocentric, Aea, Aeqd, Airy, Base, Bonne, Cass, Cea,
235                Eck6, Eqc, Eqdc, Eqearth, Etmerc, Gnom, GnSinu, Goode, Gstmerc, HotineA, HotineB,
236                Krovak, KrovakNO, KrovakM, KrovakMNO, Labrd, Laea, LaeaS, Leac, Lcc1SP, Lcc2SP,
237                LccA, MBTfps, Merc, Mill, Moll, Nzmg, Ocea, Oea, Ortho, PSterA, PSterB, PSterC,
238                Poly, Robin, Sinu, Somerc, Stere, Sterea, Tcc, Tcea, Tmerc, TmercSO, Utm, Vandg,
239                WagIV, WagV, WebMerc
240            ]
241        );
242    }
243    /// inverse conversion
244    pub fn inverse<P: TransformCoordinates>(&self, point: &mut P) {
245        dispatch_step!(
246            self,
247            point,
248            inverse,
249            [
250                AxisSwap, Cartesian, GeoLat, Geocentric, Aea, Aeqd, Airy, Base, Bonne, Cass, Cea,
251                Eck6, Eqc, Eqdc, Eqearth, Etmerc, Gnom, GnSinu, Goode, Gstmerc, HotineA, HotineB,
252                Krovak, KrovakNO, KrovakM, KrovakMNO, Labrd, Laea, LaeaS, Leac, Lcc1SP, Lcc2SP,
253                LccA, MBTfps, Merc, Mill, Moll, Nzmg, Ocea, Oea, Ortho, PSterA, PSterB, PSterC,
254                Poly, Robin, Sinu, Somerc, Stere, Sterea, Tcc, Tcea, Tmerc, TmercSO, Utm, Vandg,
255                WagIV, WagV, WebMerc
256            ]
257        );
258    }
259    /// Create a Step from JSON Method
260    pub fn from_method(method: &Method, proj: Rc<RefCell<Proj>>) -> Option<Step> {
261        // first try ID
262        if let Some(id) = method.id.as_ref()
263            && let Some(step) = Step::from_id(id.code.i64(), proj.clone())
264        {
265            return Some(step);
266        }
267        // second try IDs
268        for id in method.ids.iter() {
269            if let Some(step) = Step::from_id(id.code.i64(), proj.clone()) {
270                return Some(step);
271            }
272        }
273        // last try name
274        Step::from_name(&method.name, proj)
275    }
276    /// Create a Step from ID
277    pub fn from_id(id: i64, proj: Rc<RefCell<Proj>>) -> Option<Step> {
278        if id == 0 {
279            return Some(Step::Base(BaseProjection::new(proj).into()));
280        }
281        match_ids!(
282            id,
283            proj,
284            [
285                (ALBERS_EQUAL_AREA, Aea, AlbersConicEqualAreaProjection),
286                (AZIMUTHAL_EQUIDISTANT, Aeqd, AzimuthalEquidistantProjection),
287                (BONNE, Bonne, BonneProjection),
288                (CASSINI, Cass, CassiniProjection),
289                (EQUIDISTANT_CYLINDRICAL, Eqc, EquidistantCylindricalProjection),
290                (EQUIDISTANT_CONIC, Eqdc, EquidistantConicProjection),
291                (EQUAL_EARTH, Eqearth, EqualEarthProjection),
292                (
293                    HOTINE_OBLIQUE_MERCATOR_VARIANT_A,
294                    HotineA,
295                    HotineObliqueMercatorVariantAProjection
296                ),
297                (
298                    HOTINE_OBLIQUE_MERCATOR_VARIANT_B,
299                    HotineB,
300                    HotineObliqueMercatorVariantBProjection
301                ),
302                (KROVAK, Krovak, KrovakProjection),
303                (KROVAK_NORTH_ORIENTED, KrovakNO, KrovakNorthOrientedProjection),
304                (KROVAK_MODIFIED, KrovakM, KrovakModifiedProjection),
305                (KROVAK_MODIFIED_NORTH_ORIENTED, KrovakMNO, KrovakModifiedNorthOrientedProjection),
306                (LABORDE, Labrd, LabordeProjection),
307                (LAMBERT_AZIMUTHAL_EQUAL_AREA, Laea, LambertAzimuthalEqualAreaProjection),
308                (
309                    LAMBERT_AZIMUTHAL_EQUAL_AREA_SPHERICAL,
310                    LaeaS,
311                    LambertAzimuthalEqualAreaSphericalProjection
312                ),
313                (LAMBERT_CONFORMAL_CONIC_1SP, Lcc1SP, LambertConformalConic1SPProjection),
314                (LAMBERT_CONFORMAL_CONIC_2SP, Lcc2SP, LambertConformalConic2SPProjection),
315                (MERCATOR, Merc, MercatorProjection),
316                (OBLIQUE_STEREOGRAPHIC, Sterea, ObliqueStereographicAlternativeProjection),
317                (ORTHOGRAPHIC, Ortho, OrthographicProjection),
318                (POLAR_STEREOGRAPHIC_VARIANT_A, PSterA, PolarStereographicVariantAProjection),
319                (POLAR_STEREOGRAPHIC_VARIANT_B, PSterB, PolarStereographicVariantBProjection),
320                (POLAR_STEREOGRAPHIC_VARIANT_C, PSterC, PolarStereographicVariantCProjection),
321                (POLYCONIC, Poly, PolyconicProjection),
322                (SOMERC, Somerc, SwissOblMercatorProjection),
323                (TRANSVERSE_MERCATOR, Tmerc, TransverseMercatorProjection),
324                (
325                    TRANSVERSE_MERCATOR_SOUTH_ORIENTATED,
326                    TmercSO,
327                    TransverseMercatorSouthOrientedProjection
328                ),
329                (WEB_MERCATOR, WebMerc, WebMercatorProjection)
330            ]
331        )
332    }
333    /// Create a Step from Projection name
334    pub fn from_name(name: &str, proj: Rc<RefCell<Proj>>) -> Option<Step> {
335        match_projections!(
336            name,
337            proj,
338            [
339                (Aea, AlbersConicEqualAreaProjection),
340                (Aeqd, AzimuthalEquidistantProjection),
341                (Airy, AiryProjection),
342                (Base, BaseProjection),
343                (Bonne, BonneProjection),
344                (Cass, CassiniProjection),
345                (Cea, EqualAreaCylindricalProjection),
346                (Eck6, EckertVIProjection),
347                (Eqc, EquidistantCylindricalProjection),
348                (Eqdc, EquidistantConicProjection),
349                (Eqearth, EqualEarthProjection),
350                (Etmerc, ExtendedTransverseMercatorProjection),
351                (Gnom, GnomonicProjection),
352                (GnSinu, GeneralSinusoidalSeriesProjection),
353                (Goode, GoodeHomolosineProjection),
354                (Gstmerc, GaussSchreiberTransverseMercatorProjection),
355                (HotineA, HotineObliqueMercatorVariantAProjection),
356                (HotineB, HotineObliqueMercatorVariantBProjection),
357                (Krovak, KrovakProjection),
358                (KrovakNO, KrovakNorthOrientedProjection),
359                (KrovakM, KrovakModifiedProjection),
360                (KrovakMNO, KrovakModifiedNorthOrientedProjection),
361                (Labrd, LabordeProjection),
362                (Laea, LambertAzimuthalEqualAreaProjection),
363                (LaeaS, LambertAzimuthalEqualAreaSphericalProjection),
364                (Leac, LambertEqualAreaConicProjection),
365                (Lcc1SP, LambertConformalConic1SPProjection),
366                (Lcc2SP, LambertConformalConic2SPProjection),
367                (LccA, LambertConformalConicAlternativeProjection),
368                (MBTfps, McBrydeThomasFlatPolarSinusoidalProjection),
369                (Merc, MercatorProjection),
370                (Mill, MillerCylindricalProjection),
371                (Moll, MollweideProjection),
372                (Nzmg, NewZealandMapGridProjection),
373                (Ocea, ObliqueCylindricalEqualAreaProjection),
374                (Oea, OblatedEqualAreaProjection),
375                (Ortho, OrthographicProjection),
376                (PSterA, PolarStereographicVariantAProjection),
377                (PSterB, PolarStereographicVariantBProjection),
378                (PSterC, PolarStereographicVariantCProjection),
379                (Poly, PolyconicProjection),
380                (Robin, RobinsonProjection),
381                (Sinu, SinusoidalProjection),
382                (Somerc, SwissOblMercatorProjection),
383                (Stere, StereographicProjection),
384                (Sterea, ObliqueStereographicAlternativeProjection),
385                (Tcc, TransverseCentralCylindricalProjection),
386                (Tcea, TransverseCylindricalEqualArealProjection),
387                (Tmerc, TransverseMercatorProjection),
388                (TmercSO, TransverseMercatorSouthOrientedProjection),
389                (Utm, UniversalTransverseMercatorProjection),
390                (Vandg, VanDerGrintenIProjection),
391                (WagIV, WagnerIVProjection),
392                (WagV, WagnerVProjection),
393                (WebMerc, WebMercatorProjection),
394            ]
395        )
396    }
397}
398
399/// Conversion trait for modifying a Point
400pub trait CoordinateStep {
401    /// Create a new Converter
402    fn new(proj: Rc<RefCell<Proj>>) -> Self;
403    /// forward conversion
404    fn forward<P: TransformCoordinates>(&self, point: &mut P);
405    /// inverse conversion
406    fn inverse<P: TransformCoordinates>(&self, point: &mut P);
407}