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

BEVHeightGrid   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 75
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 39
dl 0
loc 75
ccs 0
cts 40
cp 0
rs 10
c 1
b 0
f 0
wmc 6

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 42 4
A getRecord() 0 11 1
A getValues() 0 5 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 PHPCoord\UnitOfMeasure\Length\Metre;
12
use SplFixedArray;
13
14
use function array_unique;
15
use function end;
16
use function explode;
17
use function round;
18
use function sort;
19
use function trim;
20
use function assert;
21
22
class BEVHeightGrid extends GeographicGeoidHeightGrid
23
{
24
    use BilinearInterpolation;
25
26
    /**
27
     * @var SplFixedArray<float>
28
     */
29
    private SplFixedArray $data;
30
31
    public function __construct(string $filename)
32
    {
33
        $this->storageOrder = self::STORAGE_ORDER_INCREASING_LONGITUDE_INCREASING_LATIITUDE;
34
        $this->gridFile = new GridFile($filename);
35
36
        // these are not rectangular!!
37
        $xs = [];
38
        $ys = [];
39
        $this->gridFile->seek(1);
40
        while ($row = $this->gridFile->fgets()) {
41
            $data = explode(';', trim($row));
42
            $xs[] = (float) $data[1];
43
            $ys[] = (float) $data[0];
44
        }
45
        $xs = array_unique($xs);
46
        $ys = array_unique($ys);
47
        sort($xs);
48
        sort($ys);
49
50
        $this->startX = $xs[0];
51
        $this->startY = $ys[0];
52
        $this->endX = (float) end($xs);
53
        $this->endY = (float) end($ys);
54
        $this->columnGridInterval = round($xs[1] - $xs[0], 7);
55
        $this->rowGridInterval = round($ys[1] - $ys[0], 7);
56
        $this->numberOfColumns = (int) (string) (($this->endX - $this->startX) / $this->columnGridInterval) + 1;
57
        $this->numberOfRows = (int) (string) (($this->endY - $this->startY) / $this->rowGridInterval) + 1;
58
59
        // init with 0
60
        $this->data = new SplFixedArray($this->numberOfColumns * $this->numberOfRows);
61
        for ($i = 0, $numValues = $this->numberOfColumns * $this->numberOfRows; $i < $numValues; ++$i) {
62
            $this->data[$i] = 0.0;
63
        }
64
65
        // fill in with actual values
66
        $this->gridFile->seek(1);
67
        while ($row = $this->gridFile->fgets()) {
68
            /** @var float[] $rowData */
69
            $rowData = explode(';', trim($row));
70
71
            $index = (int) 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(float $x, float $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
        assert($this->data[$recordId] !== null);
91
        $record = $this->data[$recordId];
92
93
        $longitude = $longitudeIndex * $this->columnGridInterval + $this->startX;
94
        $latitude = $latitudeIndex * $this->rowGridInterval + $this->startY;
95
96
        return new GridValues($longitude, $latitude, [$record]);
97
    }
98
}
99