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

Angle::makeUnit()   D

Complexity

Conditions 22
Paths 22

Size

Total Lines 48
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 44
CRAP Score 22

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 44
c 1
b 0
f 0
dl 0
loc 48
ccs 44
cts 44
cp 1
rs 4.1666
cc 22
nc 22
nop 2
crap 22

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord\UnitOfMeasure\Angle;
10
11
use PHPCoord\Exception\UnknownUnitOfMeasureException;
12
use PHPCoord\UnitOfMeasure\Time\Second;
13
use PHPCoord\UnitOfMeasure\UnitOfMeasure;
14
15
abstract class Angle implements UnitOfMeasure
16
{
17
    /**
18
     * arc-minute
19
     * 1/60th degree = ((pi/180) / 60) radians.
20
     */
21
    public const EPSG_ARC_MINUTE = 'urn:ogc:def:uom:EPSG::9103';
22
23
    /**
24
     * arc-second
25
     * 1/60th arc-minute = ((pi/180) / 3600) radians.
26
     */
27
    public const EPSG_ARC_SECOND = 'urn:ogc:def:uom:EPSG::9104';
28
29
    /**
30
     * centesimal minute
31
     * 1/100 of a grad and gon = ((pi/200) / 100) radians.
32
     */
33
    public const EPSG_CENTESIMAL_MINUTE = 'urn:ogc:def:uom:EPSG::9112';
34
35
    /**
36
     * centesimal second
37
     * 1/100 of a centesimal minute or 1/10,000th of a grad and gon = ((pi/200) / 10000) radians.
38
     */
39
    public const EPSG_CENTESIMAL_SECOND = 'urn:ogc:def:uom:EPSG::9113';
40
41
    /**
42
     * degree
43
     * = pi/180 radians.
44
     */
45
    public const EPSG_DEGREE = 'urn:ogc:def:uom:EPSG::9102';
46
47
    /**
48
     * degree (supplier to define representation)
49
     * = pi/180 radians. The degree representation (e.g. decimal, DMSH, etc.) must be clarified by suppliers of data
50
     * associated with this code.
51
     */
52
    public const EPSG_DEGREE_SUPPLIER_TO_DEFINE_REPRESENTATION = 'urn:ogc:def:uom:EPSG::9122';
53
54
    /**
55
     * degree hemisphere
56
     * Degree representation. Format: degrees (real, any precision) - hemisphere abbreviation (single character N S E
57
     * or W). Convert to degrees using algorithm.
58
     */
59
    public const EPSG_DEGREE_HEMISPHERE = 'urn:ogc:def:uom:EPSG::9116';
60
61
    /**
62
     * degree minute
63
     * Degree representation. Format: signed degrees (integer)  - arc-minutes (real, any precision). Different symbol
64
     * sets are in use as field separators, for example º '. Convert to degrees using algorithm.
65
     */
66
    public const EPSG_DEGREE_MINUTE = 'urn:ogc:def:uom:EPSG::9115';
67
68
    /**
69
     * degree minute hemisphere
70
     * Degree representation. Format: degrees (integer) - arc-minutes (real, any precision) - hemisphere abbreviation
71
     * (single character N S E or W). Different symbol sets are in use as field separators, for example º '. Convert
72
     * to degrees using algorithm.
73
     */
74
    public const EPSG_DEGREE_MINUTE_HEMISPHERE = 'urn:ogc:def:uom:EPSG::9118';
75
76
    /**
77
     * degree minute second
78
     * Degree representation. Format: signed degrees (integer) - arc-minutes (integer) - arc-seconds (real, any
79
     * precision). Different symbol sets are in use as field separators, for example º ' ". Convert to degrees using
80
     * algorithm.
81
     */
82
    public const EPSG_DEGREE_MINUTE_SECOND = 'urn:ogc:def:uom:EPSG::9107';
83
84
    /**
85
     * degree minute second hemisphere
86
     * Degree representation. Format: degrees (integer) - arc-minutes (integer) - arc-seconds (real) - hemisphere
87
     * abbreviation (single character N S E or W). Different symbol sets are in use as field separators for example º
88
     * ' ". Convert to deg using algorithm.
89
     */
90
    public const EPSG_DEGREE_MINUTE_SECOND_HEMISPHERE = 'urn:ogc:def:uom:EPSG::9108';
91
92
    /**
93
     * gon
94
     * =pi/200 radians.
95
     * @deprecated
96
     */
97
    public const EPSG_GON = 'urn:ogc:def:uom:EPSG::9106';
98
99
    /**
100
     * grad
101
     * =pi/200 radians.
102
     */
103
    public const EPSG_GRAD = 'urn:ogc:def:uom:EPSG::9105';
104
105
    /**
106
     * hemisphere degree
107
     * Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (real, any
108
     * precision). Convert to degrees using algorithm.
109
     */
110
    public const EPSG_HEMISPHERE_DEGREE = 'urn:ogc:def:uom:EPSG::9117';
111
112
    /**
113
     * hemisphere degree minute
114
     * Degree representation. Format:  hemisphere abbreviation (single character N S E or W) - degrees (integer) -
115
     * arc-minutes (real, any precision). Different symbol sets are in use as field separators, for example º '.
116
     * Convert to degrees using algorithm.
117
     */
118
    public const EPSG_HEMISPHERE_DEGREE_MINUTE = 'urn:ogc:def:uom:EPSG::9119';
119
120
    /**
121
     * hemisphere degree minute second
122
     * Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (integer) -
123
     * arc-minutes (integer) - arc-seconds (real). Different symbol sets are in use as field separators for example º
124
     * ' ". Convert to deg using algorithm.
125
     */
126
    public const EPSG_HEMISPHERE_DEGREE_MINUTE_SECOND = 'urn:ogc:def:uom:EPSG::9120';
127
128
    /**
129
     * microradian
130
     * rad * 10E-6.
131
     */
132
    public const EPSG_MICRORADIAN = 'urn:ogc:def:uom:EPSG::9109';
133
134
    /**
135
     * mil_6400
136
     * Angle subtended by 1/6400 part of a circle.  Approximates to 1/1000th radian.  Note that other approximations
137
     * (notably 1/6300 circle and 1/6000 circle) also exist.
138
     */
139
    public const EPSG_MIL_6400 = 'urn:ogc:def:uom:EPSG::9114';
140
141
    /**
142
     * milliarc-second
143
     * = ((pi/180) / 3600 / 1000) radians.
144
     */
145
    public const EPSG_MILLIARC_SECOND = 'urn:ogc:def:uom:EPSG::1031';
146
147
    /**
148
     * radian
149
     * SI coherent derived unit (standard unit) for plane angle.
150
     */
151
    public const EPSG_RADIAN = 'urn:ogc:def:uom:EPSG::9101';
152
153
    /**
154
     * sexagesimal DM
155
     * Pseudo unit. Format: signed degrees - period - integer minutes (2 digits) - fraction of minutes (any precision).
156
     * Must include leading zero in minutes and exclude decimal point for minutes. Convert to degree using algorithm.
157
     */
158
    public const EPSG_SEXAGESIMAL_DM = 'urn:ogc:def:uom:EPSG::9111';
159
160
    /**
161
     * sexagesimal DMS
162
     * Pseudo unit. Format: signed degrees - period - minutes (2 digits) - integer seconds (2 digits) - fraction of
163
     * seconds (any precision). Must include leading zero in minutes and seconds and exclude decimal point for seconds.
164
     * Convert to deg using algorithm.
165
     */
166
    public const EPSG_SEXAGESIMAL_DMS = 'urn:ogc:def:uom:EPSG::9110';
167
168
    /**
169
     * sexagesimal DMS.s
170
     * Pseudo unit. Format: signed degrees - minutes (2 digits) - integer seconds (2 digits) - period - fraction of
171
     * seconds (any precision). Must include leading zero in minutes and seconds and include decimal point for seconds.
172
     * Convert to deg using algorithm.
173
     */
174
    public const EPSG_SEXAGESIMAL_DMS_S = 'urn:ogc:def:uom:EPSG::9121';
175
176
    protected static array $sridData = [
177
        'urn:ogc:def:uom:EPSG::1031' => [
178
            'name' => 'milliarc-second',
179
        ],
180
        'urn:ogc:def:uom:EPSG::9101' => [
181
            'name' => 'radian',
182
        ],
183
        'urn:ogc:def:uom:EPSG::9102' => [
184
            'name' => 'degree',
185
        ],
186
        'urn:ogc:def:uom:EPSG::9103' => [
187
            'name' => 'arc-minute',
188
        ],
189
        'urn:ogc:def:uom:EPSG::9104' => [
190
            'name' => 'arc-second',
191
        ],
192
        'urn:ogc:def:uom:EPSG::9105' => [
193
            'name' => 'grad',
194
        ],
195
        'urn:ogc:def:uom:EPSG::9107' => [
196
            'name' => 'degree minute second',
197
        ],
198
        'urn:ogc:def:uom:EPSG::9108' => [
199
            'name' => 'degree minute second hemisphere',
200
        ],
201
        'urn:ogc:def:uom:EPSG::9109' => [
202
            'name' => 'microradian',
203
        ],
204
        'urn:ogc:def:uom:EPSG::9110' => [
205
            'name' => 'sexagesimal DMS',
206
        ],
207
        'urn:ogc:def:uom:EPSG::9111' => [
208
            'name' => 'sexagesimal DM',
209
        ],
210
        'urn:ogc:def:uom:EPSG::9112' => [
211
            'name' => 'centesimal minute',
212
        ],
213
        'urn:ogc:def:uom:EPSG::9113' => [
214
            'name' => 'centesimal second',
215
        ],
216
        'urn:ogc:def:uom:EPSG::9114' => [
217
            'name' => 'mil_6400',
218
        ],
219
        'urn:ogc:def:uom:EPSG::9115' => [
220
            'name' => 'degree minute',
221
        ],
222
        'urn:ogc:def:uom:EPSG::9116' => [
223
            'name' => 'degree hemisphere',
224
        ],
225
        'urn:ogc:def:uom:EPSG::9117' => [
226
            'name' => 'hemisphere degree',
227
        ],
228
        'urn:ogc:def:uom:EPSG::9118' => [
229
            'name' => 'degree minute hemisphere',
230
        ],
231
        'urn:ogc:def:uom:EPSG::9119' => [
232
            'name' => 'hemisphere degree minute',
233
        ],
234
        'urn:ogc:def:uom:EPSG::9120' => [
235
            'name' => 'hemisphere degree minute second',
236
        ],
237
        'urn:ogc:def:uom:EPSG::9121' => [
238
            'name' => 'sexagesimal DMS.s',
239
        ],
240
        'urn:ogc:def:uom:EPSG::9122' => [
241
            'name' => 'degree (supplier to define representation)',
242
        ],
243
    ];
244
245
    abstract public function asRadians(): Radian;
246
247
    public function asDegrees(): Degree
248
    {
249
        return new Degree($this->asRadians()->getValue() * 180 / M_PI);
250
    }
251
252 16
    public function add(self $unit): self
253
    {
254 16
        $resultAsRadians = new Radian($this->asRadians()->getValue() + $unit->asRadians()->getValue());
255 16
        $conversionRatio = (new static(1))->asRadians()->getValue();
0 ignored issues
show
Unused Code introduced by
The call to PHPCoord\UnitOfMeasure\Angle\Angle::__construct() has too many arguments starting with 1. ( Ignorable by Annotation )

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

255
        $conversionRatio = (/** @scrutinizer ignore-call */ new static(1))->asRadians()->getValue();

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
256
257 16
        return new static($resultAsRadians->getValue() / $conversionRatio);
258
    }
259
260 12
    public function subtract(self $unit): self
261
    {
262 12
        $resultAsRadians = new Radian($this->asRadians()->getValue() - $unit->asRadians()->getValue());
263 12
        $conversionRatio = (new static(1))->asRadians()->getValue();
0 ignored issues
show
Unused Code introduced by
The call to PHPCoord\UnitOfMeasure\Angle\Angle::__construct() has too many arguments starting with 1. ( Ignorable by Annotation )

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

263
        $conversionRatio = (/** @scrutinizer ignore-call */ new static(1))->asRadians()->getValue();

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
264
265 12
        return new static($resultAsRadians->getValue() / $conversionRatio);
266
    }
267
268 4
    public function multiply(float $multiplicand): self
269
    {
270 4
        return new static($this->getValue() * $multiplicand);
0 ignored issues
show
Unused Code introduced by
The call to PHPCoord\UnitOfMeasure\Angle\Angle::__construct() has too many arguments starting with $this->getValue() * $multiplicand. ( Ignorable by Annotation )

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

270
        return /** @scrutinizer ignore-call */ new static($this->getValue() * $multiplicand);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
271
    }
272
273 4
    public function divide(float $divisor): self
274
    {
275 4
        return new static($this->getValue() / $divisor);
0 ignored issues
show
Unused Code introduced by
The call to PHPCoord\UnitOfMeasure\Angle\Angle::__construct() has too many arguments starting with $this->getValue() / $divisor. ( Ignorable by Annotation )

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

275
        return /** @scrutinizer ignore-call */ new static($this->getValue() / $divisor);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
276
    }
277
278
    /**
279
     * @param float|string $measurement
280
     */
281 239
    public static function makeUnit($measurement, string $srid): self
282
    {
283
        switch ($srid) {
284 239
            case self::EPSG_RADIAN:
285 2
                return new Radian($measurement);
0 ignored issues
show
Bug introduced by
It seems like $measurement can also be of type string; however, parameter $angle of PHPCoord\UnitOfMeasure\Angle\Radian::__construct() does only seem to accept double, 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

285
                return new Radian(/** @scrutinizer ignore-type */ $measurement);
Loading history...
286 237
            case self::EPSG_MICRORADIAN:
287 2
                return new Radian($measurement / 1000000);
288 235
            case self::EPSG_DEGREE:
289 189
                return new Degree($measurement);
0 ignored issues
show
Bug introduced by
It seems like $measurement can also be of type string; however, parameter $angle of PHPCoord\UnitOfMeasure\Angle\Degree::__construct() does only seem to accept double, 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

289
                return new Degree(/** @scrutinizer ignore-type */ $measurement);
Loading history...
290 59
            case self::EPSG_ARC_MINUTE:
291 2
                return new ArcMinute($measurement);
0 ignored issues
show
Bug introduced by
It seems like $measurement can also be of type string; however, parameter $angle of PHPCoord\UnitOfMeasure\A...rcMinute::__construct() does only seem to accept double, 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

291
                return new ArcMinute(/** @scrutinizer ignore-type */ $measurement);
Loading history...
292 57
            case self::EPSG_ARC_SECOND:
293 5
                return new ArcSecond($measurement);
0 ignored issues
show
Bug introduced by
It seems like $measurement can also be of type string; however, parameter $angle of PHPCoord\UnitOfMeasure\A...rcSecond::__construct() does only seem to accept double, 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

293
                return new ArcSecond(/** @scrutinizer ignore-type */ $measurement);
Loading history...
294 52
            case self::EPSG_MILLIARC_SECOND:
295 4
                return new ArcSecond($measurement / 1000);
296 48
            case self::EPSG_GRAD:
297 4
                return new Grad($measurement);
0 ignored issues
show
Bug introduced by
It seems like $measurement can also be of type string; however, parameter $angle of PHPCoord\UnitOfMeasure\Angle\Grad::__construct() does only seem to accept double, 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

297
                return new Grad(/** @scrutinizer ignore-type */ $measurement);
Loading history...
298 44
            case self::EPSG_CENTESIMAL_MINUTE:
299 2
                return new Radian($measurement * M_PI / 20000);
300 42
            case self::EPSG_CENTESIMAL_SECOND:
301 2
                return new Radian($measurement * M_PI / 2000000);
302 40
            case self::EPSG_MIL_6400:
303 2
                return new Radian($measurement * M_PI / 3200);
304 38
            case self::EPSG_DEGREE_MINUTE_SECOND:
305 2
                return Degree::fromDegreeMinuteSecond((string) $measurement);
306 36
            case self::EPSG_DEGREE_MINUTE_SECOND_HEMISPHERE:
307 2
                return Degree::fromDegreeMinuteSecondHemisphere((string) $measurement);
308 34
            case self::EPSG_HEMISPHERE_DEGREE_MINUTE_SECOND:
309 2
                return Degree::fromHemisphereDegreeMinuteSecond((string) $measurement);
310 32
            case self::EPSG_DEGREE_MINUTE:
311 2
                return Degree::fromDegreeMinute((string) $measurement);
312 30
            case self::EPSG_DEGREE_MINUTE_HEMISPHERE:
313 2
                return Degree::fromDegreeMinuteHemisphere((string) $measurement);
314 28
            case self::EPSG_HEMISPHERE_DEGREE_MINUTE:
315 2
                return Degree::fromHemisphereDegreeMinute((string) $measurement);
316 26
            case self::EPSG_DEGREE_HEMISPHERE:
317 2
                return Degree::fromDegreeHemisphere((string) $measurement);
318 24
            case self::EPSG_HEMISPHERE_DEGREE:
319 2
                return Degree::fromHemisphereDegree((string) $measurement);
320 22
            case self::EPSG_SEXAGESIMAL_DMS_S:
321 2
                return Degree::fromSexagesimalDMSS((string) $measurement);
322 20
            case self::EPSG_SEXAGESIMAL_DMS:
323 17
                return Degree::fromSexagesimalDMS((string) $measurement);
324 3
            case self::EPSG_SEXAGESIMAL_DM:
325 2
                return Degree::fromSexagesimalDM((string) $measurement);
326
        }
327
328 1
        throw new UnknownUnitOfMeasureException($srid);
329
    }
330
331 87
    public static function getSupportedSRIDs(): array
332
    {
333 87
        return array_map(function ($sridData) {return $sridData['name']; }, static::$sridData);
334
    }
335
336 114
    public static function convert(self $angle, string $targetSRID): self
337
    {
338 114
        if ($targetSRID === self::EPSG_DEGREE_SUPPLIER_TO_DEFINE_REPRESENTATION) {
339 112
            $targetSRID = self::EPSG_DEGREE;
340
        }
341
342 114
        $conversionRatio = static::makeUnit(1, $targetSRID)->asRadians()->getValue();
343
344 114
        return self::makeUnit($angle->asRadians()->getValue() / $conversionRatio, $targetSRID);
345
    }
346
347 4
    public function __toString(): string
348
    {
349 4
        return (string) $this->getValue();
350
    }
351
}
352