Passed
Push — master ( 0baa7a...f13449 )
by Doug
50:51
created

Degree::fromSexagesimalDM()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0116

Importance

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