Passed
Push — master ( 6be4bd...2c19f0 )
by Doug
51:47
created

IGNFGrid   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Test Coverage

Coverage 66.23%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 74
c 1
b 0
f 0
dl 0
loc 124
ccs 51
cts 77
cp 0.6623
rs 10
wmc 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B initMntOrTac() 0 56 6
A getRecord() 0 13 1
A initTxt() 0 33 2
1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord\CoordinateOperation;
10
11
use SplFileObject;
12
use SplFixedArray;
13
14
use function array_map;
15
use function array_slice;
16
use function assert;
17
use function count;
18
use function explode;
19
use function max;
20
use function min;
21
use function preg_match;
22
use function preg_replace;
23
use function str_repeat;
24
use function str_replace;
25
use function strlen;
26
use function trim;
27
28
trait IGNFGrid
29
{
30
    use BilinearInterpolation;
31
32
    private int $valuesPerCoordinate;
33
34
    private SplFixedArray $data;
35
36 4
    public function __construct($filename)
37
    {
38 4
        $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...
39
40 4
        match ($this->gridFile->getExtension()) {
41 4
            '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...
42 4
            '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...
43 4
        };
44
    }
45
46 4
    protected function getRecord(int $longitudeIndex, int $latitudeIndex): GridValues
47
    {
48 4
        $recordId = match ($this->storageOrder) {
49 4
            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...
50 4
            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...
51 4
        };
52
53 4
        $record = $this->data[$recordId];
54
55 4
        $longitude = $longitudeIndex * $this->columnGridInterval + $this->startX;
56 4
        $latitude = $latitudeIndex * $this->rowGridInterval + $this->startY;
57
58 4
        return new GridValues($longitude, $latitude, $record);
59
    }
60
61
    private function initTxt(): void
62
    {
63
        $this->valuesPerCoordinate = 3;
64
65
        $header0 = $this->gridFile->fgets();
0 ignored issues
show
Unused Code introduced by
The assignment to $header0 is dead and can be removed.
Loading history...
66
        $header1 = $this->gridFile->fgets();
67
        $header2 = $this->gridFile->fgets();
68
        $header3 = $this->gridFile->fgets();
0 ignored issues
show
Unused Code introduced by
The assignment to $header3 is dead and can be removed.
Loading history...
69
70
        $interpolationMethod = trim(str_replace('GR3D2', '', $header2));
71
        assert($interpolationMethod === 'INTERPOLATION BILINEAIRE');
72
73
        $gridDimensions = explode(' ', trim(preg_replace('/ +/', ' ', str_replace('GR3D1', '', $header1))));
74
        $this->startX = (float) $gridDimensions[0];
75
        $this->endX = (float) $gridDimensions[1];
76
        $this->startY = (float) $gridDimensions[2];
77
        $this->endY = (float) $gridDimensions[3];
78
        $this->columnGridInterval = (float) $gridDimensions[4];
79
        $this->rowGridInterval = (float) $gridDimensions[5];
80
        $this->numberOfColumns = (int) (string) (($this->endX - $this->startX) / $this->columnGridInterval) + 1;
81
        $this->numberOfRows = (int) (string) (($this->endY - $this->startY) / $this->rowGridInterval) + 1;
82
        $this->storageOrder = self::STORAGE_ORDER_INCREASING_LATITUDE_INCREASING_LONGITUDE;
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...
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...
83
84
        $this->data = new SplFixedArray($this->numberOfColumns * $this->numberOfRows);
85
        for ($i = 0, $numValues = $this->numberOfColumns * $this->numberOfRows; $i < $numValues; ++$i) {
86
            $rowData = explode(' ', trim(preg_replace('/ +/', ' ', $this->gridFile->fgets())));
87
            $wantedData = array_slice($rowData, 3, 3); // ignore weird first fixed value, coordinates, precision and map sheet
88
            $wantedData = array_map(static fn (string $value) => (float) $value, $wantedData);
89
            $this->data[$i] = $wantedData;
90
        }
91
92
        $this->gridFile->fgets();
93
        assert($this->gridFile->eof());
94
    }
95
96 4
    private function initMntOrTac(): void
97
    {
98 4
        $fixedHeaderRegexp = '^(-?[\d.]+) (-?[\d.]+) (-?[\d.]+) (-?[\d.]+) ([\d.]+) ([\d.]+) ([1-4]) ([01]) (\d) ([01]) ';
99 4
        $header = $this->gridFile->fgets();
100
101 4
        preg_match('/' . $fixedHeaderRegexp . '/', $header, $fixedHeaderParts);
102
103 4
        $this->startX = min((float) $fixedHeaderParts[1], (float) $fixedHeaderParts[2]);
104 4
        $this->endX = max((float) $fixedHeaderParts[1], (float) $fixedHeaderParts[2]);
105 4
        $this->startY = min((float) $fixedHeaderParts[3], (float) $fixedHeaderParts[4]);
106 4
        $this->endY = max((float) $fixedHeaderParts[3], (float) $fixedHeaderParts[4]);
107 4
        $this->columnGridInterval = (float) $fixedHeaderParts[5];
108 4
        $this->rowGridInterval = (float) $fixedHeaderParts[6];
109 4
        $this->numberOfColumns = (int) (string) (($this->endX - $this->startX) / $this->columnGridInterval) + 1;
110 4
        $this->numberOfRows = (int) (string) (($this->endY - $this->startY) / $this->rowGridInterval) + 1;
111 4
        $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...
112 4
        $coordinatesIncludedInData = (bool) $fixedHeaderParts[8];
113 4
        $this->valuesPerCoordinate = (int) $fixedHeaderParts[9];
114 4
        $precisionIncluded = (bool) $fixedHeaderParts[10];
115
116 4
        preg_match('/' . $fixedHeaderRegexp . str_repeat('(-?[\d.]+) ', $this->valuesPerCoordinate) . '(.*)$/', $header, $fullHeaderParts);
117
118 4
        $baseAdjustments = array_slice($fullHeaderParts, count($fullHeaderParts) - $this->valuesPerCoordinate - 1, $this->valuesPerCoordinate);
119 4
        foreach ($baseAdjustments as $baseAdjustment) {
120 4
            assert((float) $baseAdjustment === 0.0);
121
        }
122
123
        // these files are not always 1 record per line (sometimes blank lines, sometimes multiple records per row)
124
        // so direct file access is not possible. Read into memory instead :/
125
126 4
        $this->data = new SplFixedArray($this->numberOfColumns * $this->numberOfRows);
127
128 4
        $rawData = $this->gridFile->fread($this->gridFile->getSize() - strlen($header));
129 4
        $values = explode(' ', trim(preg_replace('/\s+/', ' ', $rawData)));
130
131 4
        $cursor = 0;
132 4
        for ($i = 0, $numValues = $this->numberOfColumns * $this->numberOfRows; $i < $numValues; ++$i) {
133 4
            if ($coordinatesIncludedInData) {
134 4
                $cursor += 2;
135
            }
136
137 4
            $rowData = [];
138 4
            for ($j = 0; $j < $this->valuesPerCoordinate; ++$j) {
139 4
                $rowData[] = (float) $values[$cursor];
140 4
                ++$cursor;
141
            }
142
143 4
            $this->data[$i] = $rowData;
144
145 4
            if ($precisionIncluded) {
146 4
                ++$cursor;
147
            }
148
        }
149
150 4
        $this->gridFile->fgets();
151 4
        assert($this->gridFile->eof());
152
    }
153
}
154