Passed
Push — master ( 936f3f...6785f1 )
by Doug
09:29
created

Degree::convert()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 7
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 10
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 in_array;
12
use InvalidArgumentException;
13
use const M_PI;
14
use function preg_match;
15
use const PREG_UNMATCHED_AS_NULL;
16
use function str_pad;
17
use const STR_PAD_RIGHT;
18
use function str_replace;
19
use function strpos;
20
21
class Degree extends Angle
22
{
23
    private float $angle;
24
25 2355
    public function __construct(float $angle)
26
    {
27 2355
        $this->angle = $angle;
28 2355
    }
29
30 1617
    public function asRadians(): Radian
31
    {
32 1617
        return new Radian($this->angle * M_PI / 180);
33
    }
34
35 1212
    public function asDegrees(): self
36
    {
37 1212
        return $this;
38
    }
39
40 2157
    public function getValue(): float
41
    {
42 2157
        return $this->angle;
43
    }
44
45 9
    public function getUnitName(): string
46
    {
47 9
        return 'degree';
48
    }
49
50 108
    public static function fromDegreeMinuteSecond(string $angle): self
51
    {
52 108
        $regex = '/^(?P<negative>[−-])?(?P<degrees>\d+)[°º]?((?P<arcminutes>\d+)[′\'])?((?P<arcseconds>\d+\.?\d*)[″"])?$/u';
53
54 108
        return self::fromRegex($angle, $regex);
55
    }
56
57 108
    public static function fromDegreeMinuteSecondHemisphere(string $angle): self
58
    {
59 108
        $regex = '/^(?P<degrees>\d+)[°º]?((?P<arcminutes>\d+)[′\'])?((?P<arcseconds>\d+\.?\d*)[″"])?(?P<hemisphere>[NSEW])$/u';
60
61 108
        return self::fromRegex($angle, $regex);
62
    }
63
64 18
    public static function fromHemisphereDegreeMinuteSecond(string $angle): self
65
    {
66 18
        $regex = '/^(?P<hemisphere>[NSEW])(?P<degrees>\d+)[°º]?((?P<arcminutes>\d+)[′\'])?((?P<arcseconds>\d+\.?\d*)[″"])?$/u';
67
68 18
        return self::fromRegex($angle, $regex);
69
    }
70
71 99
    public static function fromDegreeMinute(string $angle): self
72
    {
73 99
        $regex = '/^(?P<negative>[−-])?(?P<degrees>\d+)[°º]?((?P<arcminutes>\d+\.?\d*)[′\'])?$/u';
74
75 99
        return self::fromRegex($angle, $regex);
76
    }
77
78 108
    public static function fromDegreeMinuteHemisphere(string $angle): self
79
    {
80 108
        $regex = '/^(?P<degrees>\d+)[°º]?((?P<arcminutes>\d+\.?\d*)[′\'])?(?P<hemisphere>[NSEW])$/u';
81
82 108
        return self::fromRegex($angle, $regex);
83
    }
84
85 18
    public static function fromHemisphereDegreeMinute(string $angle): self
86
    {
87 18
        $regex = '/^(?P<hemisphere>[NSEW])(?P<degrees>\d+)[°º]?((?P<arcminutes>\d+\.?\d*)[′\'])?$/u';
88
89 18
        return self::fromRegex($angle, $regex);
90
    }
91
92 72
    public static function fromDegreeHemisphere(string $angle): self
93
    {
94 72
        $regex = '/^(?P<degrees>\d+\.?\d*)[°º]?(?P<hemisphere>[NSEW])$/u';
95
96 72
        return self::fromRegex($angle, $regex);
97
    }
98
99 18
    public static function fromHemisphereDegree(string $angle): self
100
    {
101 18
        $regex = '/^(?P<hemisphere>[NSEW])(?P<degrees>\d+\.?\d*)[°º]?$/u';
102
103 18
        return self::fromRegex($angle, $regex);
104
    }
105
106 99
    public static function fromSexagesimalDMSS(string $angle): self
107
    {
108 99
        $regex = '/^(?P<negative>[−-])?(?P<degrees>\d+)(?P<arcminutes>\d{2})(?P<arcseconds>\d{2}\.\d*)$/u';
109
110 99
        return self::fromRegex($angle, $regex);
111
    }
112
113 81
    public static function fromSexagesimalDMS(string $angle): self
114
    {
115 81
        $decimalPosition = strpos($angle, '.');
116 81
        if ($decimalPosition) {
117 81
            $angle = str_pad($angle, $decimalPosition + 5, '0', STR_PAD_RIGHT);
118
        } else {
119
            $angle .= '.0000';
120
        }
121 81
        $regex = '/^(?P<negative>[−-])?(?P<degrees>\d+)\.(?P<arcminutes>\d{2})(?P<arcseconds>\d{2})(?P<fractionarcseconds>\d+)?$/u';
122
123 81
        return self::fromRegex($angle, $regex);
124
    }
125
126 27
    public static function fromSexagesimalDM(string $angle): self
127
    {
128 27
        $decimalPosition = strpos($angle, '.');
129 27
        if ($decimalPosition) {
130 27
            $angle = str_pad($angle, $decimalPosition + 5, '0', STR_PAD_RIGHT);
131
        } else {
132
            $angle .= '.0000';
133
        }
134 27
        $regex = '/^(?P<negative>[−-])?(?P<degrees>\d+)\.(?P<arcminutes>\d{2})(?P<fractionarcminutes>\d+)?$/u';
135
136 27
        return self::fromRegex($angle, $regex);
137
    }
138
139 756
    private static function fromRegex(string $angle, string $regex): self
140
    {
141 756
        $angle = str_replace(' ', '', $angle);
142 756
        $foundAngle = preg_match($regex, $angle, $angleParts, PREG_UNMATCHED_AS_NULL);
143
144 756
        if (!$foundAngle) {
145 72
            throw new InvalidArgumentException("Could not find angle in '{$angle}'");
146
        }
147
148 684
        $degrees = ($angleParts['degrees'] * 1);
149 684
        $degrees += (($angleParts['arcminutes'] ?? 0) / 60);
150 684
        $degrees += (($angleParts['fractionarcminutes'] ?? 0) / 60 / 100);
151 684
        $degrees += (($angleParts['arcseconds'] ?? 0) / 3600);
152 684
        $degrees += (($angleParts['fractionarcseconds'] ?? 0) / 3600 / 100);
153
154 684
        if ($angleParts['negative'] ?? '' || in_array($angleParts['hemisphere'] ?? [], ['S', 'W'], true)) {
155 180
            $degrees *= -1;
156
        }
157
158 684
        return new static($degrees);
159
    }
160
161 779
    public static function convert(Angle $angle, string $targetSRID): Angle
162
    {
163 779
        if ($targetSRID === self::EPSG_DEGREE) {
164
            return $angle;
165
        }
166
167 779
        return parent::convert($angle, $targetSRID);
168
    }
169
}
170