Passed
Push — master ( f00c65...31a7ea )
by Doug
61:30
created

Angle::makeUnit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 18
nc 1
nop 2
dl 0
loc 20
ccs 13
cts 13
cp 1
crap 1
rs 9.6666
c 0
b 0
f 0
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 const M_PI;
12
use PHPCoord\Exception\UnknownUnitOfMeasureException;
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 hemisphere
37
     * Degree representation. Format: degrees (real, any precision) - hemisphere abbreviation (single character N S E
38
     * or W). Convert to degrees using algorithm.
39
     */
40
    public const EPSG_DEGREE_HEMISPHERE = 'urn:ogc:def:uom:EPSG::9116';
41
42
    /**
43
     * degree minute
44
     * Degree representation. Format: signed degrees (integer)  - arc-minutes (real, any precision). Different symbol
45
     * sets are in use as field separators, for example º '. Convert to degrees using algorithm.
46
     */
47
    public const EPSG_DEGREE_MINUTE = 'urn:ogc:def:uom:EPSG::9115';
48
49
    /**
50
     * degree minute hemisphere
51
     * Degree representation. Format: degrees (integer) - arc-minutes (real, any precision) - hemisphere abbreviation
52
     * (single character N S E or W). Different symbol sets are in use as field separators, for example º '. Convert
53
     * to degrees using algorithm.
54
     */
55
    public const EPSG_DEGREE_MINUTE_HEMISPHERE = 'urn:ogc:def:uom:EPSG::9118';
56
57
    /**
58
     * degree minute second
59
     * Degree representation. Format: signed degrees (integer) - arc-minutes (integer) - arc-seconds (real, any
60
     * precision). Different symbol sets are in use as field separators, for example º ' ". Convert to degrees using
61
     * algorithm.
62
     */
63
    public const EPSG_DEGREE_MINUTE_SECOND = 'urn:ogc:def:uom:EPSG::9107';
64
65
    /**
66
     * degree minute second hemisphere
67
     * Degree representation. Format: degrees (integer) - arc-minutes (integer) - arc-seconds (real) - hemisphere
68
     * abbreviation (single character N S E or W). Different symbol sets are in use as field separators for example º
69
     * ' ". Convert to deg using algorithm.
70
     */
71
    public const EPSG_DEGREE_MINUTE_SECOND_HEMISPHERE = 'urn:ogc:def:uom:EPSG::9108';
72
73
    /**
74
     * grad
75
     * =pi/200 radians.
76
     */
77
    public const EPSG_GRAD = 'urn:ogc:def:uom:EPSG::9105';
78
79
    /**
80
     * hemisphere degree
81
     * Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (real, any
82
     * precision). Convert to degrees using algorithm.
83
     */
84
    public const EPSG_HEMISPHERE_DEGREE = 'urn:ogc:def:uom:EPSG::9117';
85
86
    /**
87
     * hemisphere degree minute
88
     * Degree representation. Format:  hemisphere abbreviation (single character N S E or W) - degrees (integer) -
89
     * arc-minutes (real, any precision). Different symbol sets are in use as field separators, for example º '.
90
     * Convert to degrees using algorithm.
91
     */
92
    public const EPSG_HEMISPHERE_DEGREE_MINUTE = 'urn:ogc:def:uom:EPSG::9119';
93
94
    /**
95
     * hemisphere degree minute second
96
     * Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (integer) -
97
     * arc-minutes (integer) - arc-seconds (real). Different symbol sets are in use as field separators for example º
98
     * ' ". Convert to deg using algorithm.
99
     */
100
    public const EPSG_HEMISPHERE_DEGREE_MINUTE_SECOND = 'urn:ogc:def:uom:EPSG::9120';
101
102
    /**
103
     * microradian
104
     * rad * 10E-6.
105
     */
106
    public const EPSG_MICRORADIAN = 'urn:ogc:def:uom:EPSG::9109';
107
108
    /**
109
     * milliarc-second
110
     * = ((pi/180) / 3600 / 1000) radians.
111
     */
112
    public const EPSG_MILLIARC_SECOND = 'urn:ogc:def:uom:EPSG::1031';
113
114
    /**
115
     * radian
116
     * SI coherent derived unit (standard unit) for plane angle.
117
     */
118
    public const EPSG_RADIAN = 'urn:ogc:def:uom:EPSG::9101';
119
120
    /**
121
     * sexagesimal DMS
122
     * Pseudo unit. Format: signed degrees - period - minutes (2 digits) - integer seconds (2 digits) - fraction of
123
     * seconds (any precision). Must include leading zero in minutes and seconds and exclude decimal point for seconds.
124
     * Convert to deg using algorithm.
125
     */
126
    public const EPSG_SEXAGESIMAL_DMS = 'urn:ogc:def:uom:EPSG::9110';
