Passed
Push — 4.x ( f9780c...a64886 )
by Doug
05:20
created

GeocentricValue::getDatum()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 0
crap 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 function abs;
12
use function atan2;
13
use function cos;
14
use PHPCoord\Datum\Datum;
15
use PHPCoord\UnitOfMeasure\Angle\Radian;
16
use PHPCoord\UnitOfMeasure\Length\Length;
17
use PHPCoord\UnitOfMeasure\Length\Metre;
18
use function sin;
19
use function sqrt;
20
21
/**
22
 * A geocentric point w/out a CRS.
23
 * @internal
24
 */
25
class GeocentricValue
26
{
27
    protected const NEWTON_RAPHSON_CONVERGENCE = 1e-16;
28
29
    private Metre$x;
30
31
    private Metre $y;
32
33
    private Metre $z;
34
35
    private Datum $datum;
36
37 18
    public function __construct(Length $x, Length $y, Length $z, Datum $datum)
38
    {
39 18
        $this->x = $x->asMetres();
40 18
        $this->y = $y->asMetres();
41 18
        $this->z = $z->asMetres();
42 18
        $this->datum = $datum;
43 18
    }
44
45 13
    public function getX(): Metre
46
    {
47 13
        return $this->x;
48
    }
49
50 13
    public function getY(): Metre
51
    {
52 13
        return $this->y;
53
    }
54
55 13
    public function getZ(): Metre
56
    {
57 13
        return $this->z;
58
    }
59
60 15
    public function asGeographicValue(): GeographicValue
61
    {
62 15
        $a = $this->datum->getEllipsoid()->getSemiMajorAxis()->asMetres()->getValue();
63 15
        $e2 = $this->datum->getEllipsoid()->getEccentricitySquared();
64 15
        $x = $this->x->getValue();
65 15
        $y = $this->y->getValue();
66 15
        $z = $this->z->getValue();
67
68 15
        $longitude = atan2($y, $x);
69 15
        $p = sqrt(($x ** 2) + ($y ** 2));
70
71 15
        $latitude = atan2($z, ($p * (1 - $e2)));
72
73
        do {
74 15
            $phi1 = $latitude;
75 15
            $v = $a / sqrt(1 - $e2 * (sin($latitude) ** 2));
76 15
            $latitude = atan2($z + ($e2 * $v * sin($latitude)), $p);
77 15
        } while (abs($latitude - $phi1) >= self::NEWTON_RAPHSON_CONVERGENCE);
78
79 15
        $latitude += $this->datum->getPrimeMeridian()->getGreenwichLongitude()->asRadians()->getValue();
80 15
        $h = $p / cos($latitude) - $v;
81
82 15
        return new GeographicValue(new Radian($latitude), new Radian($longitude), new Metre($h), $this->datum);
83
    }
84
}
85