gistools/proj/parse/
ellipsoid.rs

1use crate::proj::{Proj, RA4, RA6, SIXTH};
2use libm::{asin, cos, sin, sqrt, tan};
3
4/// Builds a sphere with ellipsoid parameters
5///
6/// ## Parameters
7/// - `proj`: an object with/wihtout sphere properties and builds the sphere
8pub fn derive_sphere(proj: &mut Proj) {
9    if proj.a == 0.0 {
10        // do we have an ellipsoid? Then update the ellipsoid
11        let ellipse = get_ellipsoid(&proj.ellps).unwrap_or(WGS84);
12        proj.a = ellipse.a;
13        if let Some(b) = ellipse.b {
14            proj.b = b;
15        }
16        if let Some(rf) = ellipse.rf {
17            proj.rf = rf;
18        }
19    }
20    if proj.b == 0.0 && proj.rf != 0.0 {
21        proj.b = (1. - 1. / proj.rf) * proj.a;
22    }
23    if proj.b != 0.0 && proj.rf == 0.0 {
24        let a = proj.a;
25        let b = proj.b;
26        proj.rf = (a - b) / a;
27    }
28    let rf = proj.rf;
29    let a = proj.a;
30    if rf == 0.0 || (proj.b != 0.0 && (a - proj.b).abs() < f64::EPSILON) {
31        proj.sphere = true;
32        proj.b = proj.a;
33    }
34
35    derive_eccentricity(proj);
36}
37
38/// Derives an ellipsoid's eccentricity for an object
39///
40/// ## Parameters
41/// - `el`: ellipsoid object to modify
42pub fn derive_eccentricity(proj: &mut Proj) {
43    let mut a = proj.a;
44    let b = proj.b;
45    let mut a2 = a * a; // used in geocentric
46    let b2 = b * b; // used in geocentric
47    let mut es = (a2 - b2) / a2; // e ^ 2
48    let mut e = 0.0;
49    if proj.sphere {
50        a *= 1. - es * (SIXTH + es * (RA4 + es * RA6));
51        a2 = a * a;
52        es = 0.;
53    } else {
54        e = sqrt(es); // eccentricity
55    }
56    proj.a = a;
57    proj.b = b;
58    proj.es = es;
59    proj.e = e;
60
61    // Angular eccentricity
62    let alpha = asin(e);
63    proj.alpha = alpha;
64
65    // Derived eccentricities
66    proj.e2 = tan(alpha);
67    proj.e2s = proj.e2 * proj.e2;
68
69    let sin_alpha = sin(alpha);
70    proj.e3 = if alpha != 0.0 { sin_alpha / sqrt(2.0 - sin_alpha * sin_alpha) } else { 0.0 };
71    proj.e3s = proj.e3 * proj.e3;
72
73    // Flattening and reciprocals
74    let cos_alpha = cos(alpha);
75    proj.f = 1. - cos_alpha;
76    proj.rf = if proj.f != 0.0 { 1. / proj.f } else { f64::INFINITY };
77    proj.f2 = if cos_alpha != 0.0 { 1. / cos_alpha - 1. } else { 0.0 };
78    proj.rf2 = if proj.f2 != 0.0 { 1. / proj.f2 } else { f64::INFINITY };
79
80    // Third flattening
81    proj.n = (a - b) / (a + b);
82    proj.rn = if proj.n != 0.0 { 1. / proj.n } else { f64::INFINITY };
83
84    // Inverse semiaxes
85    proj.ra = 1. / a;
86    proj.rb = 1. / b;
87
88    // One minus es and its reciprocal
89    proj.one_es = 1. - es;
90    if proj.one_es == 0.0 {
91        // caller must handle invalid case
92        return;
93    }
94    proj.rone_es = 1. / proj.one_es;
95
96    // Second eccentricity squared
97    proj.e2 = (a2 - b2) / b2;
98}
99
100/// ellipsoid constants
101#[derive(Debug)]
102pub struct Ellipsoidal {
103    /// semi-major axis
104    pub a: f64,
105    /// semi-minor axis
106    pub b: Option<f64>,
107    /// inverse flattening
108    pub rf: Option<f64>,
109}
110
111/// [CGCS2000 - 1024](https://epsg.org/ellipsoid_1024/CGCS2000.html)
112pub const CGCS2000: Ellipsoidal = Ellipsoidal { a: 6_378_137.0, b: None, rf: Some(298.257222101) };
113
114/// [GSK-2011 - 1025](https://epsg.org/ellipsoid_1025/GSK-2011.html)
115pub const GSK_2011: Ellipsoidal = Ellipsoidal { a: 6_378_136.5, b: None, rf: Some(298.2564151) };
116
117/// [Zach 1812 - 1026](https://epsg.org/ellipsoid_1026/Zach-1812.html)
118pub const ZACH: Ellipsoidal = Ellipsoidal { a: 6_376_045.0, b: None, rf: Some(310.0) };
119
120/// [Airy 1830 - 7001](https://epsg.org/ellipsoid_7001/Airy-1830.html)
121pub const AIRY: Ellipsoidal = Ellipsoidal { a: 6_377_563.396, b: None, rf: Some(299.3249646) };
122
123/// [Airy Modified 1849 - 7002](https://epsg.org/ellipsoid_7002/Airy-Modified-1849.html)
124pub const MOD_AIRY: Ellipsoidal = Ellipsoidal { a: 6_377_340.189, b: None, rf: Some(299.3249646) };
125
126/// [Australian National Spheroid (Australian Natl & S. Amer. 1969) - 7003](https://epsg.org/ellipsoid_7003/Australian-National-Spheroid.html)
127pub const AUST_SA: Ellipsoidal = Ellipsoidal { a: 6_378_160.0, b: None, rf: Some(298.25) };
128
129/// [Bessel 1841 - 7004](https://epsg.org/ellipsoid_7004/Bessel-1841.html)
130pub const BESSEL: Ellipsoidal = Ellipsoidal { a: 6_377_397.155, b: None, rf: Some(299.1528128) };
131
132/// [Bessel 1841 (Modified) - 7005](https://epsg.org/ellipsoid_7005/Bessel-Modified.html)
133pub const MOD_BESSEL: Ellipsoidal = Ellipsoidal { a: 6_377_390.0, b: None, rf: Some(299.1528128) };
134
135/// [Clarke 1858 - 7007](https://epsg.org/ellipsoid_7007/Clarke-1858.html)
136pub const CLRK58: Ellipsoidal =
137    Ellipsoidal { a: 6_378_293.645_208_759, b: Some(6_356_617.987_679_838), rf: None };
138
139/// [Clarke 1866 - 7008](https://epsg.org/ellipsoid_7008/Clarke-1866.html)
140pub const CLRK66: Ellipsoidal = Ellipsoidal { a: 6_378_206.4, b: Some(6_356_583.8), rf: None };
141
142/// [Clarke 1880 (Benoit) - 7010](https://epsg.org/ellipsoid_7010/Clarke-1880-Benoit.html)
143pub const CLRK80BEN: Ellipsoidal =
144    Ellipsoidal { a: 6_378_300.789, b: Some(6_356_566.435), rf: None };
145
146/// [Clarke 1880 (IGN) - 7011](https://epsg.org/ellipsoid_7011/Clarke-1880-IGN.html)
147pub const CLRK80IGN: Ellipsoidal = Ellipsoidal { a: 6378249.2, b: Some(6356515.0), rf: None };
148
149/// [Clarke 1880 (RGS) - 7012](https://epsg.org/ellipsoid_7012/Clarke-1880-RGS.html)
150pub const CLRK80RGS: Ellipsoidal = Ellipsoidal { a: 6_378_249.145, b: None, rf: Some(293.465) };
151
152/// [Clarke 1880 (Arc) - 7013](https://epsg.org/ellipsoid_7013/Clarke-1880-Arc.html)
153pub const CLRK80ARC: Ellipsoidal = Ellipsoidal { a: 6_378_249.145, b: None, rf: Some(293.4663077) };
154
155/// [Clarke 1880 (SGA) - 7014](https://epsg.org/ellipsoid_7014/Clarke-1880-SGA-1922.html)
156pub const CLRK80SGA: Ellipsoidal = Ellipsoidal { a: 6_378_249.2, b: None, rf: Some(293.46598) };
157
158/// [Everest 1830 (1937 Adjustment) - 7015](https://epsg.org/ellipsoid_7015/Everest-1830-1937-Adjustment.html)
159pub const EVRST30: Ellipsoidal = Ellipsoidal { a: 6_377_276.345, b: None, rf: Some(300.8017) };
160
161/// Everest (Sabah & Sarawak)
162pub const EVRSTSS: Ellipsoidal = Ellipsoidal { a: 6_377_298.556, b: None, rf: Some(300.8017) };
163
164/// [Everest 1830 (1967 Definition) - 7016](https://epsg.org/ellipsoid_7016/Everest-1830-1967-Definition.html)
165pub const EVRST67: Ellipsoidal = EVRSTSS;
166
167/// Everest 1948
168pub const EVRST48: Ellipsoidal = Ellipsoidal { a: 6_377_304.063, b: None, rf: Some(300.8017) };
169
170/// [Everest 1830 Modified - 7018](https://epsg.org/ellipsoid_7018/Everest-1830-Modified.html)
171pub const EVRST30_MOD: Ellipsoidal = EVRST48;
172
173/// [GRS 1980 (IUGG, 1980) - 7019](https://epsg.org/ellipsoid_7019/GRS-1980.html)
174pub const GRS80: Ellipsoidal = Ellipsoidal { a: 6_378_137.0, b: None, rf: Some(298.257222101) };
175
176/// [Helmert 1906 - 7020](https://epsg.org/ellipsoid_7020/Helmert-1906.html)
177pub const HELMERT: Ellipsoidal = Ellipsoidal { a: 6_378_200.0, b: None, rf: Some(298.3) };
178
179/// [Indonesian National Spheroid - 7021](https://epsg.org/ellipsoid_7021/Indonesian-National-Spheroid.html)
180pub const INDONESIAN: Ellipsoidal = Ellipsoidal { a: 6_378_160.0, b: None, rf: Some(298.247) };
181
182/// [International 1924 - 7022](https://epsg.org/ellipsoid_7022/International-1924.html)
183pub const INTL24: Ellipsoidal = Ellipsoidal { a: 6_378_388.0, b: None, rf: Some(297.0) };
184
185/// [Krassowsky 1940 - 7024](https://epsg.org/ellipsoid_7024/Krassowsky-1940.html)
186pub const KRASS: Ellipsoidal = Ellipsoidal { a: 6_378_245.0, b: None, rf: Some(298.3) };
187
188/// [Naval Weapons Lab., 1965 (NWL 9D) - 7025](https://epsg.org/ellipsoid_7025/NWL-9D.html)
189pub const NWL9D: Ellipsoidal = Ellipsoidal { a: 6_378_145.0, b: None, rf: Some(298.25) };
190
191/// Naval Weapons Lab., 1965
192pub const NWL10D: Ellipsoidal = NWL9D;
193
194/// [Plessis 1817 (France) - 7027](https://epsg.org/ellipsoid_7027/Plessis-1817.html)
195pub const PLESSIS: Ellipsoidal = Ellipsoidal { a: 6_376_523.0, b: None, rf: Some(308.64) };
196
197/// [Struve 1860 - 7028](https://epsg.org/ellipsoid_7028/Struve-1860.html)
198pub const STRUVE: Ellipsoidal = Ellipsoidal { a: 6_378_298.3, b: None, rf: Some(294.73) };
199
200/// [War Office - 7029](https://epsg.org/ellipsoid_7029/War-Office.html)
201pub const WARO: Ellipsoidal = Ellipsoidal { a: 6_378_300.0, b: None, rf: Some(296.0) };
202
203/// [WGS 84 - 7030](https://epsg.org/ellipsoid_7030/WGS-84.html)
204pub const WGS84: Ellipsoidal = Ellipsoidal { a: 6_378_137.0, b: None, rf: Some(298.257223563) };
205
206/// [GEM 10C - 7031](https://epsg.org/ellipsoid_7031/GEM-10C.html)
207pub const GEM10C: Ellipsoidal = WGS84;
208
209/// [OSU86F - 7032](https://epsg.org/ellipsoid_7032/OSU86F.html)
210pub const OSU86F: Ellipsoidal = Ellipsoidal { a: 6_378_136.2, b: None, rf: Some(298.257223563) };
211
212/// [OSU91A - 7033](https://epsg.org/ellipsoid_7033/OSU91A.html)
213pub const OSU91A: Ellipsoidal = Ellipsoidal { a: 6_378_136.3, b: None, rf: Some(298.257223563) };
214
215/// [Clarke 1880 - 7034](https://epsg.org/ellipsoid_7034/Clarke-1880.html)
216pub const CLRK80: Ellipsoidal =
217    Ellipsoidal { a: 6_378_249.144_808_011, b: Some(6_356_514.966204133), rf: None };
218
219/// [GRS 1967 (IUGG 1967) - 7036](https://epsg.org/ellipsoid_7036/GRS-1967.html)
220pub const GRS67: Ellipsoidal = Ellipsoidal { a: 6_378_160.0, b: None, rf: Some(298.247167427) };
221
222/// [Average Terrestrial System 1977 - 7041](https://epsg.org/ellipsoid_7041/Average-Terrestrial-System-1977.html)
223pub const ATS77: Ellipsoidal = Ellipsoidal { a: 6_378_135.0, b: None, rf: Some(298.257) };
224
225/// [Everest 1830 (1830 Definition) - 7042](https://epsg.org/ellipsoid_7042/Everest-1830-Definition.html)
226pub const EVRST1830: Ellipsoidal =
227    Ellipsoidal { a: 6_377_299.365_595_443, b: Some(6_356_098.359_005_22), rf: None };
228
229/// [WGS 72 - 7043](https://epsg.org/ellipsoid_7043/WGS-72.html)
230pub const WGS7: Ellipsoidal = Ellipsoidal { a: 6_378_135.0, b: None, rf: Some(298.26) };
231
232/// [Everest 1830 (1962 Definition) - 7044](https://epsg.org/ellipsoid_7044/Everest-1830-1962-Definition.html)
233pub const EVRST62: Ellipsoidal = Ellipsoidal { a: 6_377_301.243, b: None, rf: Some(300.8017255) };
234
235/// [Everest 1830 (1975 Definition) - 7045](https://epsg.org/ellipsoid_7045/Everest-1830-1975-Definition.html)
236pub const EVRST75: Ellipsoidal = Ellipsoidal { a: 6_377_299.151, b: None, rf: Some(300.8017255) };
237
238/// [Bessel 1841 (Namibia GLM) - 7046](https://epsg.org/ellipsoid_7046/Bessel-Namibia-GLM.html)
239pub const BESS_NAM: Ellipsoidal =
240    Ellipsoidal { a: 6_377_483.865280418, b: None, rf: Some(299.1528128) };
241
242/// [GRS 1980 Authalic Sphere - 7048](https://epsg.org/ellipsoid_7048/GRS-1980-Authalic-Sphere.html)
243///
244/// NOTE: Not an ellipse why does this exist?
245pub const GRS80_AUTH: Ellipsoidal = Ellipsoidal { a: 6_371_007.0, b: Some(6_371_007.0), rf: None };
246
247/// [IAG 1975 - 7049](https://epsg.org/ellipsoid_7049/IAG-1975.html)
248pub const IAG75: Ellipsoidal = Ellipsoidal { a: 6_378_140.0, b: None, rf: Some(298.257) };
249
250/// [GRS 1967 Modified - 7050](https://epsg.org/ellipsoid_7050/GRS-1967-Modified.html)
251pub const GRS_MOD: Ellipsoidal = Ellipsoidal { a: 6_378_160.0, b: None, rf: Some(298.25) };
252
253/// [Danish 1876 - 7051](https://epsg.org/ellipsoid_7051/Danish-1876.html)
254pub const DANISH: Ellipsoidal = Ellipsoidal { a: 6_377_019.27, b: None, rf: Some(300.0) };
255
256/// [Clarke 1866 Authalic Sphere - 7052](https://epsg.org/ellipsoid_7052/Clarke-1866-Authalic-Sphere.html)
257///
258/// NOTE: Not an ellipse why does this exist?
259pub const CLRK_AUTH: Ellipsoidal = Ellipsoidal { a: 6_370_997.0, b: Some(6_370_997.0), rf: None };
260
261/// [Hough 1960 - 7053](https://epsg.org/ellipsoid_7053/Hough-1960.html)
262pub const HOUGH: Ellipsoidal = Ellipsoidal { a: 6_378_270.0, b: None, rf: Some(297.0) };
263
264/// [PZ-90 - 7054](https://epsg.org/ellipsoid_7054/PZ-90.html)
265pub const PZ90: Ellipsoidal = Ellipsoidal { a: 6_378_136.0, b: None, rf: Some(298.257839303) };
266
267/// [Clarke 1880 (international foot) - 7055](https://epsg.org/ellipsoid_7055/Clarke-1880-international-foot.html)
268pub const CLRK80FOOT: Ellipsoidal =
269    Ellipsoidal { a: 6_378_306.369_6, b: Some(6_356_571.996), rf: None };
270
271/// [Everest 1830 (RSO 1969) - 7056](https://epsg.org/ellipsoid_7056/Everest-1830-RSO-1969.html)
272pub const EVRST_RSO: Ellipsoidal = Ellipsoidal { a: 6_377_295.664, b: None, rf: Some(300.8017) };
273
274/// [International 1924 Authalic Sphere - 7057](https://epsg.org/ellipsoid_7057/International-1924-Authalic-Sphere.html)
275///
276/// NOTE: Not an ellipse why does this exist?
277pub const INTL1924_AUTH: Ellipsoidal =
278    Ellipsoidal { a: 6_371_228.0, b: Some(6_371_228.0), rf: None };
279
280/// [Hughes 1980 - 7058](https://epsg.org/ellipsoid_7058/Hughes-1980.html)
281pub const HUGHES: Ellipsoidal = Ellipsoidal { a: 6_378_273.0, b: Some(6_356_889.449), rf: None };
282
283// Everything after this I have no clue if they are accurate
284
285/// MERIT 1983
286pub const MERIT: Ellipsoidal = Ellipsoidal { a: 6_378_137.0, b: None, rf: Some(298.257) };
287
288/// Soviet Geodetic System 85
289pub const SGS85: Ellipsoidal = Ellipsoidal { a: 6_378_136.0, b: None, rf: Some(298.257) };
290
291/// IAU 1976
292pub const IAU76: Ellipsoidal =
293    Ellipsoidal { a: 6_378_140.0, b: Some(6_356_755.29), rf: Some(298.257) };
294
295/// Appl. Physics. 1965
296pub const APL4: Ellipsoidal = Ellipsoidal { a: 6_378_137.0, b: None, rf: Some(298.25) };
297
298/// Andrae 1876 (Den., Iclnd.)
299pub const ANDRAE: Ellipsoidal = Ellipsoidal { a: 6_377_104.43, b: None, rf: Some(300.0) };
300
301/// Clarke 1866 (Michigan)
302pub const CLRK80MICH: Ellipsoidal =
303    Ellipsoidal { a: 6_378_450.0475489, b: Some(6_356_826.62148844), rf: None };
304
305/// Comm. des Poids et Mesures 1799
306pub const CPM: Ellipsoidal = Ellipsoidal { a: 6_375_738.7, b: None, rf: Some(334.29) };
307
308/// Delambre 1810 (Belgium)
309pub const DELMBR: Ellipsoidal = Ellipsoidal { a: 6_376_428.0, b: None, rf: Some(311.5) };
310
311/// Engelis 1985
312pub const ENGELIS: Ellipsoidal = Ellipsoidal { a: 6_378_136.05, b: None, rf: Some(298.2566) };
313
314/// Everest 1956
315pub const EVRST56: Ellipsoidal = Ellipsoidal { a: 6_377_301.243, b: None, rf: Some(300.8017) };
316
317/// Everest 1969
318pub const EVRST69: Ellipsoidal = Ellipsoidal { a: 6_377_295.664, b: None, rf: Some(300.8017) };
319
320/// Fischer (Mercury Datum) 1960
321pub const FSCHR60: Ellipsoidal = Ellipsoidal { a: 6_378_166.0, b: None, rf: Some(298.3) };
322
323/// Fischer 1960
324pub const FSCHR60M: Ellipsoidal = Ellipsoidal { a: 6_378_155.0, b: None, rf: Some(298.3) };
325
326/// Fischer 1968
327pub const FSCHR68: Ellipsoidal = Ellipsoidal { a: 6_378_150.0, b: None, rf: Some(298.3) };
328
329/// International 1909 (Hayford)
330pub const INTL: Ellipsoidal = Ellipsoidal { a: 6_378_388.0, b: None, rf: Some(297.0) };
331
332/// International 1909 (Hayford)
333pub const INTL09: Ellipsoidal = INTL;
334
335/// International 1967
336pub const INTL67: Ellipsoidal = AUST_SA;
337
338/// Kaula 1961
339pub const KAULA: Ellipsoidal = Ellipsoidal { a: 6_378_163.0, b: None, rf: Some(298.24) };
340
341/// Lerch 1979
342pub const LERCH: Ellipsoidal = Ellipsoidal { a: 6_378_139.0, b: None, rf: Some(298.257) };
343
344/// Maupertius 1738
345pub const MPRTS: Ellipsoidal = Ellipsoidal { a: 6_397_300.0, b: None, rf: Some(191.0) };
346
347/// New International 1967
348pub const NEW_INTL: Ellipsoidal = Ellipsoidal { a: 6_378_157.5, b: Some(6_356_772.2), rf: None };
349
350/// Southeast Asia
351pub const SEASIA: Ellipsoidal = Ellipsoidal { a: 6_378_155.0, b: Some(6_356_773.320_5), rf: None };
352
353/// Walbeck
354pub const WALBECK: Ellipsoidal = Ellipsoidal { a: 6_376_896.0, b: Some(6_355_834.846_7), rf: None };
355
356/// WGS 60
357pub const WGS60: Ellipsoidal = Ellipsoidal { a: 6_378_165.0, b: None, rf: Some(298.3) };
358
359/// WGS 66
360pub const WGS66: Ellipsoidal = Ellipsoidal { a: 6_378_145.0, b: None, rf: Some(298.25) };
361
362/// Normal Sphere (r=6370997)
363pub const SPHERE: Ellipsoidal = Ellipsoidal { a: 6_370_997.0, b: Some(6_370_997.0), rf: None };
364
365/// Given a name, return the corresponding ellipsoid
366#[cfg_attr(feature = "nightly", coverage(off))]
367pub fn get_ellipsoid_from_id(id: i64) -> Option<Ellipsoidal> {
368    match id {
369        1024 => Some(CGCS2000),
370        1025 => Some(GSK_2011),
371        1026 => Some(ZACH),
372        7001 => Some(AIRY),
373        7002 => Some(MOD_AIRY),
374        7003 => Some(AUST_SA),
375        7004 => Some(BESSEL),
376        7005 => Some(MOD_BESSEL),
377        7007 => Some(CLRK58),
378        7008 => Some(CLRK66),
379        7010 => Some(CLRK80BEN),
380        7011 => Some(CLRK80IGN),
381        7012 => Some(CLRK80RGS),
382        7013 => Some(CLRK80ARC),
383        7014 => Some(CLRK80SGA),
384        7015 => Some(EVRST30),
385        7016 => Some(EVRST67),
386        7018 => Some(EVRST30_MOD),
387        7019 => Some(GRS80),
388        7020 => Some(HELMERT),
389        7021 => Some(INDONESIAN),
390        7022 => Some(INTL24),
391        7024 => Some(KRASS),
392        7025 => Some(NWL9D),
393        7027 => Some(PLESSIS),
394        7028 => Some(STRUVE),
395        7029 => Some(WARO),
396        7030 => Some(WGS84),
397        7031 => Some(GEM10C),
398        7032 => Some(OSU86F),
399        7033 => Some(OSU91A),
400        7034 => Some(CLRK80),
401        7036 => Some(GRS67),
402        7041 => Some(ATS77),
403        7042 => Some(EVRST1830),
404        7043 => Some(WGS7),
405        7044 => Some(EVRST62),
406        7045 => Some(EVRST75),
407        7046 => Some(BESS_NAM),
408        7048 => Some(GRS80_AUTH),
409        7049 => Some(IAG75),
410        7050 => Some(GRS_MOD),
411        7051 => Some(DANISH),
412        7052 => Some(CLRK_AUTH),
413        7053 => Some(HOUGH),
414        7054 => Some(PZ90),
415        7055 => Some(CLRK80FOOT),
416        7056 => Some(EVRST_RSO),
417        7057 => Some(INTL1924_AUTH),
418        7058 => Some(HUGHES),
419        _ => None,
420    }
421}
422
423/// Given a name, return the corresponding ellipsoid
424#[cfg_attr(feature = "nightly", coverage(off))]
425pub fn get_ellipsoid(name: &str) -> Option<Ellipsoidal> {
426    // fix name to remove _ and convert to uppercase
427    let name = name.to_uppercase().replace("_", "");
428    match name.as_str() {
429        "AIRY" => Some(AIRY),
430        "APL4" => Some(APL4),
431        "NWL9D" => Some(NWL9D),
432        "NWL10D" => Some(NWL10D),
433        "MODAIRY" => Some(MOD_AIRY),
434        "ANDRAE" => Some(ANDRAE),
435        "AUSTSA" => Some(AUST_SA),
436        "GRS67" => Some(GRS67),
437        "BESSEL" => Some(BESSEL),
438        "MODBESSEL" => Some(MOD_BESSEL),
439        "BESSNAM" => Some(BESS_NAM),
440        "CLRK58" => Some(CLRK58),
441        "CLRK66" => Some(CLRK66),
442        "CLRK80" => Some(CLRK80),
443        "CLRK80MICH" => Some(CLRK80MICH),
444        "CLRK80BEN" => Some(CLRK80BEN),
445        "CLRK80IGN" => Some(CLRK80IGN),
446        "CLRK80RGS" => Some(CLRK80RGS),
447        "CLRK80ARC" => Some(CLRK80ARC),
448        "CLRK80SGA" => Some(CLRK80SGA),
449        "CPM" => Some(CPM),
450        "DELMBR" => Some(DELMBR),
451        "ENGLIS" => Some(ENGELIS),
452        "EVRST30" => Some(EVRST30),
453        "EVRST48" => Some(EVRST48),
454        "EVRST30MOD" => Some(EVRST30_MOD),
455        "EVRST56" => Some(EVRST56),
456        "EVRSTSS" => Some(EVRSTSS),
457        "EVRST67" => Some(EVRST67),
458        "EVRST69" => Some(EVRST69),
459        "EVRST75" => Some(EVRST75),
460        "FSCHR60" => Some(FSCHR60),
461        "FSCHR60M" => Some(FSCHR60M),
462        "FSCHR68" => Some(FSCHR68),
463        "GEM10C" => Some(GEM10C),
464        "GRS80" => Some(GRS80),
465        "HELMERT" => Some(HELMERT),
466        "HOUGH" => Some(HOUGH),
467        "IAU76" => Some(IAU76),
468        "INDONESIAN" => Some(INDONESIAN),
469        "INTL" => Some(INTL),
470        "INTL09" => Some(INTL09),
471        "INTL24" => Some(INTL24),
472        "INTL67" => Some(INTL67),
473        "KAULA" => Some(KAULA),
474        "LERCH" => Some(LERCH),
475        "MPRTS" => Some(MPRTS),
476        "NEWINTL" => Some(NEW_INTL),
477        "PLESSIS" => Some(PLESSIS),
478        "KRASS" => Some(KRASS),
479        "SEASIA" => Some(SEASIA),
480        "STRUVE" => Some(STRUVE),
481        "MERIT" => Some(MERIT),
482        "SGS85" => Some(SGS85),
483        "OSU86F" => Some(OSU86F),
484        "OSU91A" => Some(OSU91A),
485        "WGS66" => Some(WGS66),
486        "WGS7" => Some(WGS7),
487        "WGS84" => Some(WGS84),
488        "WGS60" => Some(WGS60),
489        "SPHERE" => Some(SPHERE),
490        "WARO" => Some(WARO),
491        "WALBECK" => Some(WALBECK),
492        _ => None,
493    }
494}