|
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
|
|
|
public function __construct($lat, $lng, $height, RefEll $refEll) |
|
51
|
|
|
{ |
|
52
|
|
|
$this->lat = round($lat, 5); |
|
53
|
|
|
$this->lng = round($lng, 5); |
|
54
|
|
|
$this->h = round($height); |
|
55
|
|
|
$this->refEll = $refEll; |
|
56
|
|
|
} |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* Return a string representation of this LatLng object |
|
60
|
|
|
* @return string |
|
61
|
|
|
*/ |
|
62
|
|
|
public function __toString() |
|
63
|
|
|
{ |
|
64
|
|
|
return "({$this->lat}, {$this->lng})"; |
|
65
|
|
|
} |
|
66
|
|
|
|
|
67
|
|
|
/** |
|
68
|
|
|
* @return float |
|
69
|
|
|
*/ |
|
70
|
|
|
public function getLat() |
|
71
|
|
|
{ |
|
72
|
|
|
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
|
|
|
public function getLng() |
|
87
|
|
|
{ |
|
88
|
|
|
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
|
|
|
public function getH() |
|
103
|
|
|
{ |
|
104
|
|
|
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
|
|
|
public function getRefEll() |
|
120
|
|
|
{ |
|
121
|
|
|
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
|
|
|
public function distance(LatLng $to) |
|
142
|
|
|
{ |
|
143
|
|
|
|
|
144
|
|
|
if ($this->refEll != $to->refEll) { |
|
145
|
|
|
trigger_error('Source and destination co-ordinates are not using the same ellipsoid', E_USER_WARNING); |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
//Mean radius definition from taken from Wikipedia |
|
149
|
|
|
$er = ((2 * $this->refEll->getMaj()) + $this->refEll->getMin()) / 3; |
|
150
|
|
|
|
|
151
|
|
|
$latFrom = deg2rad($this->lat); |
|
152
|
|
|
$latTo = deg2rad($to->lat); |
|
153
|
|
|
$lngFrom = deg2rad($this->lng); |
|
154
|
|
|
$lngTo = deg2rad($to->lng); |
|
155
|
|
|
|
|
156
|
|
|
$d = acos(sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lngTo - $lngFrom)) * $er; |
|
157
|
|
|
|
|
158
|
|
|
return round($d, 5); |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
|
|
162
|
|
|
/** |
|
163
|
|
|
* Convert this LatLng object from OSGB36 datum to WGS84 datum. |
|
164
|
|
|
* Reference values for transformation are taken from OS document |
|
165
|
|
|
* "A Guide to Coordinate Systems in Great Britain" |
|
166
|
|
|
* @return void |
|
167
|
|
|
*/ |
|
168
|
|
View Code Duplication |
public function OSGB36ToWGS84() |
|
|
|
|
|
|
169
|
|
|
{ |
|
170
|
|
|
|
|
171
|
|
|
if ($this->refEll != RefEll::airy1830()) { |
|
172
|
|
|
trigger_error('Current co-ordinates are not using the Airy ellipsoid', E_USER_WARNING); |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
$wgs84 = RefEll::wgs84(); |
|
176
|
|
|
|
|
177
|
|
|
$tx = 446.448; |
|
178
|
|
|
$ty = -125.157; |
|
179
|
|
|
$tz = 542.060; |
|
180
|
|
|
$s = -0.0000204894; |
|
181
|
|
|
$rx = deg2rad(0.1502 / 3600); |
|
182
|
|
|
$ry = deg2rad(0.2470 / 3600); |
|
183
|
|
|
$rz = deg2rad(0.8421 / 3600); |
|
184
|
|
|
|
|
185
|
|
|
$this->transformDatum($wgs84, $tx, $ty, $tz, $s, $rx, $ry, $rz); |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
|
|
189
|
|
|
/** |
|
190
|
|
|
* Convert this LatLng object from WGS84 datum to OSGB36 datum. |
|
191
|
|
|
* Reference values for transformation are taken from OS document |
|
192
|
|
|
* "A Guide to Coordinate Systems in Great Britain" |
|
193
|
|
|
* @return void |
|
194
|
|
|
*/ |
|
195
|
|
View Code Duplication |
public function WGS84ToOSGB36() |
|
|
|
|
|
|
196
|
|
|
{ |
|
197
|
|
|
|
|
198
|
|
|
if ($this->refEll != RefEll::wgs84()) { |
|
199
|
|
|
trigger_error('Current co-ordinates are not using the WGS84 ellipsoid', E_USER_WARNING); |
|
200
|
|
|
} |
|
201
|
|
|
|
|
202
|
|
|
$airy1830 = RefEll::airy1830(); |
|
203
|
|
|
|
|
204
|
|
|
$tx = -446.448; |
|
205
|
|
|
$ty = 125.157; |
|
206
|
|
|
$tz = -542.060; |
|
207
|
|
|
$s = 0.0000204894; |
|
208
|
|
|
$rx = deg2rad(-0.1502 / 3600); |
|
209
|
|
|
$ry = deg2rad(-0.2470 / 3600); |
|
210
|
|
|
$rz = deg2rad(-0.8421 / 3600); |
|
211
|
|
|
|
|
212
|
|
|
$this->transformDatum($airy1830, $tx, $ty, $tz, $s, $rx, $ry, $rz); |
|
213
|
|
|
} |
|
214
|
|
|
|
|
215
|
|
|
/** |
|
216
|
|
|
* Convert this LatLng object from WGS84 datum to ED50 datum. |
|
217
|
|
|
* Reference values for transformation are taken from http://www.globalmapper.com/helpv9/datum_list.htm |
|
218
|
|
|
* @return void |
|
219
|
|
|
*/ |
|
220
|
|
View Code Duplication |
public function WGS84ToED50() |
|
|
|
|
|
|
221
|
|
|
{ |
|
222
|
|
|
|
|
223
|
|
|
if ($this->refEll != RefEll::wgs84()) { |
|
224
|
|
|
trigger_error('Current co-ordinates are not using the WGS84 ellipsoid', E_USER_WARNING); |
|
225
|
|
|
} |
|
226
|
|
|
|
|
227
|
|
|
$heyford1924 = RefEll::heyford1924(); |
|
228
|
|
|
|
|
229
|
|
|
$tx = 87; |
|
230
|
|
|
$ty = 98; |
|
231
|
|
|
$tz = 121; |
|
232
|
|
|
$s = 0; |
|
233
|
|
|
$rx = deg2rad(0); |
|
234
|
|
|
$ry = deg2rad(0); |
|
235
|
|
|
$rz = deg2rad(0); |
|
236
|
|
|
|
|
237
|
|
|
$this->transformDatum($heyford1924, $tx, $ty, $tz, $s, $rx, $ry, $rz); |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
/** |
|
241
|
|
|
* Convert this LatLng object from ED50 datum to WGS84 datum. |
|
242
|
|
|
* Reference values for transformation are taken from http://www.globalmapper.com/helpv9/datum_list.htm |
|
243
|
|
|
* @return void |
|
244
|
|
|
*/ |
|
245
|
|
View Code Duplication |
public function ED50ToWGS84() |
|
|
|
|
|
|
246
|
|
|
{ |
|
247
|
|
|
|
|
248
|
|
|
if ($this->refEll != RefEll::heyford1924()) { |
|
249
|
|
|
trigger_error('Current co-ordinates are not using the Heyford ellipsoid', E_USER_WARNING); |
|
250
|
|
|
} |
|
251
|
|
|
|
|
252
|
|
|
$wgs84 = RefEll::wgs84(); |
|
253
|
|
|
|
|
254
|
|
|
$tx = -87; |
|
255
|
|
|
$ty = -98; |
|
256
|
|
|
$tz = -121; |
|
257
|
|
|
$s = 0; |
|
258
|
|
|
$rx = deg2rad(0); |
|
259
|
|
|
$ry = deg2rad(0); |
|
260
|
|
|
$rz = deg2rad(0); |
|
261
|
|
|
|
|
262
|
|
|
$this->transformDatum($wgs84, $tx, $ty, $tz, $s, $rx, $ry, $rz); |
|
263
|
|
|
} |
|
264
|
|
|
|
|
265
|
|
|
/** |
|
266
|
|
|
* Convert this LatLng object from WGS84 datum to NAD27 datum. |
|
267
|
|
|
* Reference values for transformation are taken from Wikipedia |
|
268
|
|
|
* @return void |
|
269
|
|
|
*/ |
|
270
|
|
View Code Duplication |
public function WGS84ToNAD27() |
|
|
|
|
|
|
271
|
|
|
{ |
|
272
|
|
|
|
|
273
|
|
|
if ($this->refEll != RefEll::wgs84()) { |
|
274
|
|
|
trigger_error('Current co-ordinates are not using the WGS84 ellipsoid', E_USER_WARNING); |
|
275
|
|
|
} |
|
276
|
|
|
|
|
277
|
|
|
$clarke1866 = RefEll::clarke1866(); |
|
278
|
|
|
|
|
279
|
|
|
$tx = 8; |
|
280
|
|
|
$ty = -160; |
|
281
|
|
|
$tz = -176; |
|
282
|
|
|
$s = 0; |
|
283
|
|
|
$rx = deg2rad(0); |
|
284
|
|
|
$ry = deg2rad(0); |
|
285
|
|
|
$rz = deg2rad(0); |
|
286
|
|
|
|
|
287
|
|
|
$this->transformDatum($clarke1866, $tx, $ty, $tz, $s, $rx, $ry, $rz); |
|
288
|
|
|
} |
|
289
|
|
|
|
|
290
|
|
|
/** |
|
291
|
|
|
* Convert this LatLng object from NAD27 datum to WGS84 datum. |
|
292
|
|
|
* Reference values for transformation are taken from Wikipedia |
|
293
|
|
|
* @return void |
|
294
|
|
|
*/ |
|
295
|
|
View Code Duplication |
public function NAD27ToWGS84() |
|
|
|
|
|
|
296
|
|
|
{ |
|
297
|
|
|
|
|
298
|
|
|
if ($this->refEll != RefEll::clarke1866()) { |
|
299
|
|
|
trigger_error('Current co-ordinates are not using the Clarke ellipsoid', E_USER_WARNING); |
|
300
|
|
|
} |
|
301
|
|
|
|
|
302
|
|
|
$wgs84 = RefEll::wgs84(); |
|
303
|
|
|
|
|
304
|
|
|
$tx = -8; |
|
305
|
|
|
$ty = 160; |
|
306
|
|
|
$tz = 176; |
|
307
|
|
|
$s = 0; |
|
308
|
|
|
$rx = deg2rad(0); |
|
309
|
|
|
$ry = deg2rad(0); |
|
310
|
|
|
$rz = deg2rad(0); |
|
311
|
|
|
|
|
312
|
|
|
$this->transformDatum($wgs84, $tx, $ty, $tz, $s, $rx, $ry, $rz); |
|
313
|
|
|
} |
|
314
|
|
|
|
|
315
|
|
|
/** |
|
316
|
|
|
* Transform co-ordinates from one datum to another using a Helmert transformation |
|
317
|
|
|
* @param RefEll $toRefEll |
|
318
|
|
|
* @param float $tranX |
|
319
|
|
|
* @param float $tranY |
|
320
|
|
|
* @param float $tranZ |
|
321
|
|
|
* @param float $scale |
|
322
|
|
|
* @param float $rotX rotation about x-axis in seconds |
|
323
|
|
|
* @param float $rotY rotation about y-axis in seconds |
|
324
|
|
|
* @param float $rotZ rotation about z-axis in seconds |
|
325
|
|
|
* @return mixed |
|
326
|
|
|
*/ |
|
327
|
|
|
public function transformDatum(RefEll $toRefEll, $tranX, $tranY, $tranZ, $scale, $rotX, $rotY, $rotZ) |
|
328
|
|
|
{ |
|
329
|
|
|
|
|
330
|
|
|
$cartesian = Cartesian::fromLatLong($this); |
|
331
|
|
|
$cartesian->transformDatum($toRefEll, $tranX, $tranY, $tranZ, $scale, $rotX, $rotY, $rotZ); |
|
332
|
|
|
$newLatLng = $cartesian->toLatitudeLongitude(); |
|
333
|
|
|
|
|
334
|
|
|
$this->lat = $newLatLng->getLat(); |
|
335
|
|
|
$this->lng = $newLatLng->getLng(); |
|
336
|
|
|
$this->h = $newLatLng->getH(); |
|
337
|
|
|
$this->refEll = $newLatLng->getRefEll(); |
|
338
|
|
|
} |
|
339
|
|
|
|
|
340
|
|
|
|
|
341
|
|
|
/** |
|
342
|
|
|
* Convert this LatLng object into an OSGB grid reference. Note that this |
|
343
|
|
|
* function does not take into account the bounds of the OSGB grid - |
|
344
|
|
|
* beyond the bounds of the OSGB grid, the resulting OSRef object has no |
|
345
|
|
|
* meaning |
|
346
|
|
|
* |
|
347
|
|
|
* Reference values for transformation are taken from OS document |
|
348
|
|
|
* "A Guide to Coordinate Systems in Great Britain" |
|
349
|
|
|
* |
|
350
|
|
|
* @return OSRef |
|
351
|
|
|
*/ |
|
352
|
|
|
public function toOSRef() |
|
353
|
|
|
{ |
|
354
|
|
|
|
|
355
|
|
|
if ($this->refEll != RefEll::airy1830()) { |
|
356
|
|
|
trigger_error('Current co-ordinates are in a non-OSGB datum', E_USER_WARNING); |
|
357
|
|
|
} |
|
358
|
|
|
|
|
359
|
|
|
$OSGB = new OSRef(0, 0); //dummy to get reference data |
|
360
|
|
|
$scale = $OSGB->getScaleFactor(); |
|
361
|
|
|
$N0 = $OSGB->getOriginNorthing(); |
|
362
|
|
|
$E0 = $OSGB->getOriginEasting(); |
|
363
|
|
|
$phi0 = $OSGB->getOriginLatitude(); |
|
364
|
|
|
$lambda0 = $OSGB->getOriginLongitude(); |
|
365
|
|
|
|
|
366
|
|
|
$coords = $this->toTransverseMercatorEastingNorthing($scale, $E0, $N0, $phi0, $lambda0); |
|
367
|
|
|
|
|
368
|
|
|
return new OSRef(round($coords['E']), round($coords['N'])); |
|
369
|
|
|
} |
|
370
|
|
|
|
|
371
|
|
|
|
|
372
|
|
|
/** |
|
373
|
|
|
* Convert a WGS84 latitude and longitude to an UTM reference |
|
374
|
|
|
* |
|
375
|
|
|
* Reference values for transformation are taken from OS document |
|
376
|
|
|
* "A Guide to Coordinate Systems in Great Britain" |
|
377
|
|
|
* @return UTMRef |
|
378
|
|
|
*/ |
|
379
|
|
|
public function toUTMRef() |
|
380
|
|
|
{ |
|
381
|
|
|
|
|
382
|
|
|
if ($this->refEll != RefEll::wgs84()) { |
|
383
|
|
|
trigger_error('Current co-ordinates are in a non-WGS84 datum', E_USER_WARNING); |
|
384
|
|
|
} |
|
385
|
|
|
|
|
386
|
|
|
$longitudeZone = (int)(($this->lng + 180) / 6) + 1; |
|
387
|
|
|
|
|
388
|
|
|
// Special zone for Norway |
|
389
|
|
View Code Duplication |
if ($this->lat >= 56 && $this->lat < 64 && $this->lng >= 3 && $this->lng < 12) { |
|
|
|
|
|
|
390
|
|
|
$longitudeZone = 32; |
|
391
|
|
|
} |
|
392
|
|
|
|
|
393
|
|
|
// Special zones for Svalbard |
|
394
|
|
|
if ($this->lat >= 72 && $this->lat < 84) { |
|
395
|
|
|
if ($this->lng >= 0 && $this->lng < 9) { |
|
396
|
|
|
$longitudeZone = 31; |
|
397
|
|
|
} else { |
|
398
|
|
|
if ($this->lng >= 9 && $this->lng < 21) { |
|
399
|
|
|
$longitudeZone = 33; |
|
400
|
|
View Code Duplication |
} else { |
|
|
|
|
|
|
401
|
|
|
if ($this->lng >= 21 && $this->lng < 33) { |
|
402
|
|
|
$longitudeZone = 35; |
|
403
|
|
|
} else { |
|
404
|
|
|
if ($this->lng >= 33 && $this->lng < 42) { |
|
405
|
|
|
$longitudeZone = 37; |
|
406
|
|
|
} |
|
407
|
|
|
} |
|
408
|
|
|
} |
|
409
|
|
|
} |
|
410
|
|
|
} |
|
411
|
|
|
|
|
412
|
|
|
$UTMZone = $this->getUTMLatitudeZoneLetter($this->lat); |
|
413
|
|
|
|
|
414
|
|
|
$UTM = new UTMRef(0, 0, $UTMZone, $longitudeZone); //dummy to get reference data |
|
415
|
|
|
$scale = $UTM->getScaleFactor(); |
|
416
|
|
|
$N0 = $UTM->getOriginNorthing(); |
|
417
|
|
|
$E0 = $UTM->getOriginEasting(); |
|
418
|
|
|
$phi0 = $UTM->getOriginLatitude(); |
|
419
|
|
|
$lambda0 = $UTM->getOriginLongitude(); |
|
420
|
|
|
|
|
421
|
|
|
$coords = $this->toTransverseMercatorEastingNorthing($scale, $E0, $N0, $phi0, $lambda0); |
|
422
|
|
|
|
|
423
|
|
|
if ($this->lat < 0) { |
|
424
|
|
|
$coords['N'] += 10000000; |
|
425
|
|
|
} |
|
426
|
|
|
|
|
427
|
|
|
return new UTMRef(round($coords['E']), round($coords['N']), $UTMZone, $longitudeZone); |
|
428
|
|
|
} |
|
429
|
|
|
|
|
430
|
|
|
/** |
|
431
|
|
|
* Work out the UTM latitude zone from the latitude |
|
432
|
|
|
* @param float $latitude |
|
433
|
|
|
* @return string |
|
434
|
|
|
*/ |
|
435
|
|
|
private function getUTMLatitudeZoneLetter($latitude) |
|
436
|
|
|
{ |
|
437
|
|
|
|
|
438
|
|
|
if ($latitude < -80 || $latitude > 84) { |
|
439
|
|
|
throw new \OutOfRangeException('UTM zones do not apply in polar regions'); |
|
440
|
|
|
} |
|
441
|
|
|
|
|
442
|
|
|
$zones = "CDEFGHJKLMNPQRSTUVWXX"; |
|
443
|
|
|
$zoneIndex = (int)(($latitude + 80) / 8); |
|
444
|
|
|
return $zones[$zoneIndex]; |
|
445
|
|
|
} |
|
446
|
|
|
|
|
447
|
|
|
|
|
448
|
|
|
/** |
|
449
|
|
|
* Convert a latitude and longitude to easting and northing using a Transverse Mercator projection |
|
450
|
|
|
* Formula for transformation is taken from OS document |
|
451
|
|
|
* "A Guide to Coordinate Systems in Great Britain" |
|
452
|
|
|
* |
|
453
|
|
|
* @param float $scale scale factor on central meridian |
|
454
|
|
|
* @param float $originEasting easting of true origin |
|
455
|
|
|
* @param float $originNorthing northing of true origin |
|
456
|
|
|
* @param float $originLat latitude of true origin |
|
457
|
|
|
* @param float $originLong longitude of true origin |
|
458
|
|
|
* @return array |
|
459
|
|
|
*/ |
|
460
|
|
|
public function toTransverseMercatorEastingNorthing( |
|
461
|
|
|
$scale, |
|
462
|
|
|
$originEasting, |
|
463
|
|
|
$originNorthing, |
|
464
|
|
|
$originLat, |
|
465
|
|
|
$originLong |
|
466
|
|
|
) { |
|
467
|
|
|
|
|
468
|
|
|
$originLat = deg2rad($originLat); |
|
469
|
|
|
$originLong = deg2rad($originLong); |
|
470
|
|
|
|
|
471
|
|
|
$lat = deg2rad($this->lat); |
|
472
|
|
|
$sinLat = sin($lat); |
|
473
|
|
|
$cosLat = cos($lat); |
|
474
|
|
|
$tanLat = tan($lat); |
|
475
|
|
|
$tanLatSq = pow($tanLat, 2); |
|
476
|
|
|
$long = deg2rad($this->lng); |
|
477
|
|
|
|
|
478
|
|
|
$n = ($this->refEll->getMaj() - $this->refEll->getMin()) / ($this->refEll->getMaj() + $this->refEll->getMin()); |
|
479
|
|
|
$nSq = pow($n, 2); |
|
480
|
|
|
$nCu = pow($n, 3); |
|
481
|
|
|
|
|
482
|
|
|
$v = $this->refEll->getMaj() * $scale * pow(1 - $this->refEll->getEcc() * pow($sinLat, 2), -0.5); |
|
483
|
|
|
$p = $this->refEll->getMaj() * $scale * (1 - $this->refEll->getEcc()) * pow(1 - $this->refEll->getEcc() * pow($sinLat, 2), -1.5); |
|
484
|
|
|
$hSq = (($v / $p) - 1); |
|
485
|
|
|
|
|
486
|
|
|
$latPlusOrigin = $lat + $originLat; |
|
487
|
|
|
$latMinusOrigin = $lat - $originLat; |
|
488
|
|
|
|
|
489
|
|
|
$longMinusOrigin = $long - $originLong; |
|
490
|
|
|
|
|
491
|
|
|
$M = $this->refEll->getMin() * $scale |
|
492
|
|
|
* ((1 + $n + 1.25 * ($nSq + $nCu)) * $latMinusOrigin |
|
493
|
|
|
- (3 * ($n + $nSq) + 2.625 * $nCu) * sin($latMinusOrigin) * cos($latPlusOrigin) |
|
494
|
|
|
+ 1.875 * ($nSq + $nCu) * sin(2 * $latMinusOrigin) * cos(2 * $latPlusOrigin) |
|
495
|
|
|
- (35 / 24 * $nCu * sin(3 * $latMinusOrigin) * cos(3 * $latPlusOrigin))); |
|
496
|
|
|
|
|
497
|
|
|
$I = $M + $originNorthing; |
|
498
|
|
|
$II = $v / 2 * $sinLat * $cosLat; |
|
499
|
|
|
$III = $v / 24 * $sinLat * pow($cosLat, 3) * (5 - $tanLatSq + 9 * $hSq); |
|
500
|
|
|
$IIIA = $v / 720 * $sinLat * pow($cosLat, 5) * (61 - 58 * $tanLatSq + pow($tanLatSq, 2)); |
|
501
|
|
|
$IV = $v * $cosLat; |
|
502
|
|
|
$V = $v / 6 * pow($cosLat, 3) * ($v / $p - $tanLatSq); |
|
503
|
|
|
$VI = $v / 120 * pow($cosLat, 5) * (5 - 18 * $tanLatSq + pow($tanLatSq, 2) + 14 * $hSq - 58 * $tanLatSq * $hSq); |
|
504
|
|
|
|
|
505
|
|
|
$E = $originEasting + $IV * $longMinusOrigin + $V * pow($longMinusOrigin, 3) + $VI * pow($longMinusOrigin, 5); |
|
506
|
|
|
$N = $I + $II * pow($longMinusOrigin, 2) + $III * pow($longMinusOrigin, 4) + $IIIA * pow($longMinusOrigin, 6); |
|
507
|
|
|
|
|
508
|
|
|
return array('E' => $E, 'N' => $N); |
|
509
|
|
|
} |
|
510
|
|
|
} |
|
511
|
|
|
|
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.