Passed
Push — master ( 99135b...c08bef )
by Doug
16:52
created

VerticalPoint::verticalOffsetGTX()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 4
dl 0
loc 13
ccs 5
cts 5
cp 1
crap 2
rs 10
1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord;
10
11
use function abs;
12
use function cos;
13
use DateTime;
14
use DateTimeImmutable;
15
use DateTimeInterface;
16
use PHPCoord\CoordinateOperation\GTXGrid;
17
use PHPCoord\CoordinateReferenceSystem\Vertical;
18
use PHPCoord\Exception\InvalidCoordinateReferenceSystemException;
19
use PHPCoord\UnitOfMeasure\Angle\Angle;
20
use PHPCoord\UnitOfMeasure\Length\Length;
21
use PHPCoord\UnitOfMeasure\Length\Metre;
22
use function sin;
23
use function sqrt;
24
25
/**
26
 * Coordinate representing a vertical dimension.
27
 */
28
class VerticalPoint extends Point
29
{
30
    /**
31
     * Height.
32
     */
33
    protected Length $height;
34
35
    /**
36
     * Coordinate reference system.
37
     */
38
    protected Vertical $crs;
39
40
    /**
41
     * Coordinate epoch (date for which the specified coordinates represented this point).
42
     */
43
    protected ?DateTimeImmutable $epoch;
44
45
    /**
46
     * Constructor.
47
     * @param Length $height refer to CRS for preferred unit of measure, but any length unit accepted
48
     */
49 189
    protected function __construct(Length $height, Vertical $crs, ?DateTimeInterface $epoch = null)
50
    {
51 189
        $this->height = Length::convert($height, $crs->getCoordinateSystem()->getAxes()[0]->getUnitOfMeasureId());
52 189
        $this->crs = $crs;
53
54 189
        if ($epoch instanceof DateTime) {
55 9
            $epoch = DateTimeImmutable::createFromMutable($epoch);
56
        }
57 189
        $this->epoch = $epoch;
58 189
    }
59
60
    /**
61
     * Constructor.
62
     * @param Length $height refer to CRS for preferred unit of measure, but any length unit accepted
63
     */
64 189
    public static function create(Length $height, Vertical $crs, ?DateTimeInterface $epoch = null): self
65
    {
66 189
        return new static($height, $crs, $epoch);
67
    }
68
69 153
    public function getHeight(): Length
70
    {
71 153
        return $this->height;
72
    }
73
74 45
    public function getCRS(): Vertical
75
    {
76 45
        return $this->crs;
77
    }
78
79 27
    public function getCoordinateEpoch(): ?DateTimeImmutable
80
    {
81 27
        return $this->epoch;
82
    }
83
84 9
    public function calculateDistance(Point $to): Length
85
    {
86 9
        if ($to->getCRS()->getSRID() !== $this->crs->getSRID()) {
87
            throw new InvalidCoordinateReferenceSystemException('Can only calculate distances between two points in the same CRS');
88
        }
89
90
        /* @var self $to */
91 9
        return new Metre(abs($this->height->asMetres()->getValue() - $to->height->asMetres()->getValue()));
92
    }
93
94 54
    public function __toString(): string
95
    {
96 54
        return "({$this->height})";
97
    }
98
99
    /**
100
     * Vertical Offset
101
     * This transformation allows calculation of height (or depth) in the target system by adding the parameter value
102
     * to the height (or depth)-value of the point in the source system.
103
     */
104 9
    public function verticalOffset(
105
        Vertical $to,
106
        Length $verticalOffset
107
    ): self {
108 9
        return static::create($this->height->add($verticalOffset), $to);
109
    }
110
111
    /**
112
     * Vertical Offset and Slope
113
     * This transformation allows calculation of height in the target system by applying the parameter values to the
114
     * height value of the point in the source system.
115
     */
116 18
    public function verticalOffsetAndSlope(
117
        Vertical $to,
118
        Angle $ordinate1OfEvaluationPoint,
119
        Angle $ordinate2OfEvaluationPoint,
120
        Length $verticalOffset,
121
        Angle $inclinationInLatitude,
122
        Angle $inclinationInLongitude,
123
        string $EPSGCodeForHorizontalCRS,
0 ignored issues
show
Unused Code introduced by
The parameter $EPSGCodeForHorizontalCRS is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

123
        /** @scrutinizer ignore-unused */ string $EPSGCodeForHorizontalCRS,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
124
        GeographicPoint $horizontalPoint
125
    ): self {
126 18
        $latitude = $horizontalPoint->getLatitude()->asRadians()->getValue();
127 18
        $longitude = $horizontalPoint->getLongitude()->asRadians()->getValue();
128 18
        $latitudeOrigin = $ordinate1OfEvaluationPoint->asRadians()->getValue();
129 18
        $longitudeOrigin = $ordinate2OfEvaluationPoint->asRadians()->getValue();
130 18
        $a = $horizontalPoint->getCRS()->getDatum()->getEllipsoid()->getSemiMajorAxis()->asMetres()->getValue();
131 18
        $e2 = $horizontalPoint->getCRS()->getDatum()->getEllipsoid()->getEccentricitySquared();
132
133 18
        $rhoOrigin = $a * (1 - $e2) / (1 - $e2 * sin($latitudeOrigin) ** 2) ** 1.5;
134 18
        $nuOrigin = $a / sqrt(1 - $e2 * (sin($latitudeOrigin) ** 2));
135
136 18
        $latitudeTerm = new Metre($inclinationInLatitude->asRadians()->getValue() * $rhoOrigin * ($latitude - $latitudeOrigin));
137 18
        $longitudeTerm = new Metre($inclinationInLongitude->asRadians()->getValue() * $nuOrigin * ($longitude - $longitudeOrigin) * cos($latitude));
138 18
        $newVerticalHeight = $this->getHeight()->add($verticalOffset)->add($latitudeTerm)->add($longitudeTerm);
139
140 18
        return self::create($newVerticalHeight, $to);
141
    }
142
143
    /**
144
     * Height Depth Reversal.
145
     */
146 9
    public function heightDepthReversal(
147
        Vertical $to
148
    ): self {
149 9
        return static::create($this->height->multiply(-1), $to);
150
    }
151
152
    /**
153
     * Change of Vertical Unit.
154
     */
155 9
    public function changeOfVerticalUnit(
156
        Vertical $to
157
    ): self {
158
        // units are auto-converted, don't need to use the supplied param
159 9
        return static::create($this->height, $to, $this->epoch);
160
    }
161
162
    /**
163
     * Zero-tide height to mean-tide height (EVRF2019)
164
     * The offset of -0.08593 is applied to force EVRF2019 mean-tide height to be equal to EVRF2019 height at the
165
     * EVRF2019 nominal origin at Amsterdams Peil.
166
     */
167 18
    public function zeroTideHeightToMeanTideHeightEVRF2019(
168
        Vertical $to,
169
        bool $inReverse,
170
        GeographicPoint $horizontalPoint
171
    ): self {
172 18
        $latitude = $horizontalPoint->getLatitude()->asRadians()->getValue();
173 18
        $delta = new Metre((0.29541 * sin($latitude) ** 2 + 0.00042 * sin($latitude) ** 4 - 0.0994) - 0.08593);
174
175 18
        if ($inReverse) {
176 9
            $delta = $delta->multiply(-1);
177
        }
178
179 18
        return static::create($this->height->add($delta), $to);
180
    }
181
182
    /**
183
     * Vertical Offset by Grid Interpolation (gtx).
184
     */
185 2
    public function verticalOffsetGTX(
186
        Vertical $to,
187
        GTXGrid $verticalOffsetFile,
188
        bool $inReverse,
189
        GeographicPoint $horizontalPoint
190
    ): self {
191 2
        $delta = $verticalOffsetFile->getAdjustment($horizontalPoint);
192
193 2
        if ($inReverse) {
194 1
            $delta = $delta->multiply(-1);
195
        }
196
197 2
        return static::create($this->height->add($delta), $to);
198
    }
199
}
200