Passed
Push — master ( fd93b5...48e916 )
by Doug
40:26 queued 29:39
created

IGNFGrid::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 7
ccs 0
cts 3
cp 0
crap 2
rs 10
c 1
b 0
f 0
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 array_map;
12
use function array_slice;
13
use function assert;
14
use function count;
15
use function explode;
16
use function max;
17
use function min;
18
use function preg_match;
19
use function preg_replace;
20
use SplFileObject;
21
use SplFixedArray;
22
use function str_repeat;
23
use function str_replace;
24
use function strlen;
25
use function trim;
26
27
trait IGNFGrid
28
{
29
    use BilinearInterpolation;
30
31
    private int $valuesPerCoordinate;
32
33
    private SplFixedArray $data;
34
35
    public function __construct($filename)
36
    {
37
        $this->gridFile = new SplFileObject($filename);
0 ignored issues
show
Bug Best Practice introduced by
The property gridFile does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
38
39
        match ($this->gridFile->getExtension()) {
40
            'txt' => $this->initTxt(),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->initTxt() targeting PHPCoord\CoordinateOperation\IGNFGrid::initTxt() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
41
            'mnt', 'tac' => $this->initMntOrTac(),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->initMntOrTac() targeting PHPCoord\CoordinateOpera...GNFGrid::initMntOrTac() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
42
        };
43
    }
44
45
    protected function getRecord(int $longitudeIndex, int $latitudeIndex): GridValues
46
    {
47
        $recordId = match ($this->storageOrder) {
48
            self::STORAGE_ORDER_INCREASING_LATITUDE_INCREASING_LONGITUDE => ($longitudeIndex * ($this->numberOfRows) + $latitudeIndex),
0 ignored issues
show
Bug introduced by
The constant PHPCoord\CoordinateOpera...DE_INCREASING_LONGITUDE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
49
            self::STORAGE_ORDER_INCREASING_LONGITUDE_DECREASING_LATIITUDE => ($this->numberOfRows - $latitudeIndex - 1) * $this->numberOfColumns + $longitudeIndex,
0 ignored issues
show
Bug introduced by
The constant PHPCoord\CoordinateOpera...DE_DECREASING_LATIITUDE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
50
        };
51
52
        $record = $this->data[$recordId];
53
54
        $longitude = $longitudeIndex * $this->columnGridInterval + $this->startX;
55
        $latitude = $latitudeIndex * $this->rowGridInterval + $this->startY;
56
57
        return new GridValues($longitude, $latitude, $record);
58
    }
59
60
    private function initTxt(): void
61
    {
62
        $this->valuesPerCoordinate = 3;
63
64
        $header0 = $this->gridFile->fgets();
0 ignored issues
show
Unused Code introduced by
The assignment to $header0 is dead and can be removed.
Loading history...
65
        $header1 = $this->gridFile->fgets();
66
        $header2 = $this->gridFile->fgets();
67
        $header3 = $this->gridFile->fgets();
0 ignored issues
show
Unused Code introduced by
The assignment to $header3 is dead and can be removed.
Loading history...
68
69
        $interpolationMethod = trim(str_replace('GR3D2', '', $header2));
70
        assert($interpolationMethod === 'INTERPOLATION BILINEAIRE');
71
72
        $gridDimensions = explode(' ', trim(preg_replace('/ +/', ' ', str_replace('GR3D1', '', $header1))));
73
        $this->startX = (float) $gridDimensions[0];
74
        $this->endX = (float) $gridDimensions[1];
75
        $this->startY = (float) $gridDimensions[2];
76
        $this->endY = (float) $gridDimensions[3];
77
        $this->columnGridInterval = (float) $gridDimensions[4];
78
        $this->rowGridInterval = (float) $gridDimensions[5];
79
        $this->numberOfColumns = (int) (string) (($this->endX - $this->startX) / $this->columnGridInterval) + 1;
80
        $this->numberOfRows = (int) (string) (($this->endY - $this->startY) / $this->rowGridInterval) + 1;
81
        $this->storageOrder = self::STORAGE_ORDER_INCREASING_LATITUDE_INCREASING_LONGITUDE;
0 ignored issues
show
Bug introduced by
The constant PHPCoord\CoordinateOpera...DE_INCREASING_LONGITUDE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug Best Practice introduced by
The property storageOrder does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
82
83
        $this->data = new SplFixedArray($this->numberOfColumns * $this->numberOfRows);
84
        for ($i = 0, $numValues = $this->numberOfColumns * $this->numberOfRows; $i < $numValues; ++$i) {
85
            $rowData = explode(' ', trim(preg_replace('/ +/', ' ', $this->gridFile->fgets())));
86
            $wantedData = array_slice($rowData, 3, 3); // ignore weird first fixed value, coordinates, precision and map sheet
87
            $wantedData = array_map(static function (string $value) {return (float) ($value); }, $wantedData);
88
            $this->data[$i] = $wantedData;
89
        }
90
91
        $this->gridFile->fgets();
92
        assert($this->gridFile->eof());
93
    }
94
95
    private function initMntOrTac(): void
96
    {
97
        $fixedHeaderRegexp = '^(-?[\d.]+) (-?[\d.]+) (-?[\d.]+) (-?[\d.]+) ([\d.]+) ([\d.]+) ([1-4]) ([01]) (\d) ([01]) ';
98
        $header = $this->gridFile->fgets();
99
100
        preg_match('/' . $fixedHeaderRegexp . '/', $header, $fixedHeaderParts);
101
102
        $this->startX = min((float) $fixedHeaderParts[1], (float) $fixedHeaderParts[2]);
103
        $this->endX = max((float) $fixedHeaderParts[1], (float) $fixedHeaderParts[2]);
104
        $this->startY = min((float) $fixedHeaderParts[3], (float) $fixedHeaderParts[4]);
105
        $this->endY = max((float) $fixedHeaderParts[3], (float) $fixedHeaderParts[4]);
106
        $this->columnGridInterval = (float) $fixedHeaderParts[5];
107
        $this->rowGridInterval = (float) $fixedHeaderParts[6];
108
        $this->numberOfColumns = (int) (string) (($this->endX - $this->startX) / $this->columnGridInterval) + 1;
109
        $this->numberOfRows = (int) (string) (($this->endY - $this->startY) / $this->rowGridInterval) + 1;
110
        $this->storageOrder = (int) $fixedHeaderParts[7];
0 ignored issues
show
Bug Best Practice introduced by
The property storageOrder does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
111
        $coordinatesIncludedInData = (bool) $fixedHeaderParts[8];
112
        $this->valuesPerCoordinate = (int) $fixedHeaderParts[9];
113
        $precisionIncluded = (bool) $fixedHeaderParts[10];
114
115
        preg_match('/' . $fixedHeaderRegexp . str_repeat('(-?[\d.]+) ', $this->valuesPerCoordinate) . '(.*)$/', $header, $fullHeaderParts);
116
117
        $baseAdjustments = array_slice($fullHeaderParts, count($fullHeaderParts) - $this->valuesPerCoordinate - 1, $this->valuesPerCoordinate);
118
        foreach ($baseAdjustments as $baseAdjustment) {
119
            assert((float) $baseAdjustment === 0.0);
120
        }
121
122
        // these files are not always 1 record per line (sometimes blank lines, sometimes multiple records per row)
123
        // so direct file access is not possible. Read into memory instead :/
124
125
        $this->data = new SplFixedArray($this->numberOfColumns * $this->numberOfRows);
126
127
        $rawData = $this->gridFile->fread($this->gridFile->getSize() - strlen($header));
128
        $values = explode(' ', trim(preg_replace('/\s+/', ' ', $rawData)));
129
130
        $cursor = 0;
131
        for ($i = 0, $numValues = $this->numberOfColumns * $this->numberOfRows; $i < $numValues; ++$i) {
132
            if ($coordinatesIncludedInData) {
133
                $cursor += 2;
134
            }
135
136
            $rowData = [];
137
            for ($j = 0; $j < $this->valuesPerCoordinate; ++$j) {
138
                $rowData[] = (float) $values[$cursor];
139
                ++$cursor;
140
            }
141
142
            $this->data[$i] = $rowData;
143
144
            if ($precisionIncluded) {
145
                ++$cursor;
146
            }
147
        }
148
149
        $this->gridFile->fgets();
150
        assert($this->gridFile->eof());
151
    }
152
}
153