Completed
Push — master ( 3821b5...87ff99 )
by Doug
07:12
created

Cartesian::transformDatum()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 8
nc 1
nop 8
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * PHPCoord
4
 * @package PHPCoord
5
 * @author Doug Wright
6
 */
7
namespace PHPCoord;
8
9
/**
10
 * ECEF Cartesian coordinate
11
 * @author Doug Wright
12
 * @package PHPCoord
13
 */
14
class Cartesian
15
{
16
17
    /**
18
     * X
19
     * @var float
20
     */
21
    protected $x;
22
23
    /**
24
     * Y
25
     * @var float
26
     */
27
    protected $y;
28
29
    /**
30
     * Z
31
     * @var float
32
     */
33
    protected $z;
34
35
    /**
36
     * Reference ellipsoid used in this datum
37
     * @var RefEll
38
     */
39
    protected $refEll;
40
41
    /**
42
     * Cartesian constructor.
43
     * @param float $x
44
     * @param float $y
45
     * @param float $z
46
     * @param RefEll $refEll
47
     */
48 13
    public function __construct($x, $y, $z, RefEll $refEll)
49
    {
50 13
        $this->setX($x);
51 13
        $this->setY($y);
52 13
        $this->setZ($z);
53 13
        $this->setRefEll($refEll);
54 13
    }
55
56
    /**
57
     * String version of coordinate.
58
     * @return string
59
     */
60 1
    public function __toString()
61
    {
62 1
        return "({$this->x}, {$this->y}, {$this->z})";
63
    }
64
65
    /**
66
     * @return float
67
     */
68 12
    public function getX()
69
    {
70 12
        return $this->x;
71
    }
72
73
    /**
74
     * @param float $x
75
     */
76 13
    public function setX($x)
77
    {
78 13
        $this->x = $x;
79 13
    }
80
81
    /**
82
     * @return float
83
     */
84 12
    public function getY()
85
    {
86 12
        return $this->y;
87
    }
88
89
    /**
90
     * @param float $y
91
     */
92 13
    public function setY($y)
93
    {
94 13
        $this->y = $y;
95 13
    }
96
97
    /**
98
     * @return float
99
     */
100 11
    public function getZ()
101
    {
102 11
        return $this->z;
103
    }
104
105
    /**
106
     * @param float $z
107
     */
108 13
    public function setZ($z)
109
    {
110 13
        $this->z = $z;
111 13
    }
112
113
    /**
114
     * @return RefEll
115
     */
116 1
    public function getRefEll()
117
    {
118 1
        return $this->refEll;
119
    }
120
121
    /**
122
     * @param RefEll $refEll
123
     */
124 13
    public function setRefEll($refEll)
125
    {
126 13
        $this->refEll = $refEll;
127 13
    }
128
129
    /**
130
     * Convert these coordinates into a latitude, longitude
131
     * Formula for transformation is taken from OS document
132
     * "A Guide to Coordinate Systems in Great Britain"
133
     *
134
     * @return LatLng
135
     */
136 9
    public function toLatitudeLongitude()
137
    {
138
139 9
        $lambda = rad2deg(atan2($this->y, $this->x));
140
141 9
        $p = sqrt(pow($this->x, 2) + pow($this->y, 2));
142
143 9
        $phi = atan($this->z / ($p * (1 - $this->refEll->getEcc())));
144
145
        do {
146 9
            $phi1 = $phi;
147 9
            $v = $this->refEll->getMaj() / (sqrt(1 - $this->refEll->getEcc() * pow(sin($phi), 2)));
148 9
            $phi = atan(($this->z + ($this->refEll->getEcc() * $v * sin($phi))) / $p);
149 9
        } while (abs($phi - $phi1) >= 0.00001);
150
151 9
        $h = $p / cos($phi) - $v;
152
153 9
        $phi = rad2deg($phi);
154
155 9
        return new LatLng($phi, $lambda, $h, $this->refEll);
156
    }
157
158
    /**
159
     * Convert a latitude, longitude height to x, y, z
160
     * Formula for transformation is taken from OS document
161
     * "A Guide to Coordinate Systems in Great Britain"
162
     *
163
     * @param LatLng $latLng
164
     * @return Cartesian
165
     */
166 9
    public static function fromLatLong(LatLng $latLng)
167
    {
168
169 9
        $a = $latLng->getRefEll()->getMaj();
170 9
        $eSquared = $latLng->getRefEll()->getEcc();
171 9
        $phi = deg2rad($latLng->getLat());
172 9
        $lambda = deg2rad($latLng->getLng());
173
174 9
        $v = $a / (sqrt(1 - $eSquared * pow(sin($phi), 2)));
175 9
        $x = ($v + $latLng->getH()) * cos($phi) * cos($lambda);
176 9
        $y = ($v + $latLng->getH()) * cos($phi) * sin($lambda);
177 9
        $z = ((1 - $eSquared) * $v + $latLng->getH()) * sin($phi);
178
179 9
        return new static($x, $y, $z, $latLng->getRefEll());
180
    }
181
182
    /**
183
     * Transform the datum used for these coordinates by using a Helmert Transform
184
     * @param RefEll $toRefEll
185
     * @param float $tranX
186
     * @param float $tranY
187
     * @param float $tranZ
188
     * @param float $scale
189
     * @param float $rotX  rotation about x-axis in radians
190
     * @param float $rotY  rotation about y-axis in radians
191
     * @param float $rotZ  rotation about z-axis in radians
192
     * @return mixed
193
     */
194 10
    public function transformDatum(RefEll $toRefEll, $tranX, $tranY, $tranZ, $scale, $rotX, $rotY, $rotZ)
195
    {
196
197 10
        $x = $tranX + ($this->getX() * (1 + $scale)) - ($this->getY() * $rotZ) + ($this->getZ() * $rotY);
198 10
        $y = $tranY + ($this->getX() * $rotZ) + ($this->getY() * (1 + $scale)) - ($this->getZ() * $rotX);
199 10
        $z = $tranZ - ($this->getX() * $rotY) + ($this->getY() * $rotX) + ($this->getZ() * (1 + $scale));
200
201 10
        $this->setX($x);
202 10
        $this->setY($y);
203 10
        $this->setZ($z);
204 10
        $this->setRefEll($toRefEll);
205 10
    }
206
207
    /**
208
     * Calculate the surface distance between this object and the one
209
     * passed in as a parameter.
210
     *
211
     * @param self $to object to measure the distance to
0 ignored issues
show
Documentation introduced by
Should the type for parameter $to not be \self?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
212
     * @return float
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
213
     */
214 1
    public function distance(self $to) {
215
216 1
        if ($this->refEll != $to->refEll) {
217
            throw new \RuntimeException('Source and destination co-ordinates are not using the same ellipsoid');
218
        }
219
220
        //Because this is a 2D grid, we can use simple Pythagoras
221 1
        $distanceX = $to->getX()-$this->getX();
222 1
        $distanceY = $to->getY()-$this->getY();
223
224 1
        return pow(pow($distanceX, 2) + pow($distanceY, 2), 0.5);
225
226
    }
227
228
}
229