Passed
Push — master ( 1c87d2...a64886 )
by Doug
04:35
created

Angle::makeUnit()   C

Complexity

Conditions 17
Paths 17

Size

Total Lines 38
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 17

Importance

Changes 0
Metric Value
cc 17
eloc 34
nc 17
nop 2
dl 0
loc 38
ccs 34
cts 34
cp 1
crap 17
rs 5.2166
c 0
b 0
f 0

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 function array_map;
12
use PHPCoord\Exception\UnknownUnitOfMeasureException;
13
use PHPCoord\UnitOfMeasure\Time\Second;
0 ignored issues
show
Bug introduced by
The type PHPCoord\UnitOfMeasure\Time\Second was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use PHPCoord\UnitOfMeasure\UnitOfMeasure;
15
16
abstract class Angle implements UnitOfMeasure
17
{
18
    /**
19
     * arc-second
20
     * 1/60th arc-minute = ((pi/180) / 3600) radians.
21
     */
22
    public const EPSG_ARC_SECOND = 'urn:ogc:def:uom:EPSG::9104';
23
24
    /**
25
     * centesimal second
26
     * 1/100 of a centesimal minute or 1/10,000th of a grad and gon = ((pi/200) / 10000) radians.
27
     */
28
    public const EPSG_CENTESIMAL_SECOND = 'urn:ogc:def:uom:EPSG::9113';
29
30
    /**
31
     * degree
32
     * = pi/180 radians.
33
     */
34
    public const EPSG_DEGREE = 'urn:ogc:def:uom:EPSG::9102';
35
36
    /**
37
     * degree (supplier to define representation)
38
     * = pi/180 radians. The degree representation (e.g. decimal, DMSH, etc.) must be clarified by suppliers of data
39
     * associated with this code.
40
     */
41
    public const EPSG_DEGREE_SUPPLIER_TO_DEFINE_REPRESENTATION = 'urn:ogc:def:uom:EPSG::9122';
42
43
    /**
44
     * degree hemisphere
45
     * Degree representation. Format: degrees (real, any precision) - hemisphere abbreviation (single character N S E
46
     * or W). Convert to degrees using algorithm.
47
     */
48
    public const EPSG_DEGREE_HEMISPHERE = 'urn:ogc:def:uom:EPSG::9116';
49
50
    /**
51
     * degree minute
52
     * Degree representation. Format: signed degrees (integer)  - arc-minutes (real, any precision). Different symbol
53
     * sets are in use as field separators, for example º '. Convert to degrees using algorithm.
54
     */
55
    public const EPSG_DEGREE_MINUTE = 'urn:ogc:def:uom:EPSG::9115';
56
57
    /**
58
     * degree minute hemisphere
59
     * Degree representation. Format: degrees (integer) - arc-minutes (real, any precision) - hemisphere abbreviation
60
     * (single character N S E or W). Different symbol sets are in use as field separators, for example º '. Convert
61
     * to degrees using algorithm.
62
     */
63
    public const EPSG_DEGREE_MINUTE_HEMISPHERE = 'urn:ogc:def:uom:EPSG::9118';
64
65
    /**
66
     * degree minute second
67
     * Degree representation. Format: signed degrees (integer) - arc-minutes (integer) - arc-seconds (real, any
68
     * precision). Different symbol sets are in use as field separators, for example º ' ". Convert to degrees using
69
     * algorithm.
70
     */
71
    public const EPSG_DEGREE_MINUTE_SECOND = 'urn:ogc:def:uom:EPSG::9107';
72
73
    /**
74
     * degree minute second hemisphere
75
     * Degree representation. Format: degrees (integer) - arc-minutes (integer) - arc-seconds (real) - hemisphere
76
     * abbreviation (single character N S E or W). Different symbol sets are in use as field separators for example º
77
     * ' ". Convert to deg using algorithm.
78
     */
79
    public const EPSG_DEGREE_MINUTE_SECOND_HEMISPHERE = 'urn:ogc:def:uom:EPSG::9108';
80
81
    /**
82
     * grad
83
     * =pi/200 radians.
84
     */
85
    public const EPSG_GRAD = 'urn:ogc:def:uom:EPSG::9105';
86
87
    /**
88
     * hemisphere degree
89
     * Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (real, any
90
     * precision). Convert to degrees using algorithm.
91
     */
92
    public const EPSG_HEMISPHERE_DEGREE = 'urn:ogc:def:uom:EPSG::9117';
93
94
    /**
95
     * hemisphere degree minute
96
     * Degree representation. Format:  hemisphere abbreviation (single character N S E or W) - degrees (integer) -
97
     * arc-minutes (real, any precision). Different symbol sets are in use as field separators, for example º '.
98
     * Convert to degrees using algorithm.
99
     */
100
    public const EPSG_HEMISPHERE_DEGREE_MINUTE = 'urn:ogc:def:uom:EPSG::9119';
101
102
    /**
103
     * hemisphere degree minute second
104
     * Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (integer) -
105
     * arc-minutes (integer) - arc-seconds (real). Different symbol sets are in use as field separators for example º
106
     * ' ". Convert to deg using algorithm.
107
     */
108
    public const EPSG_HEMISPHERE_DEGREE_MINUTE_SECOND = 'urn:ogc:def:uom:EPSG::9120';
109
110
    /**
111
     * microradian
112
     * rad * 10E-6.
113
     */
114
    public const EPSG_MICRORADIAN = 'urn:ogc:def:uom:EPSG::9109';
115
116
    /**
117
     * milliarc-second
118
     * = ((pi/180) / 3600 / 1000) radians.
119
     */
120
    public const EPSG_MILLIARC_SECOND = 'urn:ogc:def:uom:EPSG::1031';
121
122
    /**
123
     * radian
124
     * SI coherent derived unit (standard unit) for plane angle.
125
     */
126
    public const EPSG_RADIAN = 'urn:ogc:def:uom:EPSG::9101';
127
128
    /**
129
     * sexagesimal DMS
130
     * Pseudo unit. Format: signed degrees - period - minutes (2 digits) - integer seconds (2 digits) - fraction of
131
     * seconds (any precision). Must include leading zero in minutes and seconds and exclude decimal point for seconds.
132
     * Convert to deg using algorithm.
133
     */
134
    public const EPSG_SEXAGESIMAL_DMS = 'urn:ogc:def:uom:EPSG::9110';
135
136
    protected static array $sridData = [
137
        'urn:ogc:def:uom:EPSG::1031' => [
138
            'name' => 'milliarc-second',
139
        ],
140
        'urn:ogc:def:uom:EPSG::9101' => [
141
            'name' => 'radian',
142
        ],
143
        'urn:ogc:def:uom:EPSG::9102' => [
144
            'name' => 'degree',
145
        ],
146
        'urn:ogc:def:uom:EPSG::9104' => [
147
            'name' => 'arc-second',
148
        ],
149
        'urn:ogc:def:uom:EPSG::9105' => [
150
            'name' => 'grad',
151
        ],
152
        'urn:ogc:def:uom:EPSG::9107' => [
153
            'name' => 'degree minute second',
154
        ],
155
        'urn:ogc:def:uom:EPSG::9108' => [
156
            'name' => 'degree minute second hemisphere',
157
        ],
158
        'urn:ogc:def:uom:EPSG::9109' => [
159
            'name' => 'microradian',
160
        ],
161
        'urn:ogc:def:uom:EPSG::9110' => [
162
            'name' => 'sexagesimal DMS',
163
        ],
164
        'urn:ogc:def:uom:EPSG::9113' => [
165
            'name' => 'centesimal second',
166
        ],
167
        'urn:ogc:def:uom:EPSG::9115' => [
168
            'name' => 'degree minute',
169
        ],
170
        'urn:ogc:def:uom:EPSG::9116' => [
171
            'name' => 'degree hemisphere',
172
        ],
173
        'urn:ogc:def:uom:EPSG::9117' => [
174
            'name' => 'hemisphere degree',
175
        ],
176
        'urn:ogc:def:uom:EPSG::9118' => [
177
            'name' => 'degree minute hemisphere',
178
        ],
179
        'urn:ogc:def:uom:EPSG::9119' => [
180
            'name' => 'hemisphere degree minute',
181
        ],
182
        'urn:ogc:def:uom:EPSG::9120' => [
183
            'name' => 'hemisphere degree minute second',
184
        ],
185
        'urn:ogc:def:uom:EPSG::9122' => [
186
            'name' => 'degree (supplier to define representation)',
187
        ],
188
    ];
189
190
    abstract public function asRadians(): Radian;
191
192 13
    public function asDegrees(): Degree
193
    {
194 13
        return new Degree($this->asRadians()->getValue() * 180 / M_PI);
195
    }
196
197 17
    public function add(self $unit): self
198
    {
199 17
        $resultAsRadians = new Radian($this->asRadians()->getValue() + $unit->asRadians()->getValue());
200 17
        $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

200
        $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...
201
202 17
        return new static($resultAsRadians->getValue() / $conversionRatio);
203
    }
204
205 9
    public function subtract(self $unit): self
206
    {
207 9
        $resultAsRadians = new Radian($this->asRadians()->getValue() - $unit->asRadians()->getValue());
208 9
        $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

208
        $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...
209
210 9
        return new static($resultAsRadians->getValue() / $conversionRatio);
211
    }
212
213 4
    public function multiply(float $multiplicand): self
214
    {
215 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

215
        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...
216
    }
217
218 4
    public function divide(float $divisor): self
219
    {
220 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

220
        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...
221
    }
222
223
    /**
224
     * @param float|string $measurement
225
     */
226 247
    public static function makeUnit($measurement, string $srid): self
227
    {
228
        switch ($srid) {
229 247
            case self::EPSG_RADIAN:
230 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

230
                return new Radian(/** @scrutinizer ignore-type */ $measurement);
Loading history...
231 245
            case self::EPSG_MICRORADIAN:
232 2
                return new Radian($measurement / 1000000);
233 243
            case self::EPSG_DEGREE:
234 207
                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

234
                return new Degree(/** @scrutinizer ignore-type */ $measurement);
Loading history...
235 53
            case self::EPSG_ARC_SECOND:
236 7
                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

236
                return new ArcSecond(/** @scrutinizer ignore-type */ $measurement);
Loading history...
237 46
            case self::EPSG_MILLIARC_SECOND:
238 5
                return new ArcSecond($measurement / 1000);
239 41
            case self::EPSG_GRAD:
240 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

240
                return new Grad(/** @scrutinizer ignore-type */ $measurement);
Loading history...
241 37
            case self::EPSG_CENTESIMAL_SECOND:
242 2
                return new Radian($measurement * M_PI / 2000000);
243 35
            case self::EPSG_DEGREE_MINUTE_SECOND:
244 2
                return Degree::fromDegreeMinuteSecond((string) $measurement);
245 33
            case self::EPSG_DEGREE_MINUTE_SECOND_HEMISPHERE:
246 2
                return Degree::fromDegreeMinuteSecondHemisphere((string) $measurement);
247 31
            case self::EPSG_HEMISPHERE_DEGREE_MINUTE_SECOND:
248 2
                return Degree::fromHemisphereDegreeMinuteSecond((string) $measurement);
249 29
            case self::EPSG_DEGREE_MINUTE:
250 2
                return Degree::fromDegreeMinute((string) $measurement);
251 27
            case self::EPSG_DEGREE_MINUTE_HEMISPHERE:
252 2
                return Degree::fromDegreeMinuteHemisphere((string) $measurement);
253 25
            case self::EPSG_HEMISPHERE_DEGREE_MINUTE:
254 2
                return Degree::fromHemisphereDegreeMinute((string) $measurement);
255 23
            case self::EPSG_DEGREE_HEMISPHERE:
256 2
                return Degree::fromDegreeHemisphere((string) $measurement);
257 21
            case self::EPSG_HEMISPHERE_DEGREE:
258 2
                return Degree::fromHemisphereDegree((string) $measurement);
259 19
            case self::EPSG_SEXAGESIMAL_DMS:
260 18
                return Degree::fromSexagesimalDMS((string) $measurement);
261
        }
262
263 1
        throw new UnknownUnitOfMeasureException($srid);
264
    }
265
266 62
    public static function getSupportedSRIDs(): array
267
    {
268 62
        return array_map(function ($sridData) {return $sridData['name']; }, static::$sridData);
269
    }
270
271 126
    public static function convert(self $angle, string $targetSRID): self
272
    {
273 126
        if ($targetSRID === self::EPSG_DEGREE_SUPPLIER_TO_DEFINE_REPRESENTATION) {
274 124
            $targetSRID = self::EPSG_DEGREE;
275
        }
276
277 126
        $conversionRatio = static::makeUnit(1, $targetSRID)->asRadians()->getValue();
278
279 126
        return self::makeUnit($angle->asRadians()->getValue() / $conversionRatio, $targetSRID);
280
    }
281
282 4
    public function __toString(): string
283
    {
284 4
        return (string) $this->getValue();
285
    }
286
}
287