Passed
Push — 4.x ( 3d97aa...7116cb )
by Doug
14:10 queued 08:22
created

Degree::fromSexagesimalDMS()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

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