Passed
Push — master ( aca0dd...3e5121 )
by Doug
22:36
created

GTXGrid   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 67
Duplicated Lines 0 %

Test Coverage

Coverage 90.7%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 41
c 1
b 0
f 0
dl 0
loc 67
ccs 39
cts 43
cp 0.907
rs 10
wmc 7

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getRecord() 0 11 1
A getHeader() 0 20 3
A getAdjustment() 0 7 1
A __construct() 0 14 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 PHPCoord\GeographicPoint;
12
use PHPCoord\UnitOfMeasure\Length\Metre;
13
use SplFileObject;
14
use function substr;
15
use function unpack;
16
17
/**
18
 * @see https://vdatum.noaa.gov/docs/gtx_info.html for documentation
19
 */
20
class GTXGrid extends SplFileObject
21
{
22
    use BilinearInterpolation;
23
24
    private int $headerLength;
25
    private string $offsetDataType;
26
27 7
    public function __construct($filename)
28
    {
29 7
        parent::__construct($filename);
30
31 7
        $header = $this->getHeader();
32 7
        $this->startX = $header['xlonsw'];
33 7
        $this->startY = $header['xlatsw'];
34 7
        $this->numberOfColumns = $header['nlon'];
35 7
        $this->numberOfRows = $header['nlat'];
36 7
        $this->columnGridInterval = $header['dlon'];
37 7
        $this->rowGridInterval = $header['dlat'];
38
39 7
        if ($this->startX > 180) { // normalise if necessary
40 1
            $this->startX -= 360;
41
        }
42 7
    }
43
44 7
    public function getAdjustment(GeographicPoint $point): Metre
45
    {
46 7
        $latitude = $point->getLatitude()->getValue();
47 7
        $longitude = $point->getLongitude()->getValue();
48 7
        $offset = $this->interpolateBilinear($longitude, $latitude)[0];
49
50 7
        return new Metre($offset);
51
    }
52
53 7
    private function getRecord(int $longitudeIndex, int $latitudeIndex): GridValues
0 ignored issues
show
Unused Code introduced by
The method getRecord() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
54
    {
55 7
        $offset = $this->headerLength + ($latitudeIndex * $this->numberOfColumns + $longitudeIndex) * 4;
56 7
        $this->fseek($offset);
57 7
        $rawRow = $this->fread(4);
58 7
        $data = unpack("{$this->offsetDataType}offset", $rawRow);
59
60 7
        return new GridValues(
61 7
            $longitudeIndex * $this->columnGridInterval + $this->startX,
62 7
            $latitudeIndex * $this->rowGridInterval + $this->startY,
63 7
            [$data['offset']]
64
        );
65
    }
66
67 7
    private function getHeader(): array
68
    {
69 7
        $this->fseek(0);
70 7
        $rawHeader = $this->fread(44);
71 7
        $ikind = substr($rawHeader, 40, 4);
72 7
        if (unpack('Nikind', $ikind)['ikind'] === 1) { // big endian
73
            $this->headerLength = 44;
74
            $this->offsetDataType = 'G';
75
            $data = unpack('Exlatsw/Exlonsw/Edlat/Edlon/Nnlat/Nnlon', $rawHeader);
76 7
        } elseif (unpack('Vikind', $ikind)['ikind'] === 1) { // little endian
77 1
            $this->headerLength = 44;
78 1
            $this->offsetDataType = 'g';
79 1
            $data = unpack('exlatsw/exlonsw/edlat/edlon/Vnlat/Vnlon', $rawHeader);
80
        } else { // not all files (e.g. NZ) have this endian check column, assume big endian
81 6
            $this->headerLength = 40;
82 6
            $this->offsetDataType = 'G';
83 6
            $data = unpack('Exlatsw/Exlonsw/Edlat/Edlon/Nnlat/Nnlon', $rawHeader);
84
        }
85
86 7
        return $data;
87
    }
88
}
89