Passed
Push — 4.x ( 17e0c5...e9b635 )
by Doug
07:44
created

Ellipsoid   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 400
Duplicated Lines 0 %

Test Coverage

Coverage 91.3%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 8
eloc 69
c 1
b 0
f 0
dl 0
loc 400
ccs 21
cts 23
cp 0.913
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getSemiMinorAxis() 0 3 1
A getSemiMajorAxis() 0 3 1
A getInverseFlattening() 0 3 1
A getEccentricitySquared() 0 3 1
A getFlattening() 0 3 1
A fromEPSGCode() 0 14 2
1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord\Datum;
10
11
use PHPCoord\EPSG\Repository;
12
use PHPCoord\Exception\UnknownEllipsoidException;
13
use PHPCoord\UnitOfMeasure\Length\Length;
14
use PHPCoord\UnitOfMeasure\UnitOfMeasureFactory;
15
16
class Ellipsoid
17
{
18
    /**
19
     * Airy 1830
20
     * Original definition is a=20923713, b=20853810 feet of 1796. 1/f is given to 7 decimal places. For the 1936
21
     * retriangulation OSGB defines the relationship of 10 feet of 1796 to the International metre through
22
     * ([10^0.48401603]/10) exactly = 0.3048007491...
23
     */
24
    public const EPSG_AIRY_1830 = 7001;
25
26
    /**
27
     * Airy Modified 1849
28
     * OSGB Airy 1830 figure (ellipsoid code 7001) rescaled by 0.999965 to best fit the scale of the 19th century
29
     * primary triangulation of Ireland.
30
     */
31
    public const EPSG_AIRY_MODIFIED_1849 = 7002;
32
33
    /**
34
     * Australian National Spheroid
35
     * Based on the GRS 1967 figure but with 1/f taken to 2 decimal places exactly.  The dimensions are also used as
36
     * the GRS 1967 Modified ellipsoid (see code 7050).
37
     */
38
    public const EPSG_AUSTRALIAN_NATIONAL_SPHEROID = 7003;
39
40
    /**
41
     * Average Terrestrial System 1977.
42
     */
43
    public const EPSG_AVERAGE_TERRESTRIAL_SYSTEM_1977 = 7041;
44
45
    /**
46
     * Bessel 1841
47
     * Original Bessel definition is a=3272077.14 and b=3261139.33 toise. This used a weighted mean of values from
48
     * several authors but did not account for differences in the length of the various toise: the "Bessel toise" is
49
     * therefore of uncertain length.
50
     */
51
    public const EPSG_BESSEL_1841 = 7004;
52
53
    /**
54
     * Bessel Modified
55
     * Used in Norway and also in Sweden with a 1mm increase in semi-major axis.
56
     */
57
    public const EPSG_BESSEL_MODIFIED = 7005;
58
59
    /**
60
     * Bessel Namibia (GLM)
61
     * The semi-major axis has the same value as the Bessel 1841 ellipsoid (code 7004) but is in different units -
62
     * German Legal Metres rather than International metres - hence a different size.  a = 6377483.865 International
63
     * metres. Used in Namibia.
64
     */
65
    public const EPSG_BESSEL_NAMIBIA_GLM = 7046;
66
67
    /**
68
     * CGCS2000
69
     * Defining parameters semi-major axis, flattening and angular velocity are same as for GRS 1980 (ellipsoid code
70
     * 7019); GM = 3986004.4e8 m*m*m/s/s (from NASA 1986 Lageos determination).
71
     */
72
    public const EPSG_CGCS2000 = 1024;
73
74
    /**
75
     * Clarke 1858
76
     * Clarke's 1858/II solution. Derived parameters: a = 6378293.645m using his 1865 ratio of 0.3047972654 feet per
77
     * metre; 1/f = 294.26068…  In Australia and Amoco Trinidad 1/f taken to two decimal places (294.26 exactly);
78
     * elsewhere a and b used to derive 1/f.
79
     */
80
    public const EPSG_CLARKE_1858 = 7007;
81
82
    /**
83
     * Clarke 1866
84
     * Original definition a=20926062 and b=20855121 (British) feet. Uses Clarke's 1865 inch-metre ratio of 39.370432
85
     * to obtain metres. (Metric value then converted to US survey feet for use in the US and international feet for
86
     * use in Cayman Islands).
87
     */
88
    public const EPSG_CLARKE_1866 = 7008;
89
90
    /**
91
     * Clarke 1866 Authalic Sphere
92
     * Authalic sphere derived from Clarke 1866 ellipsoid (code 7008).
93
     */
94
    public const EPSG_CLARKE_1866_AUTHALIC_SPHERE = 7052;
95
96
    /**
97
     * Clarke 1880
98
     * Clarke gave a and b and also 1/f=293.465 (to 3 decimal places exactly). In the 19th century b was normally given
99
     * as the second defining parameter.
100
     */
101
    public const EPSG_CLARKE_1880 = 7034;
102
103
    /**
104
     * Clarke 1880 (Arc)
105
     * Adopts Clarke's value for a with derived 1/f.  Uses his 1865 ratio of 39.370432 inch per metre to convert
106
     * semi-major axis to metres.
107
     */
108
    public const EPSG_CLARKE_1880_ARC = 7013;
109
110
    /**
111
     * Clarke 1880 (Benoit)
112
     * Adopts Clarke's values for a and b.  Uses Benoit's 1895 ratio of 0.9143992 metres per yard to convert to metres.
113
     */
114
    public const EPSG_CLARKE_1880_BENOIT = 7010;
115
116
    /**
117
     * Clarke 1880 (IGN)
118
     * Adopts Clarke's values for a and b using his 1865 ratio of 39.370432 inches per metre to convert axes to metres.
119
     */
120
    public const EPSG_CLARKE_1880_IGN = 7011;
121
122
    /**
123
     * Clarke 1880 (RGS)
124
     * Adopts Clarke's values for a and 1/f.  Adopts his 1865 ratio of 39.370432 inches per metre to convert semi-major
125
     * axis to metres. Also known as Clarke Modified 1880.
126
     */
127
    public const EPSG_CLARKE_1880_RGS = 7012;
128
129
    /**
130
     * Clarke 1880 (SGA 1922)
131
     * Used in Old French Triangulation (ATF).   Uses Clarke's 1865 inch-metre ratio of 39.370432 to convert axes to
132
     * metres.
133
     */
134
    public const EPSG_CLARKE_1880_SGA_1922 = 7014;
135
136
    /**
137
     * Clarke 1880 (international foot)
138
     * Clarke's 1880 definition in feet assumed for the purposes of metric conversion to be international foot. a =
139
     * 6378306.370…metres. 1/f derived from a and b = 293.4663077… Used in Fiji.
140
     */
141
    public const EPSG_CLARKE_1880_INTERNATIONAL_FOOT = 7055;
142
143
    /**
144
     * Danish 1876
145
     * Semi-major axis originally given as 3271883.25 toise. Uses toise to French metre ratio of 1.94903631 to two
146
     * decimal place precision. An alternative ratio with the German legal metre of 1.9490622 giving 6377104m has not
147
     * been used in Danish work.
148
     */
149
    public const EPSG_DANISH_1876 = 7051;
150
151
    /**
152
     * Everest (1830 Definition)
153
     * Everest gave a and b to 2 decimal places and also 1/f=300.8017 (to 4 decimal places exactly). In the 19th
154
     * century b was normally given as the second defining parameter.
155
     */
156
    public const EPSG_EVEREST_1830_DEFINITION = 7042;
157
158
    /**
159
     * Everest 1830 (1937 Adjustment)
160
     * Used for the 1937 readjustment of Indian triangulation.  Clarke's 1865 Indian-British foot ratio (0.99999566)
161
     * and Benoit's 1898 British inch-metre ratio (39.370113) rounded as 0.30479841 exactly and applied to Everest's
162
     * 1830 definition taken as a and 1/f.
163
     */
164
    public const EPSG_EVEREST_1830_1937_ADJUSTMENT = 7015;
165
166
    /**
167
     * Everest 1830 (1962 Definition)
168
     * Used by Pakistan since metrication.  Clarke's 1865 Indian foot-British foot ratio (0.99999566) and his 1865
169
     * British inch-metre ratio (39.369971) rounded with slight error as 1 Ind ft = 0.3047995m exactly and applied to
170
     * Everest's 1830 definition of a & b.
171
     */
172
    public const EPSG_EVEREST_1830_1962_DEFINITION = 7044;
173
174
    /**
175
     * Everest 1830 (1967 Definition)
176
     * Adopted 1967 for use in East Malaysia.  Applies Sears 1922 inch-metre ratio of 39.370147 to Everest 1830
177
     * original definition of a and 1/f but with a taken to be in British rather than Indian feet.
178
     */
179
    public const EPSG_EVEREST_1830_1967_DEFINITION = 7016;
180
181
    /**
182
     * Everest 1830 (1975 Definition)
183
     * Used by India since metrication.  Clarke's 1865 Indian foot-British foot ratio (0.99999566) and his 1865 British
184
     * inch-metre ratio (39.369971) rounded as 1 Ind ft = 0.3047995m exactly applied to Everest's 1830 original
185
     * definition taken as a and b.
186
     */
187
    public const EPSG_EVEREST_1830_1975_DEFINITION = 7045;
188
189
    /**
190
     * Everest 1830 (RSO 1969)
191
     * Adopted for 1969 metrication of peninsula Malaysia RSO grid.  Uses Sears 1922 yard-metre ratio truncated to 6
192
     * significant figures applied to Everest 1830 original definition of a and 1/f but with a taken to be in British
193
     * rather than Indian feet.
194
     */
195
    public const EPSG_EVEREST_1830_RSO_1969 = 7056;
196
197
    /**
198
     * Everest 1830 Modified
199
     * Adopted 1967 for use in West Malaysia.  Applies Benoit 1898 inch-metre ratio of 39.370113 to Everest 1830
200
     * original definition of a and 1/f but with a taken to be in British rather than Indian feet.
201
     */
202
    public const EPSG_EVEREST_1830_MODIFIED = 7018;
203
204
    /**
205
     * GEM 10C
206
     * Used for  GEM 10C Gravity Potential Model.
207
     */
208
    public const EPSG_GEM_10C = 7031;
209
210
    /**
211
     * GRS 1967
212
     * Adopted by IUGG 1967 Lucerne.  1/f given is derived from geocentric gravitational constant (GM)= 398603e9
213
     * m*m*m/s/s; dynamic form factor (J2) = 0.0010827 and Earth's angular velocity w = 7.2921151467e-5 rad/s. See also
214
     * GRS 1967 Modified (code 7050).
215
     */
216
    public const EPSG_GRS_1967 = 7036;
217
218
    /**
219
     * GRS 1967 Modified
220
     * Based on the GRS 1967 figure (code 7036) but with 1/f taken to 2 decimal places exactly. Used with SAD69 and
221
     * TWD67 datums. The dimensions are also used as the Australian National Spheroid (code 7003).
222
     */
223
    public const EPSG_GRS_1967_MODIFIED = 7050;
224
225
    /**
226
     * GRS 1980
227
     * Adopted by IUGG 1979 Canberra.  Inverse flattening is derived from geocentric gravitational constant GM =
228
     * 3986005e8 m*m*m/s/s; dynamic form factor J2 = 108263e-8 and Earth's angular velocity = 7292115e-11 rad/s.
229
     */
230
    public const EPSG_GRS_1980 = 7019;
231
232
    /**
233
     * GRS 1980 Authalic Sphere
234
     * Authalic sphere derived from GRS 1980 ellipsoid (code 7019).  (An authalic sphere is one with a surface area
235
     * equal to the surface area of the ellipsoid). 1/f is infinite.
236
     */
237
    public const EPSG_GRS_1980_AUTHALIC_SPHERE = 7048;
238
239
    /**
240
     * GSK-2011.
241
     */
242
    public const EPSG_GSK_2011 = 1025;
243
244
    /**
245
     * Helmert 1906
246
     * Helmert 1906/III solution.
247
     */
248
    public const EPSG_HELMERT_1906 = 7020;
249
250
    /**
251
     * Hough 1960.
252
     */
253
    public const EPSG_HOUGH_1960 = 7053;
254
255
    /**
256
     * Hughes 1980
257
     * Used in US DMSP SSM/I microwave sensor processing software. Semi-minor axis derived from
258
     * eccentricity=0.081816153. Semi-major axis (a) sometimes given as 3443.992nm which OGP suspects is a derived
259
     * approximation. OGP conversion assumes 1nm=1852m exactly.
260
     */
261
    public const EPSG_HUGHES_1980 = 7058;
262
263
    /**
264
     * IAG 1975.
265
     */
266
    public const EPSG_IAG_1975 = 7049;
267
268
    /**
269
     * Indonesian National Spheroid
270
     * Based on the GRS 1967 figure but with 1/f taken to 3 decimal places exactly.
271
     */
272
    public const EPSG_INDONESIAN_NATIONAL_SPHEROID = 7021;
273
274
    /**
275
     * International 1924
276
     * Adopted by IUGG 1924 in Madrid. Based on Hayford 1909/1910 figures.
277
     */
278
    public const EPSG_INTERNATIONAL_1924 = 7022;
279
280
    /**
281
     * International 1924 Authalic Sphere
282
     * Authalic sphere derived from International 1924 ellipsoid (code 7022).
283
     */
284
    public const EPSG_INTERNATIONAL_1924_AUTHALIC_SPHERE = 7057;
285
286
    /**
287
     * Krassowsky 1940.
288
     */
289
    public const EPSG_KRASSOWSKY_1940 = 7024;
290
291
    /**
292
     * NWL 9D
293
     * Used by Transit Precise Ephemeris between October 1971 and January 1987.
294
     */
295
    public const EPSG_NWL_9D = 7025;
296
297
    /**
298
     * OSU86F
299
     * Used for OSU86 gravity potential (geoidal) model.
300
     */
301
    public const EPSG_OSU86F = 7032;
302
303
    /**
304
     * OSU91A
305
     * Used for OSU91 gravity potential (geoidal) model.
306
     */
307
    public const EPSG_OSU91A = 7033;
308
309
    /**
310
     * PZ-90
311
     * Earth's angular velocity ω = 7.292115e-5 rad/sec; gravitational constant GM =  3986004.418e8 m*m*m/s/s.
312
     */
313
    public const EPSG_PZ_90 = 7054;
314
315
    /**
316
     * Plessis 1817
317
     * Rescaling of Delambre 1810 figure (a=6376985 m) to make meridional arc from equator to pole equal to 10000000
318
     * metres exactly. (Ref: Strasser).
319
     */
320
    public const EPSG_PLESSIS_1817 = 7027;
321
322
    /**
323
     * Struve 1860
324
     * Original definition of semi-major axis given as 3272539 toise.  In "Ellipsoidisch Parameter der Erdfigur
325
     * (1800-1950)" , Strasser suggests a conversion factor of 1.94903631 which gives a=6378297.337 metres.
326
     */
327
    public const EPSG_STRUVE_1860 = 7028;
328
329
    /**
330
     * WGS 72.
331
     */
332
    public const EPSG_WGS_72 = 7043;
333
334
    /**
335
     * WGS 84
336
     * 1/f derived from four defining parameters semi-major axis; C20 = -484.16685*10e-6; earth's angular velocity ω =
337
     * 7292115e-11 rad/sec; gravitational constant GM = 3986005e8 m*m*m/s/s. In 1994 new GM = 3986004.418e8 m*m*m/s/s
338
     * but a and 1/f retained.
339
     */
340
    public const EPSG_WGS_84 = 7030;
341
342
    /**
343
     * War Office
344
     * In non-metric form, a=20926201 Gold Coast feet. DMA Technical Manual 8358.1 and data derived from this quotes
345
     * value for semi-major axis as 6378300.58m: OGP recommends use of defined value 6378300m exactly.
346
     */
347
    public const EPSG_WAR_OFFICE = 7029;
348
349
    /**
350
     * Zach 1812
351
     * Defined as log a = 6.5266022 Klafter (Austrian fathom, Kl), log b = 6.5251990 Kl. a=10^6.526 6022 = 3362035 Kl.
352
     * Then using the Austro-Hungarian 1871 KL/m legal ratio of 1.89648384, a = 6376045m.
353
     */
354
    public const EPSG_ZACH_1812 = 1026;
355
356
    /**
357
     * @var Repository
358
     */
359
    private static $repository;
360
361
    /**
362
     * @var Length
363
     */
364
    protected $semiMajorAxis;
365
366
    /**
367
     * @var Length
368
     */
369
    protected $semiMinorAxis;
370
371 52
    public function __construct(Length $semiMajorAxis, Length $semiMinorAxis)
372
    {
373 52
        $this->semiMajorAxis = $semiMajorAxis;
374 52
        $this->semiMinorAxis = $semiMinorAxis;
375 52
    }
376
377 17
    public function getSemiMajorAxis(): Length
378
    {
379 17
        return $this->semiMajorAxis;
380
    }
381
382 5
    public function getSemiMinorAxis(): Length
383
    {
384 5
        return $this->semiMinorAxis;
385
    }
386
387
    public function getFlattening(): float
388
    {
389
        return $this->semiMajorAxis->getValue() / ($this->semiMajorAxis->getValue() - $this->semiMinorAxis->getValue());
390
    }
391
392 15
    public function getInverseFlattening(): float
393
    {
394 15
        return ($this->semiMajorAxis->getValue() - $this->semiMinorAxis->getValue()) / $this->semiMajorAxis->getValue();
395
    }
396
397 15
    public function getEccentricitySquared(): float
398
    {
399 15
        return (2 * $this->getInverseFlattening()) - $this->getInverseFlattening() ** 2;
400
    }
401
402 53
    public static function fromEPSGCode(int $epsgCode): self
403
    {
404 53
        $repository = static::$repository ?? new Repository();
0 ignored issues
show
Bug introduced by
Since $repository is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $repository to at least protected.
Loading history...
405 53
        $allData = $repository->getEllipsoids();
406
407 53
        if (!isset($allData[$epsgCode])) {
408 1
            throw new UnknownEllipsoidException($epsgCode);
409
        }
410
411 52
        $data = $allData[$epsgCode];
412
413 52
        return new self(
414 52
            UnitOfMeasureFactory::makeUnit($data['semi_major_axis'], $data['uom_code']),
0 ignored issues
show
Bug introduced by
It seems like PHPCoord\UnitOfMeasure\U...s'], $data['uom_code']) can also be of type PHPCoord\UnitOfMeasure\Angle\ArcSecond and PHPCoord\UnitOfMeasure\Angle\Degree and PHPCoord\UnitOfMeasure\Angle\ExoticAngle and PHPCoord\UnitOfMeasure\Angle\Radian and PHPCoord\UnitOfMeasure\Rate and PHPCoord\UnitOfMeasure\Scale\ExoticScale and PHPCoord\UnitOfMeasure\Scale\Unity and PHPCoord\UnitOfMeasure\Time\Second and PHPCoord\UnitOfMeasure\Time\Year; however, parameter $semiMajorAxis of PHPCoord\Datum\Ellipsoid::__construct() does only seem to accept PHPCoord\UnitOfMeasure\Length\Length, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

414
            /** @scrutinizer ignore-type */ UnitOfMeasureFactory::makeUnit($data['semi_major_axis'], $data['uom_code']),
Loading history...
415 52
            UnitOfMeasureFactory::makeUnit($data['semi_minor_axis'], $data['uom_code'])
0 ignored issues
show
Bug introduced by
It seems like PHPCoord\UnitOfMeasure\U...s'], $data['uom_code']) can also be of type PHPCoord\UnitOfMeasure\Angle\ArcSecond and PHPCoord\UnitOfMeasure\Angle\Degree and PHPCoord\UnitOfMeasure\Angle\ExoticAngle and PHPCoord\UnitOfMeasure\Angle\Radian and PHPCoord\UnitOfMeasure\Rate and PHPCoord\UnitOfMeasure\Scale\ExoticScale and PHPCoord\UnitOfMeasure\Scale\Unity and PHPCoord\UnitOfMeasure\Time\Second and PHPCoord\UnitOfMeasure\Time\Year; however, parameter $semiMinorAxis of PHPCoord\Datum\Ellipsoid::__construct() does only seem to accept PHPCoord\UnitOfMeasure\Length\Length, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

415
            /** @scrutinizer ignore-type */ UnitOfMeasureFactory::makeUnit($data['semi_minor_axis'], $data['uom_code'])
Loading history...
416
        );
417
    }
418
}
419