Passed
Push — master ( aff60e...d66a7a )
by Doug
120:22 queued 55:20
created

OSTNOSGM15Grid::getRecord()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 6
rs 10
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 abs;
12
use PHPCoord\CoordinateReferenceSystem\Projected;
0 ignored issues
show
Bug introduced by
The type PHPCoord\CoordinateReferenceSystem\Projected was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use PHPCoord\CoordinateSystem\Cartesian;
14
use PHPCoord\Datum\Datum;
15
use PHPCoord\ProjectedPoint;
16
use PHPCoord\UnitOfMeasure\Length\Metre;
17
use SplFileObject;
18
19
class OSTNOSGM15Grid extends SplFileObject
20
{
21
    private const GRID_SIZE = 1000;
22
23
    private const ITERATION_CONVERGENCE = 0.0001;
24
25
    public function applyForwardAdjustment(ProjectedPoint $point): ProjectedPoint
26
    {
27
        $adjustment = $this->getAdjustment($point->getEasting()->asMetres(), $point->getNorthing()->asMetres());
28
29
        $easting = $point->getEasting()->add(new Metre($adjustment[0]));
30
        $northing = $point->getNorthing()->add(new Metre($adjustment[1]));
31
32
        return ProjectedPoint::createFromEastingNorthing($easting, $northing, Projected::fromSRID(Projected::EPSG_OSGB36_BRITISH_NATIONAL_GRID), $point->getCoordinateEpoch());
33
    }
34
35
    public function applyReverseAdjustment(ProjectedPoint $point): ProjectedPoint
36
    {
37
        $osgb36NationalGrid = Projected::fromSRID(Projected::EPSG_OSGB36_BRITISH_NATIONAL_GRID);
38
        $etrs89NationalGrid = new Projected(
39
            'ETRS89 / National Grid',
40
            Cartesian::fromSRID(Cartesian::EPSG_2D_AXES_EASTING_NORTHING_E_N_ORIENTATIONS_EAST_NORTH_UOM_M),
41
            Datum::fromSRID(Datum::EPSG_EUROPEAN_TERRESTRIAL_REFERENCE_SYSTEM_1989_ENSEMBLE),
42
            $osgb36NationalGrid->getBoundingArea()
43
        );
44
45
        $adjustment = [0, 0];
46
        $easting = $point->getEasting();
47
        $northing = $point->getNorthing();
48
49
        do {
50
            $prevAdjustment = $adjustment;
51
            $adjustment = $this->getAdjustment($easting->asMetres(), $northing->asMetres());
52
            $easting = $point->getEasting()->subtract(new Metre($adjustment[0]));
53
            $northing = $point->getNorthing()->subtract(new Metre($adjustment[1]));
54
        } while (abs($adjustment[0] - $prevAdjustment[0]) > self::ITERATION_CONVERGENCE && abs($adjustment[1] - $prevAdjustment[1]) > self::ITERATION_CONVERGENCE);
55
56
        return ProjectedPoint::createFromEastingNorthing($easting, $northing, $etrs89NationalGrid, $point->getCoordinateEpoch());
57
    }
58
59
    public function getAdjustment(Metre $easting, Metre $northing): array
60
    {
61
        $eastIndex = (int) ($easting->getValue() / self::GRID_SIZE);
62
        $northIndex = (int) ($northing->getValue() / self::GRID_SIZE);
63
64
        $corner0 = $this->getRecord($eastIndex, $northIndex);
65
        $corner1 = $this->getRecord($eastIndex + 1, $northIndex);
66
        $corner2 = $this->getRecord($eastIndex + 1, $northIndex + 1);
67
        $corner3 = $this->getRecord($eastIndex, $northIndex + 1);
68
69
        $dx = $easting->getValue() - $corner0[1];
70
        $dy = $northing->getValue() - $corner0[2];
71
72
        $t = $dx / self::GRID_SIZE;
73
        $u = $dy / self::GRID_SIZE;
74
75
        $se = (1 - $t) * (1 - $u) * $corner0[3] + ($t) * (1 - $u) * $corner1[3] + ($t) * ($u) * $corner2[3] + (1 - $t) * ($u) * $corner3[3];
76
        $sn = (1 - $t) * (1 - $u) * $corner0[4] + ($t) * (1 - $u) * $corner1[4] + ($t) * ($u) * $corner2[4] + (1 - $t) * ($u) * $corner3[4];
77
78
        return [$se, $sn];
79
    }
80
81
    public function getRecord(int $eastIndex, int $northIndex): array
82
    {
83
        $record = $northIndex * 701 + $eastIndex + 1;
84
        $this->seek($record);
85
86
        return $this->fgetcsv();
87
    }
88
}
89