Passed
Push — master ( 2068f7...57e3ff )
by Doug
24:27
created

GUGiKHeightGrid::__construct()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 44
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 30
c 1
b 0
f 0
nc 8
nop 1
dl 0
loc 44
ccs 0
cts 31
cp 0
crap 42
rs 8.8177
1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord\CoordinateOperation;
10
11
use function explode;
12
use function max;
13
use function min;
14
use const PHP_FLOAT_MAX;
15
use const PHP_FLOAT_MIN;
16
use PHPCoord\UnitOfMeasure\Length\Metre;
17
use function round;
18
use SplFileObject;
19
use SplFixedArray;
20
use function str_replace;
21
use function trim;
22
23
class GUGiKHeightGrid extends GeographicGeoidHeightGrid
24
{
25
    use BilinearInterpolation;
26
27
    private SplFixedArray $data;
28
29
    public function __construct($filename)
30
    {
31
        $this->storageOrder = self::STORAGE_ORDER_INCREASING_LONGITUDE_INCREASING_LATIITUDE;
32
        $this->gridFile = new SplFileObject($filename);
33
        $this->columnGridInterval = 0.01; // always
34
        $this->rowGridInterval = 0.01; // always
35
36
        // these files have variable length headers, and then are not rectangular!!
37
        do {
38
            $headerLine = str_replace(self::BOM, '', $this->gridFile->fgets());
39
        } while ($headerLine && $headerLine[0] === '#');
40
41
        $firstDataRowIndex = $this->gridFile->key() + 1;
42
43
        $startX = PHP_FLOAT_MAX;
44
        $endX = PHP_FLOAT_MIN;
45
        $startY = PHP_FLOAT_MAX;
46
        $endY = PHP_FLOAT_MIN;
47
        while ($row = $this->gridFile->fgets()) {
48
            $data = explode("\t", trim($row));
49
            $startX = min($startX, (float) $data[1]);
50
            $endX = max($endX, (float) $data[1]);
51
            $startY = min($startY, (float) $data[0]);
52
            $endY = max($endY, (float) $data[0]);
53
        }
54
55
        $this->startX = $startX;
56
        $this->startY = $startY;
57
        $this->numberOfColumns = (int) (string) (($endX - $startX) / $this->columnGridInterval) + 1;
58
        $this->numberOfRows = (int) (string) (($endY - $startY) / $this->rowGridInterval) + 1;
59
60
        // init with 0
61
        $this->data = new SplFixedArray($this->numberOfColumns * $this->numberOfRows);
62
        for ($i = 0, $numValues = $this->numberOfColumns * $this->numberOfRows; $i < $numValues; ++$i) {
63
            $this->data[$i] = 0;
64
        }
65
66
        // fill in with actual values
67
        $this->gridFile->seek($firstDataRowIndex);
68
        while ($row = $this->gridFile->fgets()) {
69
            $rowData = explode("\t", trim($row));
70
71
            $index = round((($rowData[0] - $this->startY) / $this->rowGridInterval) * $this->numberOfColumns + ($rowData[1] - $this->startX) / $this->columnGridInterval);
72
            $this->data[$index] = (float) $rowData[2];
73
        }
74
    }
75
76
    /**
77
     * @return Metre[]
78
     */
79
    public function getValues($x, $y): array
80
    {
81
        $shift = $this->interpolate($x, $y)[0];
82
83
        return [new Metre($shift)];
84
    }
85
86
    protected function getRecord(int $longitudeIndex, int $latitudeIndex): GridValues
87
    {
88
        $recordId = $latitudeIndex * $this->numberOfColumns + $longitudeIndex;
89
90
        $record = $this->data[$recordId];
91
92
        $longitude = $longitudeIndex * $this->columnGridInterval + $this->startX;
93
        $latitude = $latitudeIndex * $this->rowGridInterval + $this->startY;
94
95
        return new GridValues($longitude, $latitude, [$record]);
96
    }
97
}
98