127
128
    protected static array $sridData = [
129
        'urn:ogc:def:uom:EPSG::1031' => [
130
            'name' => 'milliarc-second',
131
        ],
132
        'urn:ogc:def:uom:EPSG::9101' => [
133
            'name' => 'radian',
134
        ],
135
        'urn:ogc:def:uom:EPSG::9102' => [
136
            'name' => 'degree',
137
        ],
138
        'urn:ogc:def:uom:EPSG::9104' => [
139
            'name' => 'arc-second',
140
        ],
141
        'urn:ogc:def:uom:EPSG::9105' => [
142
            'name' => 'grad',
143
        ],
144
        'urn:ogc:def:uom:EPSG::9107' => [
145
            'name' => 'degree minute second',
146
        ],
147
        'urn:ogc:def:uom:EPSG::9108' => [
148
            'name' => 'degree minute second hemisphere',
149
        ],
150
        'urn:ogc:def:uom:EPSG::9109' => [
151
            'name' => 'microradian',
152
        ],
153
        'urn:ogc:def:uom:EPSG::9110' => [
154
            'name' => 'sexagesimal DMS',
155
        ],
156
        'urn:ogc:def:uom:EPSG::9113' => [
157
            'name' => 'centesimal second',
158
        ],
159
        'urn:ogc:def:uom:EPSG::9115' => [
160
            'name' => 'degree minute',
161
        ],
162
        'urn:ogc:def:uom:EPSG::9116' => [
163
            'name' => 'degree hemisphere',
164
        ],
165
        'urn:ogc:def:uom:EPSG::9117' => [
166
            'name' => 'hemisphere degree',
167
        ],
168
        'urn:ogc:def:uom:EPSG::9118' => [
169
            'name' => 'degree minute hemisphere',
170
        ],
171
        'urn:ogc:def:uom:EPSG::9119' => [
172
            'name' => 'hemisphere degree minute',
173
        ],
174
        'urn:ogc:def:uom:EPSG::9120' => [
175
            'name' => 'hemisphere degree minute second',
176
        ],
177
    ];
178
179
    private static array $supportedCache = [];
180
181
    abstract public function asRadians(): Radian;
182
183
    public function asDegrees(): Degree
184
    {
185
        return new Degree($this->asRadians()->getValue() * 180 / M_PI);
186
    }
187
188 1049
    public function add(self $unit): self
189
    {
190 1049
        $resultAsRadians = new Radian($this->asRadians()->getValue() + $unit->asRadians()->getValue());
191
        $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

191
        $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...
192
193 259
        return new static($resultAsRadians->getValue() / $conversionRatio);
194
    }
195 259
196 259
    public function subtract(self $unit): self
197
    {
198 259
        $resultAsRadians = new Radian($this->asRadians()->getValue() - $unit->asRadians()->getValue());
199
        $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 603
        return new static($resultAsRadians->getValue() / $conversionRatio);
202
    }
203 603
204 603
    public function multiply(float $multiplicand): self
205
    {
206 603
        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

206
        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...
207
    }
208
209 41
    public function divide(float $divisor): self
210
    {
211 41
        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

211
        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...
212
    }
213
214 36
    /**
215
     * @param float|string $measurement
216 36
     */
217
    public static function makeUnit($measurement, string $srid): self
218
    {
219
        return match ($srid) {
220
            self::EPSG_RADIAN => 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

220
            self::EPSG_RADIAN => new Radian(/** @scrutinizer ignore-type */ $measurement),
Loading history...
221
            self::EPSG_MICRORADIAN => new Radian($measurement / 1000000),
222 1368
            self::EPSG_DEGREE => 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

222
            self::EPSG_DEGREE => new Degree(/** @scrutinizer ignore-type */ $measurement),
Loading history...
223
            self::EPSG_ARC_SECOND => 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

223
            self::EPSG_ARC_SECOND => new ArcSecond(/** @scrutinizer ignore-type */ $measurement),
Loading history...
224
            self::EPSG_MILLIARC_SECOND => new ArcSecond($measurement / 1000),
225 1368
            self::EPSG_GRAD => 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

225
            self::EPSG_GRAD => new Grad(/** @scrutinizer ignore-type */ $measurement),
Loading history...
226 18
            self::EPSG_CENTESIMAL_SECOND => new Radian($measurement * M_PI / 2000000),
227 1350
            self::EPSG_DEGREE_MINUTE_SECOND => Degree::fromDegreeMinuteSecond((string) $measurement),
228 27
            self::EPSG_DEGREE_MINUTE_SECOND_HEMISPHERE => Degree::fromDegreeMinuteSecondHemisphere((string) $measurement),
229 1332
            self::EPSG_HEMISPHERE_DEGREE_MINUTE_SECOND => Degree::fromHemisphereDegreeMinuteSecond((string) $measurement),
230 1004
            self::EPSG_DEGREE_MINUTE => Degree::fromDegreeMinute((string) $measurement),
231 498
            self::EPSG_DEGREE_MINUTE_HEMISPHERE => Degree::fromDegreeMinuteHemisphere((string) $measurement),
232 210
            self::EPSG_HEMISPHERE_DEGREE_MINUTE => Degree::fromHemisphereDegreeMinute((string) $measurement),
233 315
            self::EPSG_DEGREE_HEMISPHERE => Degree::fromDegreeHemisphere((string) $measurement),
234 54
            self::EPSG_HEMISPHERE_DEGREE => Degree::fromHemisphereDegree((string) $measurement),
235 261
            self::EPSG_SEXAGESIMAL_DMS => Degree::fromSexagesimalDMS((string) $measurement),
236 36
            default => throw new UnknownUnitOfMeasureException($srid),
237 225
        };
238 18
    }
239 207
240 18
    public static function getSupportedSRIDs(): array
241 189
    {
242 18
        if (!self::$supportedCache) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::supportedCache of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
243 171
            foreach (static::$sridData as $srid => $data) {
244 18
                self::$supportedCache[$srid] = $data['name'];
245 153
            }
246 18
        }
247 135
248 18
        return self::$supportedCache;
249 117
    }
250 18
251 99
    public static function convert(self $angle, string $targetSRID): self
252 18
    {
253 81
        $conversionRatio = static::makeUnit(1, $targetSRID)->asRadians()->getValue();
254 18
255 63
        return self::makeUnit($angle->asRadians()->getValue() / $conversionRatio, $targetSRID);
256 54
    }
257
258
    public function __toString(): string
259 9
    {
260
        return (string) $this->getValue();
261
    }
262
}
263