Passed
Push — master ( 1c87d2...a64886 )
by Doug
04:35
created

IrishGridPoint   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 71
Duplicated Lines 0 %

Test Coverage

Coverage 93.55%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 28
c 1
b 0
f 0
dl 0
loc 71
ccs 29
cts 31
cp 0.9355
rs 10
wmc 6

4 Methods

Rating   Name   Duplication   Size   Complexity  
A gridReference() 0 23 2
A fromGridReference() 0 19 2
A __construct() 0 3 1
A asGridReference() 0 3 1
1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord;
10
11
use DateTimeInterface;
12
use function floor;
13
use function implode;
14
use PHPCoord\CoordinateReferenceSystem\Projected;
15
use PHPCoord\Exception\InvalidCoordinateException;
16
use PHPCoord\UnitOfMeasure\Length\Length;
17
use PHPCoord\UnitOfMeasure\Length\Metre;
18
use function str_pad;
19
use function strlen;
20
use function strpos;
21
use function substr;
22
23
/**
24
 * N.B. This is the older 1975 system, not the current ITM system for which @see IrishTransverseMercatorPoint.
25
 */
26
class IrishGridPoint extends ProjectedPoint
27
{
28
    private const GRID_LETTERS = 'VWXYZQRSTULMNOPFGHJKABCDE';
29
30 6
    public function __construct(Length $easting, Length $northing, ?DateTimeInterface $epoch = null)
31
    {
32 6
        parent::__construct($easting, $northing, null, null, Projected::fromSRID(Projected::EPSG_TM75_IRISH_GRID), $epoch);
33 6
    }
34
35
    /**
36
     * @param string Irish grid reference (e.g. "T514131")
37
     */
38 3
    public static function fromGridReference(string $reference, ?DateTimeInterface $epoch = null): self
39
    {
40 3
        if (strlen($reference) % 2 === 0) {
41
            throw new InvalidCoordinateException('Grid ref must be an even number of characters');
42
        }
43
44
        //Letter is 100km grid sq, origin at 0,0 of this square
45 3
        $minorEasting = strpos(static::GRID_LETTERS, $reference[0]) % 5 * 100000;
46 3
        $minorNorthing = (floor(strpos(static::GRID_LETTERS, $reference[0]) / 5)) * 100000;
47
48
        //numbers are a division of that square into smaller and smaller pieces
49 3
        $numericPortion = substr($reference, 1);
50 3
        $numericPortionSize = strlen($numericPortion) / 2;
51 3
        $gridSizeInMetres = 1 * (10 ** (5 - $numericPortionSize));
52
53 3
        $easting = $minorEasting + (substr($numericPortion, 0, $numericPortionSize) * $gridSizeInMetres);
54 3
        $northing = $minorNorthing + (substr($numericPortion, -$numericPortionSize, $numericPortionSize) * $gridSizeInMetres);
55
56 3
        return new static(new Metre($easting), new Metre($northing), $epoch);
57
    }
58
59
    /**
60
     * Grid reference without spaces. e.g. T514131.
61
     */
62 1
    public function asGridReference(int $length): string
63
    {
64 1
        return implode('', $this->gridReference($length));
65
    }
66
67
    /**
68
     * Convert this grid reference into a grid reference string of a
69
     * given length (2, 4, 6, 8 or 10) including the character
70
     * designation for the 100km square. e.g. T514131.
71
     *
72
     * @return string
73
     */
74 1
    protected function gridReference(int $length): array
75
    {
76 1
        if ($length % 2 !== 0) {
77
            throw new InvalidCoordinateException('Chosen length must be an even number');
78
        }
79
80 1
        $halfLength = $length / 2;
81
82 1
        $x = $this->easting->asMetres()->getValue();
83 1
        $y = $this->northing->asMetres()->getValue();
84 1
        $easting = str_pad((string) $x, 6, '0', STR_PAD_LEFT);
85 1
        $northing = str_pad((string) $y, 6, '0', STR_PAD_LEFT);
86
87
        //second (minor) letter is 100km grid sq, origin at 0,0 of this square
88 1
        $minorSquaresEast = $easting[0] % 5;
89 1
        $minorSquaresNorth = $northing[0] % 5;
90 1
        $minorLetterIndex = (5 * $minorSquaresNorth + $minorSquaresEast);
91 1
        $minorLetter = substr(self::GRID_LETTERS, $minorLetterIndex, 1);
92
93
        return [
94 1
            $minorLetter,
95 1
            substr($easting, 1, $halfLength),
96 1
            substr($northing, 1, $halfLength),
97
        ];
98
    }
99
}
100