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#[derive(Debug, Clone, PartialEq)]
85pub enum Step {
86 AxisSwap(Box<AxisSwapConverter>),
89 Cartesian(Box<CartesianConverter>),
91 GeoLat(Box<GeocentricLatitudeConverter>),
93 Geocentric(Box<GeocentricConverter>),
95
96 Aea(Box<AlbersConicEqualAreaProjection>),
99 Aeqd(Box<AzimuthalEquidistantProjection>),
101 Airy(Box<AiryProjection>),
103 Base(Box<BaseProjection>),
105 Bonne(Box<BonneProjection>),
107 Cass(Box<CassiniProjection>),
109 Cea(Box<EqualAreaCylindricalProjection>),
111 Eck6(Box<EckertVIProjection>),
113 Eqc(Box<EquidistantCylindricalProjection>),
115 Eqdc(Box<EquidistantConicProjection>),
117 Eqearth(Box<EqualEarthProjection>),
119 Etmerc(Box<ExtendedTransverseMercatorProjection>),
121 GnSinu(Box<GeneralSinusoidalSeriesProjection>),
123 Gnom(Box<GnomonicProjection>),
125 Goode(Box<GoodeHomolosineProjection>),
127 Gstmerc(Box<GaussSchreiberTransverseMercatorProjection>),
129 HotineA(Box<HotineObliqueMercatorVariantAProjection>),
131 HotineB(Box<HotineObliqueMercatorVariantBProjection>),
133 Krovak(Box<KrovakProjection>),
135 KrovakNO(Box<KrovakNorthOrientedProjection>),
137 KrovakM(Box<KrovakModifiedProjection>),
139 KrovakMNO(Box<KrovakModifiedNorthOrientedProjection>),
141 Labrd(Box<LabordeProjection>),
143 Laea(Box<LambertAzimuthalEqualAreaProjection>),
145 LaeaS(Box<LambertAzimuthalEqualAreaSphericalProjection>),
147 Leac(Box<LambertEqualAreaConicProjection>),
149 Lcc1SP(Box<LambertConformalConic1SPProjection>),
151 Lcc2SP(Box<LambertConformalConic2SPProjection>),
153 LccA(Box<LambertConformalConicAlternativeProjection>),
155 MBTfps(Box<McBrydeThomasFlatPolarSinusoidalProjection>),
157 Merc(Box<MercatorProjection>),
159 Mill(Box<MillerCylindricalProjection>),
161 Moll(Box<MollweideProjection>),
163 Nzmg(Box<NewZealandMapGridProjection>),
165 Ocea(Box<ObliqueCylindricalEqualAreaProjection>),
167 Oea(Box<OblatedEqualAreaProjection>),
169 Ortho(Box<OrthographicProjection>),
171 PSterA(Box<PolarStereographicVariantAProjection>),
173 PSterB(Box<PolarStereographicVariantBProjection>),
175 PSterC(Box<PolarStereographicVariantCProjection>),
177 Poly(Box<PolyconicProjection>),
179 Robin(Box<RobinsonProjection>),
181 Sinu(Box<SinusoidalProjection>),
183 Somerc(Box<SwissOblMercatorProjection>),
185 Stere(Box<StereographicProjection>),
187 Sterea(Box<ObliqueStereographicAlternativeProjection>),
189 Tcc(Box<TransverseCentralCylindricalProjection>),
191 Tcea(Box<TransverseCylindricalEqualArealProjection>),
193 Tmerc(Box<TransverseMercatorProjection>),
195 TmercSO(Box<TransverseMercatorSouthOrientedProjection>),
197 Utm(Box<UniversalTransverseMercatorProjection>),
199 Vandg(Box<VanDerGrintenIProjection>),
201 WagIV(Box<WagnerIVProjection>),
203 WagV(Box<WagnerVProjection>),
205 WebMerc(Box<WebMercatorProjection>),
207}
208impl Step {
209 pub fn same_step(&self, other: &Step) -> bool {
211 self.name() == other.name()
212 }
213 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 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 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 pub fn from_method(method: &Method, proj: Rc<RefCell<Proj>>) -> Option<Step> {
261 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 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 Step::from_name(&method.name, proj)
275 }
276 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 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
399pub trait CoordinateStep {
401 fn new(proj: Rc<RefCell<Proj>>) -> Self;
403 fn forward<P: TransformCoordinates>(&self, point: &mut P);
405 fn inverse<P: TransformCoordinates>(&self, point: &mut P);
407}