Passed
Push — master ( be3192...a784d9 )
by Doug
25:13
created

zeroTideHeightToMeanTideHeightEVRF2019()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

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

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