1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* PHPCoord |
4
|
|
|
* @package PHPCoord |
5
|
|
|
* @author Jonathan Stott |
6
|
|
|
* @author Doug Wright |
7
|
|
|
*/ |
8
|
|
|
namespace PHPCoord; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Latitude/Longitude reference |
12
|
|
|
* @author Jonathan Stott |
13
|
|
|
* @author Doug Wright |
14
|
|
|
* @package PHPCoord |
15
|
|
|
*/ |
16
|
|
|
class LatLng |
17
|
|
|
{ |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Latitude |
21
|
|
|
* @var float |
22
|
|
|
*/ |
23
|
|
|
protected $lat; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Longitude |
27
|
|
|
* @var float |
28
|
|
|
*/ |
29
|
|
|
protected $lng; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Height |
33
|
|
|
* @var float |
34
|
|
|
*/ |
35
|
|
|
protected $h; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Reference ellipsoid the co-ordinates are from |
39
|
|
|
* @var RefEll |
40
|
|
|
*/ |
41
|
|
|
protected $refEll; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Create a new LatLng object from the given latitude and longitude |
45
|
|
|
* @param float $lat |
46
|
|
|
* @param float $lng |
47
|
|
|
* @param float $height |
48
|
|
|
* @param RefEll $refEll |
49
|
|
|
*/ |
50
|
30 |
|
public function __construct($lat, $lng, $height, RefEll $refEll) |
51
|
|
|
{ |
52
|
30 |
|
$this->lat = round($lat, 5); |
53
|
30 |
|
$this->lng = round($lng, 5); |
54
|
30 |
|
$this->h = round($height); |
55
|
30 |
|
$this->refEll = $refEll; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Return a string representation of this LatLng object |
60
|
|
|
* @return string |
61
|
|
|
*/ |
62
|
13 |
|
public function __toString() |
63
|
|
|
{ |
64
|
13 |
|
return "({$this->lat}, {$this->lng})"; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @return float |
69
|
|
|
*/ |
70
|
15 |
|
public function getLat() |
71
|
|
|
{ |
72
|
15 |
|
return $this->lat; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* @param float $lat |
77
|
|
|
*/ |
78
|
|
|
public function setLat($lat) |
79
|
|
|
{ |
80
|
|
|
$this->lat = $lat; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* @return float |
85
|
|
|
*/ |
86
|
15 |
|
public function getLng() |
87
|
|
|
{ |
88
|
15 |
|
return $this->lng; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @param float $lng |
93
|
|
|
*/ |
94
|
|
|
public function setLng($lng) |
95
|
|
|
{ |
96
|
|
|
$this->lng = $lng; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* @return float |
101
|
|
|
*/ |
102
|
9 |
|
public function getH() |
103
|
|
|
{ |
104
|
9 |
|
return $this->h; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param float $h |
109
|
|
|
*/ |
110
|
|
|
public function setH($h) |
111
|
|
|
{ |
112
|
|
|
$this->h = $h; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* @return RefEll |
118
|
|
|
*/ |
119
|
9 |
|
public function getRefEll() |
120
|
|
|
{ |
121
|
9 |
|
return $this->refEll; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* @param RefEll $refEll |
126
|
|
|
*/ |
127
|
|
|
public function setRefEll(RefEll $refEll) |
128
|
|
|
{ |
129
|
|
|
$this->refEll = $refEll; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
|
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Calculate the surface distance between this LatLng object and the one |
136
|
|
|
* passed in as a parameter. |
137
|
|
|
* |
138
|
|
|
* @param LatLng $to a LatLng object to measure the surface distance to |
139
|
|
|
* @return float |
140
|
|
|
*/ |
141
|
2 |
|
public function distance(LatLng $to) |
142
|
|
|
{ |
143
|
2 |
|
if ($this->refEll != $to->refEll) { |
144
|
1 |
|
throw new \RuntimeException('Source and destination co-ordinates are not using the same ellipsoid'); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
//Mean radius definition from taken from Wikipedia |
148
|
1 |
|
$er = ((2 * $this->refEll->getMaj()) + $this->refEll->getMin()) / 3; |
149
|
|
|
|
150
|
1 |
|
$latFrom = deg2rad($this->lat); |
151
|
1 |
|
$latTo = deg2rad($to->lat); |
152
|
1 |
|
$lngFrom = deg2rad($this->lng); |
153
|
1 |
|
$lngTo = deg2rad($to->lng); |
154
|
|
|
|
155
|
1 |
|
$d = acos(sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lngTo - $lngFrom)) * $er; |
156
|
|
|
|
157
|
1 |
|
return round($d, 5); |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Convert this LatLng object to OSGB36 datum. |
163
|
|
|
* Reference values for transformation are taken from OS document |
164
|
|
|
* "A Guide to Coordinate Systems in Great Britain" |
165
|
|
|
* @return void |
166
|
|
|
*/ |
167
|
4 |
|
public function toOSGB36() |
|
|
|
|
168
|
|
|
{ |
169
|
4 |
|
if ($this->refEll == RefEll::airy1830()) { |
170
|
2 |
|
return; |
171
|
|
|
} |
172
|
|
|
|
173
|
2 |
|
$this->toWGS84(); |
174
|
|
|
|
175
|
1 |
|
$tx = -446.448; |
176
|
1 |
|
$ty = 125.157; |
177
|
1 |
|
$tz = -542.060; |
178
|
1 |
|
$s = 0.0000204894; |
179
|
1 |
|
$rx = deg2rad(-0.1502 / 3600); |
180
|
1 |
|
$ry = deg2rad(-0.2470 / 3600); |
181
|
1 |
|
$rz = deg2rad(-0.8421 / 3600); |
182
|
|
|
|
183
|
1 |
|
$this->transformDatum(RefEll::airy1830(), $tx, $ty, $tz, $s, $rx, $ry, $rz); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Convert this LatLng object to ED50 datum. |
188
|
|
|
* Reference values for transformation are taken from http://www.globalmapper.com/helpv9/datum_list.htm |
189
|
|
|
* @return void |
190
|
|
|
*/ |
191
|
1 |
|
public function toED50() |
|
|
|
|
192
|
|
|
{ |
193
|
1 |
|
if ($this->refEll == RefEll::international1924()) { |
194
|
|
|
return; |
195
|
|
|
} |
196
|
|
|
|
197
|
1 |
|
$this->toWGS84(); |
198
|
|
|
|
199
|
1 |
|
$tx = 87; |
200
|
1 |
|
$ty = 98; |
201
|
1 |
|
$tz = 121; |
202
|
1 |
|
$s = 0; |
203
|
1 |
|
$rx = deg2rad(0); |
204
|
1 |
|
$ry = deg2rad(0); |
205
|
1 |
|
$rz = deg2rad(0); |
206
|
|
|
|
207
|
1 |
|
$this->transformDatum(RefEll::international1924(), $tx, $ty, $tz, $s, $rx, $ry, $rz); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* Convert this LatLng object to NAD27 datum. |
212
|
|
|
* Reference values for transformation are taken from Wikipedia |
213
|
|
|
* @return void |
214
|
|
|
*/ |
215
|
1 |
|
public function toNAD27() |
|
|
|
|
216
|
|
|
{ |
217
|
1 |
|
if ($this->refEll == RefEll::clarke1866()) { |
218
|
|
|
return; |
219
|
|
|
} |
220
|
|
|
|
221
|
1 |
|
$this->toWGS84(); |
222
|
|
|
|
223
|
1 |
|
$tx = 8; |
224
|
1 |
|
$ty = -160; |
225
|
1 |
|
$tz = -176; |
226
|
1 |
|
$s = 0; |
227
|
1 |
|
$rx = deg2rad(0); |
228
|
1 |
|
$ry = deg2rad(0); |
229
|
1 |
|
$rz = deg2rad(0); |
230
|
|
|
|
231
|
1 |
|
$this->transformDatum(RefEll::clarke1866(), $tx, $ty, $tz, $s, $rx, $ry, $rz); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* Convert this LatLng object to Ireland 1975 datum. |
236
|
|
|
* Reference values for transformation are taken from OSI document |
237
|
|
|
* "Making maps compatible with GPS" |
238
|
|
|
* @return void |
239
|
|
|
*/ |
240
|
1 |
|
public function toIreland1975() |
|
|
|
|
241
|
|
|
{ |
242
|
1 |
|
if ($this->refEll == RefEll::airyModified()) { |
243
|
|
|
return; |
244
|
|
|
} |
245
|
|
|
|
246
|
1 |
|
$this->toWGS84(); |
247
|
|
|
|
248
|
1 |
|
$tx = -482.530; |
249
|
1 |
|
$ty = 130.596; |
250
|
1 |
|
$tz = -564.557; |
251
|
1 |
|
$s = -0.00000815; |
252
|
1 |
|
$rx = deg2rad(-1.042 / 3600); |
253
|
1 |
|
$ry = deg2rad(-0.214 / 3600); |
254
|
1 |
|
$rz = deg2rad(-0.631 / 3600); |
255
|
|
|
|
256
|
1 |
|
$this->transformDatum(RefEll::airyModified(), $tx, $ty, $tz, $s, $rx, $ry, $rz); |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* Convert this LatLng object to WGS84 datum |
261
|
|
|
* @return void |
262
|
|
|
*/ |
263
|
14 |
|
public function toWGS84() { |
264
|
|
|
|
265
|
14 |
|
switch ($this->refEll) { |
266
|
|
|
|
267
|
14 |
|
case RefEll::wgs84(): |
268
|
8 |
|
return; //do nothing |
269
|
|
|
|
270
|
7 |
|
case RefEll::airy1830(): // values from OSGB document "A Guide to Coordinate Systems in Great Britain" |
271
|
2 |
|
$tx = 446.448; |
272
|
2 |
|
$ty = -125.157; |
273
|
2 |
|
$tz = 542.060; |
274
|
2 |
|
$s = -0.0000204894; |
275
|
2 |
|
$rx = deg2rad(0.1502 / 3600); |
276
|
2 |
|
$ry = deg2rad(0.2470 / 3600); |
277
|
2 |
|
$rz = deg2rad(0.8421 / 3600); |
278
|
2 |
|
break; |
279
|
|
|
|
280
|
5 |
|
case RefEll::airyModified(): // values from OSI document "Making maps compatible with GPS" |
281
|
1 |
|
$tx = 482.530; |
282
|
1 |
|
$ty = -130.596; |
283
|
1 |
|
$tz = 564.557; |
284
|
1 |
|
$s = 0.00000815; |
285
|
1 |
|
$rx = deg2rad(1.042 / 3600); |
286
|
1 |
|
$ry = deg2rad(0.214 / 3600); |
287
|
1 |
|
$rz = deg2rad(0.631 / 3600); |
288
|
1 |
|
break; |
289
|
|
|
|
290
|
4 |
View Code Duplication |
case RefEll::clarke1866(): // assumes NAD27, values from Wikipedia |
|
|
|
|
291
|
1 |
|
$tx = -8; |
292
|
1 |
|
$ty = 160; |
293
|
1 |
|
$tz = 176; |
294
|
1 |
|
$s = 0; |
295
|
1 |
|
$rx = deg2rad(0); |
296
|
1 |
|
$ry = deg2rad(0); |
297
|
1 |
|
$rz = deg2rad(0); |
298
|
1 |
|
break; |
299
|
|
|
|
300
|
3 |
View Code Duplication |
case RefEll::international1924(): // assumes ED50, values from http://www.globalmapper.com/helpv9/datum_list.htm |
|
|
|
|
301
|
1 |
|
$tx = -87; |
302
|
1 |
|
$ty = -98; |
303
|
1 |
|
$tz = -121; |
304
|
1 |
|
$s = 0; |
305
|
1 |
|
$rx = deg2rad(0); |
306
|
1 |
|
$ry = deg2rad(0); |
307
|
1 |
|
$rz = deg2rad(0); |
308
|
1 |
|
break; |
309
|
|
|
|
310
|
2 |
|
case RefEll::bessel1841(): // assumes Germany, values from Wikipedia |
311
|
|
|
$tx = 582; |
312
|
|
|
$ty = -105; |
313
|
|
|
$tz = -414; |
314
|
|
|
$s = 0.0000083; |
315
|
|
|
$rx = deg2rad(1.04 / 3600); |
316
|
|
|
$ry = deg2rad(0.35 / 3600); |
317
|
|
|
$rz = deg2rad(-3.08 / 3600); |
318
|
|
|
break; |
319
|
|
|
|
320
|
|
|
default: |
321
|
2 |
|
throw new \RuntimeException('Transform parameters not known for this ellipsoid'); |
322
|
|
|
} |
323
|
|
|
|
324
|
5 |
|
$this->transformDatum(RefEll::wgs84(), $tx, $ty, $tz, $s, $rx, $ry, $rz); |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
/** |
328
|
|
|
* Transform co-ordinates from one datum to another using a Helmert transformation |
329
|
|
|
* @param RefEll $toRefEll |
330
|
|
|
* @param float $tranX |
331
|
|
|
* @param float $tranY |
332
|
|
|
* @param float $tranZ |
333
|
|
|
* @param float $scale |
334
|
|
|
* @param float $rotX rotation about x-axis in seconds |
335
|
|
|
* @param float $rotY rotation about y-axis in seconds |
336
|
|
|
* @param float $rotZ rotation about z-axis in seconds |
337
|
|
|
* @return mixed |
338
|
|
|
*/ |
339
|
15 |
|
public function transformDatum(RefEll $toRefEll, $tranX, $tranY, $tranZ, $scale, $rotX, $rotY, $rotZ) |
340
|
|
|
{ |
341
|
|
|
|
342
|
15 |
|
if ($this->refEll == $toRefEll) { |
343
|
6 |
|
return; |
344
|
|
|
} |
345
|
|
|
|
346
|
9 |
|
$cartesian = Cartesian::fromLatLong($this); |
347
|
9 |
|
$cartesian->transformDatum($toRefEll, $tranX, $tranY, $tranZ, $scale, $rotX, $rotY, $rotZ); |
348
|
9 |
|
$newLatLng = $cartesian->toLatitudeLongitude(); |
349
|
|
|
|
350
|
9 |
|
$this->lat = $newLatLng->getLat(); |
351
|
9 |
|
$this->lng = $newLatLng->getLng(); |
352
|
9 |
|
$this->h = $newLatLng->getH(); |
353
|
9 |
|
$this->refEll = $newLatLng->getRefEll(); |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
|
357
|
|
|
/** |
358
|
|
|
* Convert this LatLng object into an OSGB grid reference. Note that this |
359
|
|
|
* function does not take into account the bounds of the OSGB grid - |
360
|
|
|
* beyond the bounds of the OSGB grid, the resulting OSRef object has no |
361
|
|
|
* meaning |
362
|
|
|
* |
363
|
|
|
* Reference values for transformation are taken from OS document |
364
|
|
|
* "A Guide to Coordinate Systems in Great Britain" |
365
|
|
|
* |
366
|
|
|
* @return OSRef |
367
|
|
|
*/ |
368
|
3 |
View Code Duplication |
public function toOSRef() |
|
|
|
|
369
|
|
|
{ |
370
|
3 |
|
$this->toOSGB36(); |
371
|
|
|
|
372
|
2 |
|
$OSGB = new OSRef(0, 0); //dummy to get reference data |
373
|
2 |
|
$scale = $OSGB->getScaleFactor(); |
374
|
2 |
|
$N0 = $OSGB->getOriginNorthing(); |
375
|
2 |
|
$E0 = $OSGB->getOriginEasting(); |
376
|
2 |
|
$phi0 = $OSGB->getOriginLatitude(); |
377
|
2 |
|
$lambda0 = $OSGB->getOriginLongitude(); |
378
|
|
|
|
379
|
2 |
|
$coords = $this->toTransverseMercatorEastingNorthing($scale, $E0, $N0, $phi0, $lambda0); |
380
|
|
|
|
381
|
2 |
|
return new OSRef(round($coords['E']), round($coords['N']), $this->h); |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* Convert this LatLng object into an ITM grid reference |
386
|
|
|
* |
387
|
|
|
* @return ITMRef |
388
|
|
|
*/ |
389
|
|
View Code Duplication |
public function toITMRef() |
|
|
|
|
390
|
|
|
{ |
391
|
|
|
$this->toWGS84(); |
392
|
|
|
|
393
|
|
|
$ITM = new ITMRef(0, 0); //dummy to get reference data |
394
|
|
|
$scale = $ITM->getScaleFactor(); |
395
|
|
|
$N0 = $ITM->getOriginNorthing(); |
396
|
|
|
$E0 = $ITM->getOriginEasting(); |
397
|
|
|
$phi0 = $ITM->getOriginLatitude(); |
398
|
|
|
$lambda0 = $ITM->getOriginLongitude(); |
399
|
|
|
|
400
|
|
|
$coords = $this->toTransverseMercatorEastingNorthing($scale, $E0, $N0, $phi0, $lambda0); |
401
|
|
|
|
402
|
|
|
return new ITMRef(round($coords['E']), round($coords['N']), $this->h); |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
|
406
|
|
|
/** |
407
|
|
|
* Convert a WGS84 latitude and longitude to an UTM reference |
408
|
|
|
* |
409
|
|
|
* Reference values for transformation are taken from OS document |
410
|
|
|
* "A Guide to Coordinate Systems in Great Britain" |
411
|
|
|
* @return UTMRef |
412
|
|
|
*/ |
413
|
4 |
|
public function toUTMRef() |
414
|
|
|
{ |
415
|
4 |
|
$this->toWGS84(); |
416
|
|
|
|
417
|
4 |
|
$longitudeZone = (int)(($this->lng + 180) / 6) + 1; |
418
|
|
|
|
419
|
|
|
// Special zone for Norway |
420
|
4 |
|
if ($this->lat >= 56 && $this->lat < 64 && $this->lng >= 3 && $this->lng < 12) { |
421
|
|
|
$longitudeZone = 32; |
422
|
4 |
|
} elseif ($this->lat >= 72 && $this->lat < 84) { // Special zones for Svalbard |
423
|
|
|
if ($this->lng >= 0 && $this->lng < 9) { |
424
|
|
|
$longitudeZone = 31; |
425
|
|
|
} elseif ($this->lng >= 9 && $this->lng < 21) { |
426
|
|
|
$longitudeZone = 33; |
427
|
|
|
} elseif ($this->lng >= 21 && $this->lng < 33) { |
428
|
|
|
$longitudeZone = 35; |
429
|
|
|
} elseif ($this->lng >= 33 && $this->lng < 42) { |
430
|
|
|
$longitudeZone = 37; |
431
|
|
|
} |
432
|
|
|
} |
433
|
|
|
|
434
|
4 |
|
$UTMZone = $this->getUTMLatitudeZoneLetter($this->lat); |
435
|
|
|
|
436
|
2 |
|
$UTM = new UTMRef(0, 0, 0, $UTMZone, $longitudeZone); //dummy to get reference data |
437
|
2 |
|
$scale = $UTM->getScaleFactor(); |
438
|
2 |
|
$N0 = $UTM->getOriginNorthing(); |
439
|
2 |
|
$E0 = $UTM->getOriginEasting(); |
440
|
2 |
|
$phi0 = $UTM->getOriginLatitude(); |
441
|
2 |
|
$lambda0 = $UTM->getOriginLongitude(); |
442
|
|
|
|
443
|
2 |
|
$coords = $this->toTransverseMercatorEastingNorthing($scale, $E0, $N0, $phi0, $lambda0); |
444
|
|
|
|
445
|
2 |
|
if ($this->lat < 0) { |
446
|
1 |
|
$coords['N'] += 10000000; |
447
|
|
|
} |
448
|
|
|
|
449
|
2 |
|
return new UTMRef(round($coords['E']), round($coords['N']), $this->h, $UTMZone, $longitudeZone); |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
/** |
453
|
|
|
* Work out the UTM latitude zone from the latitude |
454
|
|
|
* @param float $latitude |
455
|
|
|
* @return string |
456
|
|
|
*/ |
457
|
4 |
|
private function getUTMLatitudeZoneLetter($latitude) |
458
|
|
|
{ |
459
|
|
|
|
460
|
4 |
|
if ($latitude < -80 || $latitude > 84) { |
461
|
2 |
|
throw new \OutOfRangeException('UTM zones do not apply in polar regions'); |
462
|
|
|
} |
463
|
|
|
|
464
|
2 |
|
$zones = "CDEFGHJKLMNPQRSTUVWXX"; |
465
|
2 |
|
$zoneIndex = (int)(($latitude + 80) / 8); |
466
|
2 |
|
return $zones[$zoneIndex]; |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
|
470
|
|
|
/** |
471
|
|
|
* Convert a latitude and longitude to easting and northing using a Transverse Mercator projection |
472
|
|
|
* Formula for transformation is taken from OS document |
473
|
|
|
* "A Guide to Coordinate Systems in Great Britain" |
474
|
|
|
* |
475
|
|
|
* @param float $scale scale factor on central meridian |
476
|
|
|
* @param float $originEasting easting of true origin |
477
|
|
|
* @param float $originNorthing northing of true origin |
478
|
|
|
* @param float $originLat latitude of true origin |
479
|
|
|
* @param float $originLong longitude of true origin |
480
|
|
|
* @return array |
|
|
|
|
481
|
|
|
*/ |
482
|
4 |
|
public function toTransverseMercatorEastingNorthing( |
483
|
|
|
$scale, |
484
|
|
|
$originEasting, |
485
|
|
|
$originNorthing, |
486
|
|
|
$originLat, |
487
|
|
|
$originLong |
488
|
|
|
) { |
489
|
|
|
|
490
|
4 |
|
$originLat = deg2rad($originLat); |
491
|
4 |
|
$originLong = deg2rad($originLong); |
492
|
|
|
|
493
|
4 |
|
$lat = deg2rad($this->lat); |
494
|
4 |
|
$sinLat = sin($lat); |
495
|
4 |
|
$cosLat = cos($lat); |
496
|
4 |
|
$tanLat = tan($lat); |
497
|
4 |
|
$tanLatSq = pow($tanLat, 2); |
498
|
4 |
|
$long = deg2rad($this->lng); |
499
|
|
|
|
500
|
4 |
|
$n = ($this->refEll->getMaj() - $this->refEll->getMin()) / ($this->refEll->getMaj() + $this->refEll->getMin()); |
501
|
4 |
|
$nSq = pow($n, 2); |
502
|
4 |
|
$nCu = pow($n, 3); |
503
|
|
|
|
504
|
4 |
|
$v = $this->refEll->getMaj() * $scale * pow(1 - $this->refEll->getEcc() * pow($sinLat, 2), -0.5); |
505
|
4 |
|
$p = $this->refEll->getMaj() * $scale * (1 - $this->refEll->getEcc()) * pow(1 - $this->refEll->getEcc() * pow($sinLat, 2), -1.5); |
506
|
4 |
|
$hSq = (($v / $p) - 1); |
507
|
|
|
|
508
|
4 |
|
$latPlusOrigin = $lat + $originLat; |
509
|
4 |
|
$latMinusOrigin = $lat - $originLat; |
510
|
|
|
|
511
|
4 |
|
$longMinusOrigin = $long - $originLong; |
512
|
|
|
|
513
|
4 |
|
$M = $this->refEll->getMin() * $scale |
514
|
4 |
|
* ((1 + $n + 1.25 * ($nSq + $nCu)) * $latMinusOrigin |
515
|
4 |
|
- (3 * ($n + $nSq) + 2.625 * $nCu) * sin($latMinusOrigin) * cos($latPlusOrigin) |
516
|
4 |
|
+ 1.875 * ($nSq + $nCu) * sin(2 * $latMinusOrigin) * cos(2 * $latPlusOrigin) |
517
|
4 |
|
- (35 / 24 * $nCu * sin(3 * $latMinusOrigin) * cos(3 * $latPlusOrigin))); |
518
|
|
|
|
519
|
4 |
|
$I = $M + $originNorthing; |
520
|
4 |
|
$II = $v / 2 * $sinLat * $cosLat; |
521
|
4 |
|
$III = $v / 24 * $sinLat * pow($cosLat, 3) * (5 - $tanLatSq + 9 * $hSq); |
522
|
4 |
|
$IIIA = $v / 720 * $sinLat * pow($cosLat, 5) * (61 - 58 * $tanLatSq + pow($tanLatSq, 2)); |
523
|
4 |
|
$IV = $v * $cosLat; |
524
|
4 |
|
$V = $v / 6 * pow($cosLat, 3) * ($v / $p - $tanLatSq); |
525
|
4 |
|
$VI = $v / 120 * pow($cosLat, 5) * (5 - 18 * $tanLatSq + pow($tanLatSq, 2) + 14 * $hSq - 58 * $tanLatSq * $hSq); |
526
|
|
|
|
527
|
4 |
|
$E = $originEasting + $IV * $longMinusOrigin + $V * pow($longMinusOrigin, 3) + $VI * pow($longMinusOrigin, 5); |
528
|
4 |
|
$N = $I + $II * pow($longMinusOrigin, 2) + $III * pow($longMinusOrigin, 4) + $IIIA * pow($longMinusOrigin, 6); |
529
|
|
|
|
530
|
4 |
|
return array('E' => $E, 'N' => $N); |
531
|
|
|
} |
532
|
|
|
} |
533
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.