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

IGNESHeightGrid   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 33
dl 0
loc 70
ccs 0
cts 35
cp 0
rs 10
c 1
b 0
f 0
wmc 6

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getRecord() 0 11 1
A getValues() 0 5 1
A init() 0 32 3
A __construct() 0 4 1
1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord\CoordinateOperation;
10
11
use Composer\Pcre\Preg;
12
use PHPCoord\UnitOfMeasure\Length\Metre;
13
use SplFixedArray;
14
15
use function explode;
16
use function strlen;
17
use function trim;
18
use function assert;
19
20
class IGNESHeightGrid extends GeographicGeoidHeightGrid
21
{
22
    use BilinearInterpolation;
23
24
    /**
25
     * @var SplFixedArray<array<float>>
26
     */
27
    private SplFixedArray $data;
28
29
    public function __construct(string $filename)
30
    {
31
        $this->gridFile = new GridFile($filename);
32
        $this->init();
33
    }
34
35
    /**
36
     * @return Metre[]
37
     */
38
    public function getValues(float $x, float $y): array
39
    {
40
        $shift = $this->interpolate($x, $y)[0];
41
42
        return [new Metre($shift)];
43
    }
44
45
    protected function getRecord(int $longitudeIndex, int $latitudeIndex): GridValues
46
    {
47
        $recordId = ($this->numberOfRows - $latitudeIndex - 1) * $this->numberOfColumns + $longitudeIndex;
48
49
        assert($this->data[$recordId] !== null);
50
        $record = $this->data[$recordId];
51
52
        $longitude = $longitudeIndex * $this->columnGridInterval + $this->startX;
53
        $latitude = $latitudeIndex * $this->rowGridInterval + $this->startY;
54
55
        return new GridValues($longitude, $latitude, $record);
56
    }
57
58
    private function init(): void
59
    {
60
        $headerRegexp = '^\s+(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)\s+([\d.]+)\s+([\d.]+)';
61
        $header = $this->gridFile->fgets();
62
63
        Preg::match('/' . $headerRegexp . '/', $header, $headerParts);
64
65
        $this->columnGridInterval = (float) $headerParts[4] / 60;
66
        $this->rowGridInterval = (float) $headerParts[3] / 60;
67
        $this->numberOfColumns = (int) $headerParts[6];
68
        $this->numberOfRows = (int) $headerParts[5];
69
        $this->startX = (float) $headerParts[2];
70
        if ($this->startX > 180) {
71
            $this->startX -= 360;
72
        }
73
        $this->endX = $this->startX + ($this->numberOfColumns - 1) * $this->columnGridInterval;
74
        $this->endY = (float) $headerParts[1];
75
        $this->startY = $this->endY - ($this->numberOfRows - 1) * $this->rowGridInterval;
76
77
        // these files are not 1 record per line so direct file access is not possible. Read into memory instead :/
78
79
        $this->data = new SplFixedArray($this->numberOfColumns * $this->numberOfRows);
80
81
        $rawData = $this->gridFile->fread($this->gridFile->getSize() - strlen($header));
82
        $values = explode(' ', trim(Preg::replace('/\s+/', ' ', $rawData)));
83
84
        $cursor = 0;
85
        for ($i = 0, $numValues = $this->numberOfColumns * $this->numberOfRows; $i < $numValues; ++$i) {
86
            $rowData = [(float) $values[$cursor]];
87
            ++$cursor;
88
89
            $this->data[$i] = $rowData;
90
        }
91
    }
92
}
93