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

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

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

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

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

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

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

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

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