Passed
Push — master ( 8bd5c3...1e8670 )
by Doug
62:22
created

Length::getSupportedSRIDsWithHelp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
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\Length;
10
11
use PHPCoord\Exception\UnknownUnitOfMeasureException;
12
use PHPCoord\UnitOfMeasure\UnitOfMeasure;
13
14
use function array_map;
15
16
abstract class Length implements UnitOfMeasure
17
{
18
    /**
19
     * British chain (Benoit 1895 B)
20
     * Uses Benoit's 1895 British yard-metre ratio as given by Bomford as 39.370113 inches per metre.  Used in West
21
     * Malaysian mapping.
22
     */
23
    public const EPSG_BRITISH_CHAIN_BENOIT_1895_B = 'urn:ogc:def:uom:EPSG::9062';
24
25
    /**
26
     * British chain (Sears 1922 truncated)
27
     * Uses Sear's 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures; this truncated
28
     * ratio (0.914398, UoM code 9099) then converted to other imperial units. 1 chSe(T) = 22 ydSe(T). Used in
29
     * metrication of Malaya RSO grid.
30
     */
31
    public const EPSG_BRITISH_CHAIN_SEARS_1922_TRUNCATED = 'urn:ogc:def:uom:EPSG::9301';
32
33
    /**
34
     * British chain (Sears 1922)
35
     * Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East
36
     * Malaysian and older New Zealand mapping.
37
     */
38
    public const EPSG_BRITISH_CHAIN_SEARS_1922 = 'urn:ogc:def:uom:EPSG::9042';
39
40
    /**
41
     * British foot (1936)
42
     * For the 1936 retriangulation OSGB defines the relationship of 10 feet of 1796 to the International metre through
43
     * the logarithmic relationship (10^0.48401603 exactly). 1 ft = 0.3048007491…m. Also used for metric conversions
44
     * in Ireland.
45
     */
46
    public const EPSG_BRITISH_FOOT_1936 = 'urn:ogc:def:uom:EPSG::9095';
47
48
    /**
49
     * British foot (Sears 1922)
50
     * Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East
51
     * Malaysian and older New Zealand mapping.
52
     */
53
    public const EPSG_BRITISH_FOOT_SEARS_1922 = 'urn:ogc:def:uom:EPSG::9041';
54
55
    /**
56
     * British yard (Sears 1922)
57
     * Uses Sear's 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East
58
     * Malaysian and older New Zealand mapping.
59
     */
60
    public const EPSG_BRITISH_YARD_SEARS_1922 = 'urn:ogc:def:uom:EPSG::9040';
61
62
    /**
63
     * Clarke's foot
64
     * Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international
65
     * metre.   Used in older Australian, southern African & British West Indian mapping.
66
     */
67
    public const EPSG_CLARKES_FOOT = 'urn:ogc:def:uom:EPSG::9005';
68
69
    /**
70
     * Clarke's link
71
     * =1/100 Clarke's chain. Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies
72
     * to the international metre.   Used in older Australian, southern African & British West Indian mapping.
73
     */
74
    public const EPSG_CLARKES_LINK = 'urn:ogc:def:uom:EPSG::9039';
75
76
    /**
77
     * Clarke's yard
78
     * =3 Clarke's feet.  Assumes Clarke's 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to
79
     * the international metre.   Used in older Australian, southern African & British West Indian mapping.
80
     */
81
    public const EPSG_CLARKES_YARD = 'urn:ogc:def:uom:EPSG::9037';
82
83
    /**
84
     * German legal metre
85
     * Used in Namibia.
86
     */
87
    public const EPSG_GERMAN_LEGAL_METRE = 'urn:ogc:def:uom:EPSG::9031';
88
89
    /**
90
     * Gold Coast foot
91
     * Used in Ghana and some adjacent parts of British west Africa prior to metrication, except for the metrication of
92
     * projection defining parameters when British foot (Sears 1922) used.
93
     */
94
    public const EPSG_GOLD_COAST_FOOT = 'urn:ogc:def:uom:EPSG::9094';
95
96
    /**
97
     * Indian foot
98
     * Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (= 3 British feet) taken to be
99
     * J.S.Clark's 1865 value of 0.9144025 metres.
100
     */
101
    public const EPSG_INDIAN_FOOT = 'urn:ogc:def:uom:EPSG::9080';
102
103
    /**
104
     * Indian yard
105
     * Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (= 3 British feet) taken to be
106
     * J.S.Clark's 1865 value of 0.9144025 metres.
107
     */
108
    public const EPSG_INDIAN_YARD = 'urn:ogc:def:uom:EPSG::9084';
109
110
    /**
111
     * US survey foot
112
     * Used in USA.
113
     */
114
    public const EPSG_US_SURVEY_FOOT = 'urn:ogc:def:uom:EPSG::9003';
115
116
    /**
117
     * Centimetre.
118
     */
119
    public const EPSG_CENTIMETRE = 'urn:ogc:def:uom:EPSG::1033';
120
121
    /**
122
     * Foot.
123
     */
124
    public const EPSG_FOOT = 'urn:ogc:def:uom:EPSG::9002';
125
126
    /**
127
     * Kilometre.
128
     */
129
    public const EPSG_KILOMETRE = 'urn:ogc:def:uom:EPSG::9036';
130
131
    /**
132
     * Link
133
     * =1/100 international chain.
134
     */
135
    public const EPSG_LINK = 'urn:ogc:def:uom:EPSG::9098';
136
137
    /**
138
     * Metre
139
     * SI base unit for length.
140
     */
141
    public const EPSG_METRE = 'urn:ogc:def:uom:EPSG::9001';
142
143
    /**
144
     * Millimetre.
145
     */
146
    public const EPSG_MILLIMETRE = 'urn:ogc:def:uom:EPSG::1025';
147
148
    /**
149
     * @var array<string, array{name: string, fqcn?: class-string<self>, help: string}>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, array{name...g<self>, help: string}> at position 12 could not be parsed: Unknown type name 'class-string' at position 12 in array<string, array{name: string, fqcn?: class-string<self>, help: string}>.
Loading history...
150
     */
151
    protected static array $sridData = [
152
        'urn:ogc:def:uom:EPSG::1025' => [
153
            'name' => 'millimetre',
154
            'help' => '',
155
        ],
156
        'urn:ogc:def:uom:EPSG::1033' => [
157
            'name' => 'centimetre',
158
            'help' => '',
159
        ],
160
        'urn:ogc:def:uom:EPSG::9001' => [
161
            'name' => 'metre',
162
            'help' => 'SI base unit for length.',
163
        ],
164
        'urn:ogc:def:uom:EPSG::9002' => [
165
            'name' => 'foot',
166
            'help' => '',
167
        ],
168
        'urn:ogc:def:uom:EPSG::9003' => [
169
            'name' => 'US survey foot',
170
            'help' => 'Used in USA.',
171
        ],
172
        'urn:ogc:def:uom:EPSG::9005' => [
173
            'name' => 'Clarke\'s foot',
174
            'help' => 'Assumes Clarke\'s 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.',
175
        ],
176
        'urn:ogc:def:uom:EPSG::9031' => [
177
            'name' => 'German legal metre',
178
            'help' => 'Used in Namibia.',
179
        ],
180
        'urn:ogc:def:uom:EPSG::9036' => [
181
            'name' => 'kilometre',
182
            'help' => '',
183
        ],
184
        'urn:ogc:def:uom:EPSG::9037' => [
185
            'name' => 'Clarke\'s yard',
186
            'help' => '=3 Clarke\'s feet.  Assumes Clarke\'s 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.',
187
        ],
188
        'urn:ogc:def:uom:EPSG::9039' => [
189
            'name' => 'Clarke\'s link',
190
            'help' => '=1/100 Clarke\'s chain. Assumes Clarke\'s 1865 ratio of 1 British foot = 0.3047972654 French legal metres applies to the international metre.   Used in older Australian, southern African & British West Indian mapping.',
191
        ],
192
        'urn:ogc:def:uom:EPSG::9040' => [
193
            'name' => 'British yard (Sears 1922)',
194
            'help' => 'Uses Sear\'s 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.',
195
        ],
196
        'urn:ogc:def:uom:EPSG::9041' => [
197
            'name' => 'British foot (Sears 1922)',
198
            'help' => 'Uses Sear\'s 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.',
199
        ],
200
        'urn:ogc:def:uom:EPSG::9042' => [
201
            'name' => 'British chain (Sears 1922)',
202
            'help' => 'Uses Sear\'s 1922 British yard-metre ratio as given by Bomford as 39.370147 inches per metre.  Used in East Malaysian and older New Zealand mapping.',
203
        ],
204
        'urn:ogc:def:uom:EPSG::9062' => [
205
            'name' => 'British chain (Benoit 1895 B)',
206
            'help' => 'Uses Benoit\'s 1895 British yard-metre ratio as given by Bomford as 39.370113 inches per metre.  Used in West Malaysian mapping.',
207
        ],
208
        'urn:ogc:def:uom:EPSG::9080' => [
209
            'name' => 'Indian foot',
210
            'help' => 'Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (= 3 British feet) taken to be J.S.Clark\'s 1865 value of 0.9144025 metres.',
211
        ],
212
        'urn:ogc:def:uom:EPSG::9084' => [
213
            'name' => 'Indian yard',
214
            'help' => 'Indian Foot = 0.99999566 British feet (A.R.Clarke 1865).  British yard (= 3 British feet) taken to be J.S.Clark\'s 1865 value of 0.9144025 metres.',
215
        ],
216
        'urn:ogc:def:uom:EPSG::9094' => [
217 351
            'name' => 'Gold Coast foot',
218
            'help' => 'Used in Ghana and some adjacent parts of British west Africa prior to metrication, except for the metrication of projection defining parameters when British foot (Sears 1922) used.',
219 351
        ],
220 351
        'urn:ogc:def:uom:EPSG::9095' => [
221
            'name' => 'British foot (1936)',
222
            'help' => 'For the 1936 retriangulation OSGB defines the relationship of 10 feet of 1796 to the International metre through the logarithmic relationship (10^0.48401603 exactly). 1 ft = 0.3048007491…m. Also used for metric conversions in Ireland.',
223
        ],
224
        'urn:ogc:def:uom:EPSG::9098' => [
225
            'name' => 'link',
226
            'help' => '=1/100 international chain.',
227
        ],
228 233
        'urn:ogc:def:uom:EPSG::9301' => [
229
            'name' => 'British chain (Sears 1922 truncated)',
230 233
            'help' => 'Uses Sear\'s 1922 British yard-metre ratio (UoM code 9040) truncated to 6 significant figures; this truncated ratio (0.914398, UoM code 9099) then converted to other imperial units. 1 chSe(T) = 22 ydSe(T). Used in metrication of Malaya RSO grid.',
231 233
        ],
232
    ];
233
234
    abstract public function __construct(float $length);
235
236
    abstract public function asMetres(): Metre;
237
238
    public function add(self $unit): self
239 5815
    {
240
        if ($this::class === $unit::class) {
241 5815
            return new static($this->getValue() + $unit->getValue());
242
        }
243
        $resultAsMetres = new Metre($this->asMetres()->getValue() + $unit->asMetres()->getValue());
244 244
        $conversionRatio = (new static(1))->asMetres()->getValue();
245
246 244
        return new static($resultAsMetres->getValue() / $conversionRatio);
247
    }
248
249 2222
    public function subtract(self $unit): self
250
    {
251 2222
        if ($this::class === $unit::class) {
252 126
            return new static($this->getValue() - $unit->getValue());
253
        }
254
        $resultAsMetres = new Metre($this->asMetres()->getValue() - $unit->asMetres()->getValue());
255 2222
        $conversionRatio = (new static(1))->asMetres()->getValue();
256 2222
257 2222
        return new static($resultAsMetres->getValue() / $conversionRatio);
258 2222
    }
259 2222
260 2222
    public function multiply(float $multiplicand): self
261 2222
    {
262 2222
        return new static($this->getValue() * $multiplicand);
263 2222
    }
264 2222
265 2222
    public function divide(float $divisor): self
266 2222
    {
267 2222
        return new static($this->getValue() / $divisor);
268 2222
    }
269 2222
270 2222
    public static function makeUnit(float $measurement, string $srid): self
271 2222
    {
272 2222
        if (isset(self::$sridData[$srid]['fqcn'])) {
273 2222
            return new self::$sridData[$srid]['fqcn']($measurement);
274 2222
        }
275 2222
276 2222
        return match ($srid) {
277 2222
            self::EPSG_METRE => new Metre($measurement),
278
            self::EPSG_KILOMETRE => new Kilometre($measurement),
279
            self::EPSG_CENTIMETRE => new Centimetre($measurement),
280 243
            self::EPSG_MILLIMETRE => new Millimetre($measurement),
281
            self::EPSG_FOOT => new Foot($measurement),
282 243
            self::EPSG_LINK => new Link($measurement),
283
            self::EPSG_BRITISH_CHAIN_BENOIT_1895_B => new BritishChain1895BenoitB($measurement),
284
            self::EPSG_BRITISH_FOOT_SEARS_1922 => new BritishFoot1922Sears($measurement),
285
            self::EPSG_BRITISH_YARD_SEARS_1922 => new BritishYard1922Sears($measurement),
286
            self::EPSG_BRITISH_CHAIN_SEARS_1922 => new BritishChain1922Sears($measurement),
287
            self::EPSG_BRITISH_CHAIN_SEARS_1922_TRUNCATED => new BritishChain1922SearsTruncated($measurement),
288 243
            self::EPSG_BRITISH_FOOT_1936 => new BritishFoot1936($measurement),
289
            self::EPSG_US_SURVEY_FOOT => new USSurveyFoot($measurement),
290
            self::EPSG_CLARKES_FOOT => new ClarkeFoot($measurement),
291 126
            self::EPSG_CLARKES_YARD => new ClarkeYard($measurement),
292
            self::EPSG_CLARKES_LINK => new ClarkeLink($measurement),
293 126
            self::EPSG_INDIAN_FOOT => new IndianFoot($measurement),
294 126
            self::EPSG_INDIAN_YARD => new IndianYard($measurement),
295 126
            self::EPSG_GOLD_COAST_FOOT => new GoldCoastFoot($measurement),
296
            self::EPSG_GERMAN_LEGAL_METRE => new GermanLegalMetre($measurement),
297
            default => throw new UnknownUnitOfMeasureException($srid),
298 406
        };
299
    }
300 406
301
    public static function convert(self $length, string $targetSRID): self
302 406
    {
303
        $conversionRatio = static::makeUnit(1, $targetSRID)->asMetres()->getValue();
304
305 225
        return self::makeUnit($length->asMetres()->getValue() / $conversionRatio, $targetSRID);
306
    }
307 225
308
    /**
309
     * @return array<string, string>
310
     */
311
    public static function getSupportedSRIDs(): array
312
    {
313
        return array_map(fn ($supportedSrid) => $supportedSrid['name'], self::$sridData);
314
    }
315
316
    /**
317
     * @return array<string, array{name: string, help: string}>
318
     */
319
    public static function getSupportedSRIDsWithHelp(): array
320
    {
321
        return array_map(fn (array $data) => ['name' => $data['name'], 'help' => $data['help']], static::$sridData);
322
    }
323
324
    /**
325
     * @param class-string<self> $implementingClassFQCN
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<self> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<self>.
Loading history...
326
     */
327
    public static function registerCustomUnit(string $srid, string $name, string $implementingClassFQCN, string $help = ''): void
328
    {
329
        self::$sridData[$srid] = ['name' => $name, 'fqcn' => $implementingClassFQCN, 'help' => $help];
330
    }
331
332
    public function __toString(): string
333
    {
334
        return (string) $this->getValue();
335
    }
336
}
337