Ellipsoid::getName()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the Geotools library.
5
 *
6
 * (c) Antoine Corcy <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace League\Geotools\Coordinate;
13
14
use League\Geotools\Exception\InvalidArgumentException;
15
use League\Geotools\Exception\NotMatchingEllipsoidException;
16
17
/**
18
 * Ellipsoid class
19
 *
20
 * @author Antoine Corcy <[email protected]>
21
 *
22
 * @see    http://en.wikipedia.org/wiki/Reference_ellipsoid
23
 * @see    http://www.colorado.edu/geography/gcraft/notes/datum/gif/ellipse.gif
24
 */
25
class Ellipsoid
26
{
27
    /**
28
     * List of selected reference ellipsoids.
29
     *
30
     * @var string
31
     */
32
    const AIRY                  = 'AIRY';
33
    const AUSTRALIAN_NATIONAL   = 'AUSTRALIAN_NATIONAL';
34
    const BESSEL_1841           = 'BESSEL_1841';
35
    const BESSEL_1841_NAMBIA    = 'BESSEL_1841_NAMBIA';
36
    const CLARKE_1866           = 'CLARKE_1866';
37
    const CLARKE_1880           = 'CLARKE_1880';
38
    const EVEREST               = 'EVEREST';
39
    const FISCHER_1960_MERCURY  = 'FISCHER_1960_MERCURY';
40
    const FISCHER_1968          = 'FISCHER_1968';
41
    const GRS_1967              = 'GRS_1967';
42
    const GRS_1980              = 'GRS_1980';
43
    const HELMERT_1906          = 'HELMERT_1906';
44
    const HOUGH                 = 'HOUGH';
45
    const INTERNATIONAL         = 'INTERNATIONAL';
46
    const KRASSOVSKY            = 'KRASSOVSKY';
47
    const MODIFIED_AIRY         = 'MODIFIED_AIRY';
48
    const MODIFIED_EVEREST      = 'MODIFIED_EVEREST';
49
    const MODIFIED_FISCHER_1960 = 'MODIFIED_FISCHER_1960';
50
    const SOUTH_AMERICAN_1969   = 'SOUTH_AMERICAN_1969';
51
    const WGS60                 = 'WGS60';
52
    const WGS66                 = 'WGS66';
53
    const WGS72                 = 'WGS72';
54
    const WGS84                 = 'WGS84';
55
56
    /**
57
     * The name of the Ellipsoid.
58
     *
59
     * @var string
60
     */
61
    protected $name;
62
63
    /**
64
     * The semi-major axis (equatorial radius) in meters.
65
     * @see http://en.wikipedia.org/wiki/Earth_radius
66
     * @see http://home.online.no/~sigurdhu/WGS84_Eng.html
67
     *
68
     * @var double
69
     */
70
    protected $a;
71
72
    /**
73
     * The inverse flattening.
74
     * @see http://home.online.no/~sigurdhu/WGS84_Eng.html
75
     *
76
     * @var double
77
     */
78
    protected $invF;
79
80
    /**
81
     * Selected reference ellipsoids.
82
     * Source: Defense Mapping Agency. 1987b. Washington, DC: Defense Mapping Agency
83
     * DMA Technical Report: Supplement to Department of Defense World Geodetic System 1984 Technical Report.
84
     * @see http://en.wikipedia.org/wiki/Geodetic_datum
85
     * @see http://www.colorado.edu/geography/gcraft/notes/datum/gif/refellip.gif
86
     *
87
     * @var array
88
     */
89
    protected static $referenceEllipsoids = array(
90
        self::AIRY => array(
91
            'name' => 'Airy',
92
            'a'    => 6377563.396,
93
            'invF' => 299.3249646,
94
        ),
95
        self::AUSTRALIAN_NATIONAL => array(
96
            'name' => 'Australian National',
97
            'a'    => 6378160.0,
98
            'invF' => 298.25,
99
        ),
100
        self::BESSEL_1841 => array(
101
            'name' => 'Bessel 1841',
102
            'a'    => 6377397.155,
103
            'invF' => 299.1528128,
104
        ),
105
        self::BESSEL_1841_NAMBIA => array(
106
            'name' => 'Bessel 1841 (Nambia)',
107
            'a'    => 6377483.865,
108
            'invF' => 299.1528128,
109
        ),
110
        self::CLARKE_1866 => array(
111
            'name' => 'Clarke 1866',
112
            'a'    => 6378206.4,
113
            'invF' => 294.9786982,
114
        ),
115
        self::CLARKE_1880 => array(
116
            'name' => 'Clarke 1880',
117
            'a'    => 6378249.145,
118
            'invF' => 293.465,
119
        ),
120
        self::EVEREST => array(
121
            'name' => 'Everest',
122
            'a'    => 6377276.345,
123
            'invF' => 300.8017,
124
        ),
125
        self::FISCHER_1960_MERCURY => array(
126
            'name' => 'Fischer 1960 (Mercury)',
127
            'a'    => 6378166.0,
128
            'invF' => 298.3,
129
        ),
130
        self::FISCHER_1968 => array(
131
            'name' => 'Fischer 1968',
132
            'a'    => 6378150.0,
133
            'invF' => 298.3,
134
        ),
135
        self::GRS_1967 => array(
136
            'name' => 'GRS 1967',
137
            'a'    => 6378160.0,
138
            'invF' => 298.247167427,
139
        ),
140
        self::GRS_1980 => array(
141
            'name' => 'GRS 1980',
142
            'a'    => 6378137,
143
            'invF' => 298.257222101,
144
        ),
145
        self::HELMERT_1906 => array(
146
            'name' => 'Helmert 1906',
147
            'a'    => 6378200.0,
148
            'invF' => 298.3,
149
        ),
150
        self::HOUGH => array(
151
            'name' => 'Hough',
152
            'a'    => 6378270.0,
153
            'invF' => 297.0,
154
        ),
155
        self::INTERNATIONAL => array(
156
            'name' => 'International',
157
            'a'    => 6378388.0,
158
            'invF' => 297.0,
159
        ),
160
        self::KRASSOVSKY => array(
161
            'name' => 'Krassovsky',
162
            'a'    => 6378245.0,
163
            'invF' => 298.3,
164
        ),
165
        self::MODIFIED_AIRY => array(
166
            'name' => 'Modified Airy',
167
            'a'    => 6377340.189,
168
            'invF' => 299.3249646,
169
        ),
170
        self::MODIFIED_EVEREST => array(
171
            'name' => 'Modified Everest',
172
            'a'    => 6377304.063,
173
            'invF' => 300.8017,
174
        ),
175
        self::MODIFIED_FISCHER_1960 => array(
176
            'name' => 'Modified Fischer 1960',
177
            'a'    => 6378155.0,
178
            'invF' => 298.3,
179
        ),
180
        self::SOUTH_AMERICAN_1969 => array(
181
            'name' => 'South American 1969',
182
            'a'    => 6378160.0,
183
            'invF' => 298.25,
184
        ),
185
        self::WGS60 => array(
186
            'name' => 'WGS 60',
187
            'a'    => 6378165.0,
188
            'invF' => 298.3,
189
        ),
190
        self::WGS66 => array(
191
            'name' => 'WGS 66',
192
            'a'    => 6378145.0,
193
            'invF' => 298.25,
194
        ),
195
        self::WGS72 => array(
196
            'name' => 'WGS 72',
197
            'a'    => 6378135.0,
198
            'invF' => 298.26,
199
        ),
200
        self::WGS84 => array(
201
            'name' => 'WGS 84',
202
            'a'    => 6378136.0,
203
            'invF' => 298.257223563,
204
        ),
205
    );
206
207
208
    /**
209
     * Create a new ellipsoid.
210
     *
211
     * @param string $name The name of the ellipsoid to create.
212
     * @param double $a    The semi-major axis (equatorial radius) in meters.
213
     * @param double $invF The inverse flattening.
214
     *
215
     * @throws InvalidArgumentException
216
     */
217 252
    public function __construct($name, $a, $invF)
218
    {
219 252
        if (0.0 >= (double) $invF) {
220 8
            throw new InvalidArgumentException('The inverse flattening cannot be negative or equal to zero !');
221
        }
222
223 244
        $this->name = $name;
224 244
        $this->a    = $a;
225 244
        $this->invF = $invF;
226 244
    }
227
228
    /**
229
     * Create the ellipsoid chosen by its name.
230
     *
231
     * @param string $name The name of the ellipsoid to create (optional).
232
     *
233
     * @return Ellipsoid
234
     */
235 268
    public static function createFromName($name = self::WGS84)
236
    {
237 268
        $name = trim($name);
238
239 268
        if (empty($name)) {
240 15
            throw new InvalidArgumentException('Please provide an ellipsoid name !');
241
        }
242
243 253
        if (!array_key_exists($name, self::$referenceEllipsoids)) {
244 15
            throw new InvalidArgumentException(
245 15
                sprintf('%s ellipsoid does not exist in selected reference ellipsoids !', $name)
246
            );
247
        }
248
249 238
        return self::createFromArray(self::$referenceEllipsoids[$name]);
250
    }
251
252
    /**
253
     * Create an ellipsoid from an array.
254
     *
255
     * @param array $newEllipsoid The ellipsoid's parameters to create.
256
     *
257
     * @return Ellipsoid
258
     */
259 246
    public static function createFromArray(array $newEllipsoid)
260
    {
261 246
        if (!isset($newEllipsoid['name']) || !isset($newEllipsoid['a']) || !isset($newEllipsoid['invF'])
262 246
            || 3 !== count($newEllipsoid)) {
263 5
            throw new InvalidArgumentException('Ellipsoid arrays should contain `name`, `a` and `invF` keys !');
264
        }
265
266 241
        return new self($newEllipsoid['name'], $newEllipsoid['a'], $newEllipsoid['invF']);
267
    }
268
269
    /**
270
     * Check if coordinates have the same ellipsoid.
271
     *
272
     * @param CoordinateInterface $a A coordinate.
273
     * @param CoordinateInterface $b A coordinate.
274
     *
275
     * @throws NotMatchingEllipsoidException
276
     */
277 84
    public static function checkCoordinatesEllipsoid(CoordinateInterface $a, CoordinateInterface $b)
278
    {
279 84
        if ($a->getEllipsoid() != $b->getEllipsoid()) {
280 1
            throw new NotMatchingEllipsoidException('The ellipsoids for both coordinates must match !');
281
        }
282 83
    }
283
284
    /**
285
     * Returns the ellipsoid's name.
286
     *
287
     * @return string
288
     */
289 5
    public function getName()
290
    {
291 5
        return $this->name;
292
    }
293
294
    /**
295
     * Returns the semi-major axis (equatorial radius) in meters.
296
     *
297
     * @return double
298
     */
299 94
    public function getA()
300
    {
301 94
        return (double) $this->a;
302
    }
303
304
    /**
305
     * Computes and returns the semi-minor axis (polar distance) in meters.
306
     * @see http://home.online.no/~sigurdhu/WGS84_Eng.html
307
     *
308
     * @return double
309
     */
310 55
    public function getB()
311
    {
312 55
        return (double) $this->a * (1 - 1 / $this->invF);
313
    }
314
315
    /**
316
     * Returns the inverse flattening.
317
     *
318
     * @return double
319
     */
320 23
    public function getInvF()
321
    {
322 23
        return (double) $this->invF;
323
    }
324
325
    /**
326
     * Computes and returns the arithmetic mean radius in meters.
327
     * @see http://home.online.no/~sigurdhu/WGS84_Eng.html
328
     *
329
     * @return double
330
     */
331 5
    public function getArithmeticMeanRadius()
332
    {
333 5
        return (double) $this->a * (1 - 1 / $this->invF / 3);
334
    }
335
336
    /**
337
     * Returns the list of available ellipsoids sorted by alphabetical order.
338
     *
339
     * @return string The list of available ellipsoids comma separated.
340
     */
341 110
    public static function getAvailableEllipsoidNames()
342
    {
343 110
        ksort(self::$referenceEllipsoids);
344
345 110
        return implode(', ', array_keys(self::$referenceEllipsoids));
346
    }
347
}
348