Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 779 lines (677 sloc) 24.184 kb
4dacc45 @pezholio First commit
authored
1 <?php
2
3 //--------------------------------------------------------------------------
4 // PHPcoord
5 // phpcoord.php
6 //
7 // (c) 2005 Jonathan Stott
8 //
9 // Created on 11-Aug-2005
10 //
11 // 2.3 - 24 Aug 2006
12 // - Changed OSRef->toSixFigureString() so that the eastings and northings
13 // are rounded rather than floored.
14 // 2.2 - 11 Feb 2006
15 // - Used different algorithm for calculating distance between latitudes
16 // and longitudes - fixes a number of problems with distance calculations
17 // 2.1 - 22 Dec 2005
18 // - Added getOSRefFromSixFigureReference function
19 // 2.0 - 21 Dec 2005
20 // - Completely different object design - conversion functions now through
21 // objects rather than static functions
22 // - Updated comments and documentation
23 // 1.1 - 11 Sep 2005
24 // - Added OSGB36/WGS84 data conversions
25 // 1.0 - 11 Aug 2005
26 // - Initial version
27 //--------------------------------------------------------------------------
28
29
30 // ================================================================== LatLng
31
32 class LatLng {
33
34 var $lat;
35 var $lng;
36
37
38 /**
39 * Create a new LatLng object from the given latitude and longitude
40 *
41 * @param lat latitude
42 * @param lng longitude
43 */
44 function LatLng($lat, $lng) {
45 $this->lat = $lat;
46 $this->lng = $lng;
47 }
48
49
50 /**
51 * Return a string representation of this LatLng object
52 *
53 * @return a string representation of this LatLng object
54 */
55 function toString() {
56 return "(" . $this->lat . ", " . $this->lng . ")";
57 }
58
59
60 /**
61 * Calculate the surface distance between this LatLng object and the one
62 * passed in as a parameter.
63 *
64 * @param to a LatLng object to measure the surface distance to
65 * @return the surface distance
66 */
67 function distance($to) {
68 $er = 6366.707;
69
70 $latFrom = deg2rad($this->lat);
71 $latTo = deg2rad($to->lat);
72 $lngFrom = deg2rad($this->lng);
73 $lngTo = deg2rad($to->lng);
74
75 $x1 = $er * cos($lngFrom) * sin($latFrom);
76 $y1 = $er * sin($lngFrom) * sin($latFrom);
77 $z1 = $er * cos($latFrom);
78
79 $x2 = $er * cos($lngTo) * sin($latTo);
80 $y2 = $er * sin($lngTo) * sin($latTo);
81 $z2 = $er * cos($latTo);
82
83 $d = acos(sin($latFrom)*sin($latTo) + cos($latFrom)*cos($latTo)*cos($lngTo-$lngFrom)) * $er;
84
85 return $d;
86 }
87
88
89 /**
90 * Convert this LatLng object from OSGB36 datum to WGS84 datum.
91 */
92 function OSGB36ToWGS84() {
93 $airy1830 = new RefEll(6377563.396, 6356256.909);
94 $a = $airy1830->maj;
95 $b = $airy1830->min;
96 $eSquared = $airy1830->ecc;
97 $phi = deg2rad($this->lat);
98 $lambda = deg2rad($this->lng);
99 $v = $a / (sqrt(1 - $eSquared * sinSquared($phi)));
100 $H = 0; // height
101 $x = ($v + $H) * cos($phi) * cos($lambda);
102 $y = ($v + $H) * cos($phi) * sin($lambda);
103 $z = ((1 - $eSquared) * $v + $H) * sin($phi);
104
105 $tx = 446.448;
106 $ty = -124.157;
107 $tz = 542.060;
108 $s = -0.0000204894;
109 $rx = deg2rad( 0.00004172222);
110 $ry = deg2rad( 0.00006861111);
111 $rz = deg2rad( 0.00023391666);
112
113 $xB = $tx + ($x * (1 + $s)) + (-$rx * $y) + ($ry * $z);
114 $yB = $ty + ($rz * $x) + ($y * (1 + $s)) + (-$rx * $z);
115 $zB = $tz + (-$ry * $x) + ($rx * $y) + ($z * (1 + $s));
116
117 $wgs84 = new RefEll(6378137.000, 6356752.3141);
118 $a = $wgs84->maj;
119 $b = $wgs84->min;
120 $eSquared = $wgs84->ecc;
121
122 $lambdaB = rad2deg(atan($yB / $xB));
123 $p = sqrt(($xB * $xB) + ($yB * $yB));
124 $phiN = atan($zB / ($p * (1 - $eSquared)));
125 for ($i = 1; $i < 10; $i++) {
126 $v = $a / (sqrt(1 - $eSquared * sinSquared($phiN)));
127 $phiN1 = atan(($zB + ($eSquared * $v * sin($phiN))) / $p);
128 $phiN = $phiN1;
129 }
130
131 $phiB = rad2deg($phiN);
132
133 $this->lat = $phiB;
134 $this->lng = $lambdaB;
135 }
136
137
138 /**
139 * Convert this LatLng object from WGS84 datum to OSGB36 datum.
140 */
141 function WGS84ToOSGB36() {
142 $wgs84 = new RefEll(6378137.000, 6356752.3141);
143 $a = $wgs84->maj;
144 $b = $wgs84->min;
145 $eSquared = $wgs84->ecc;
146 $phi = deg2rad($this->lat);
147 $lambda = deg2rad($this->lng);
148 $v = $a / (sqrt(1 - $eSquared * sinSquared($phi)));
149 $H = 0; // height
150 $x = ($v + $H) * cos($phi) * cos($lambda);
151 $y = ($v + $H) * cos($phi) * sin($lambda);
152 $z = ((1 - $eSquared) * $v + $H) * sin($phi);
153
154 $tx = -446.448;
155 $ty = 124.157;
156 $tz = -542.060;
157 $s = 0.0000204894;
158 $rx = deg2rad(-0.00004172222);
159 $ry = deg2rad(-0.00006861111);
160 $rz = deg2rad(-0.00023391666);
161
162 $xB = $tx + ($x * (1 + $s)) + (-$rx * $y) + ($ry * $z);
163 $yB = $ty + ($rz * $x) + ($y * (1 + $s)) + (-$rx * $z);
164 $zB = $tz + (-$ry * $x) + ($rx * $y) + ($z * (1 + $s));
165
166 $airy1830 = new RefEll(6377563.396, 6356256.909);
167 $a = $airy1830->maj;
168 $b = $airy1830->min;
169 $eSquared = $airy1830->ecc;
170
171 $lambdaB = rad2deg(atan($yB / $xB));
172 $p = sqrt(($xB * $xB) + ($yB * $yB));
173 $phiN = atan($zB / ($p * (1 - $eSquared)));
174 for ($i = 1; $i < 10; $i++) {
175 $v = $a / (sqrt(1 - $eSquared * sinSquared($phiN)));
176 $phiN1 = atan(($zB + ($eSquared * $v * sin($phiN))) / $p);
177 $phiN = $phiN1;
178 }
179
180 $phiB = rad2deg($phiN);
181
182 $this->lat = $phiB;
183 $this->lng = $lambdaB;
184 }
185
186
187 /**
188 * Convert this LatLng object into an OSGB grid reference. Note that this
189 * function does not take into account the bounds of the OSGB grid -
190 * beyond the bounds of the OSGB grid, the resulting OSRef object has no
191 * meaning
192 *
193 * @return the converted OSGB grid reference
194 */
195 function toOSRef() {
196 $airy1830 = new RefEll(6377563.396, 6356256.909);
197 $OSGB_F0 = 0.9996012717;
198 $N0 = -100000.0;
199 $E0 = 400000.0;
200 $phi0 = deg2rad(49.0);
201 $lambda0 = deg2rad(-2.0);
202 $a = $airy1830->maj;
203 $b = $airy1830->min;
204 $eSquared = $airy1830->ecc;
205 $phi = deg2rad($this->lat);
206 $lambda = deg2rad($this->lng);
207 $E = 0.0;
208 $N = 0.0;
209 $n = ($a - $b) / ($a + $b);
210 $v = $a * $OSGB_F0 * pow(1.0 - $eSquared * sinSquared($phi), -0.5);
211 $rho =
212 $a * $OSGB_F0 * (1.0 - $eSquared) * pow(1.0 - $eSquared * sinSquared($phi), -1.5);
213 $etaSquared = ($v / $rho) - 1.0;
214 $M =
215 ($b * $OSGB_F0)
216 * (((1 + $n + ((5.0 / 4.0) * $n * $n) + ((5.0 / 4.0) * $n * $n * $n))
217 * ($phi - $phi0))
218 - (((3 * $n) + (3 * $n * $n) + ((21.0 / 8.0) * $n * $n * $n))
219 * sin($phi - $phi0)
220 * cos($phi + $phi0))
221 + ((((15.0 / 8.0) * $n * $n) + ((15.0 / 8.0) * $n * $n * $n))
222 * sin(2.0 * ($phi - $phi0))
223 * cos(2.0 * ($phi + $phi0)))
224 - (((35.0 / 24.0) * $n * $n * $n)
225 * sin(3.0 * ($phi - $phi0))
226 * cos(3.0 * ($phi + $phi0))));
227 $I = $M + $N0;
228 $II = ($v / 2.0) * sin($phi) * cos($phi);
229 $III =
230 ($v / 24.0)
231 * sin($phi)
232 * pow(cos($phi), 3.0)
233 * (5.0 - tanSquared($phi) + (9.0 * $etaSquared));
234 $IIIA =
235 ($v / 720.0)
236 * sin($phi)
237 * pow(cos($phi), 5.0)
238 * (61.0 - (58.0 * tanSquared($phi)) + pow(tan($phi), 4.0));
239 $IV = $v * cos($phi);
240 $V = ($v / 6.0) * pow(cos($phi), 3.0) * (($v / $rho) - tanSquared($phi));
241 $VI =
242 ($v / 120.0)
243 * pow(cos($phi), 5.0)
244 * (5.0
245 - (18.0 * tanSquared($phi))
246 + (pow(tan($phi), 4.0))
247 + (14 * $etaSquared)
248 - (58 * tanSquared($phi) * $etaSquared));
249
250 $N =
251 $I
252 + ($II * pow($lambda - $lambda0, 2.0))
253 + ($III * pow($lambda - $lambda0, 4.0))
254 + ($IIIA * pow($lambda - $lambda0, 6.0));
255 $E =
256 $E0
257 + ($IV * ($lambda - $lambda0))
258 + ($V * pow($lambda - $lambda0, 3.0))
259 + ($VI * pow($lambda - $lambda0, 5.0));
260
261 return new OSRef($E, $N);
262 }
263
264
265 /**
266 * Convert a latitude and longitude to an UTM reference
267 *
268 * @return the converted UTM reference
269 */
270 function toUTMRef() {
271 $wgs84 = new RefEll(6378137, 6356752.314);
272 $UTM_F0 = 0.9996;
273 $a = $wgs84->maj;
274 $eSquared = $wgs84->ecc;
275 $longitude = $this->lng;
276 $latitude = $this->lat;
277
278 $latitudeRad = $latitude * (pi() / 180.0);
279 $longitudeRad = $longitude * (pi() / 180.0);
280 $longitudeZone = (int) (($longitude + 180.0) / 6.0) + 1;
281
282 // Special zone for Norway
283 if ($latitude >= 56.0
284 && $latitude < 64.0
285 && $longitude >= 3.0
286 && $longitude < 12.0) {
287 $longitudeZone = 32;
288 }
289
290 // Special zones for Svalbard
291 if ($latitude >= 72.0 && $latitude < 84.0) {
292 if ($longitude >= 0.0 && $longitude < 9.0) {
293 $longitudeZone = 31;
294 } else if ($longitude >= 9.0 && $longitude < 21.0) {
295 $longitudeZone = 33;
296 } else if ($longitude >= 21.0 && $longitude < 33.0) {
297 $longitudeZone = 35;
298 } else if ($longitude >= 33.0 && $longitude < 42.0) {
299 $longitudeZone = 37;
300 }
301 }
302
303 $longitudeOrigin = ($longitudeZone - 1) * 6 - 180 + 3;
304 $longitudeOriginRad = $longitudeOrigin * (pi() / 180.0);
305
306 $UTMZone = getUTMLatitudeZoneLetter($latitude);
307
308 $ePrimeSquared = ($eSquared) / (1 - $eSquared);
309
310 $n = $a / sqrt(1 - $eSquared * sin($latitudeRad) * sin($latitudeRad));
311 $t = tan($latitudeRad) * tan($latitudeRad);
312 $c = $ePrimeSquared * cos($latitudeRad) * cos($latitudeRad);
313 $A = cos($latitudeRad) * ($longitudeRad - $longitudeOriginRad);
314
315 $M =
316 $a
317 * ((1
318 - $eSquared / 4
319 - 3 * $eSquared * $eSquared / 64
320 - 5 * $eSquared * $eSquared * $eSquared / 256)
321 * $latitudeRad
322 - (3 * $eSquared / 8
323 + 3 * $eSquared * $eSquared / 32
324 + 45 * $eSquared * $eSquared * $eSquared / 1024)
325 * sin(2 * $latitudeRad)
326 + (15 * $eSquared * $eSquared / 256
327 + 45 * $eSquared * $eSquared * $eSquared / 1024)
328 * sin(4 * $latitudeRad)
329 - (35 * $eSquared * $eSquared * $eSquared / 3072)
330 * sin(6 * $latitudeRad));
331
332 $UTMEasting =
333 (double) ($UTM_F0
334 * $n
335 * ($A
336 + (1 - $t + $c) * pow($A, 3.0) / 6
337 + (5 - 18 * $t + $t * $t + 72 * $c - 58 * $ePrimeSquared)
338 * pow($A, 5.0)
339 / 120)
340 + 500000.0);
341
342 $UTMNorthing =
343 (double) ($UTM_F0
344 * ($M
345 + $n
346 * tan($latitudeRad)
347 * ($A * $A / 2
348 + (5 - $t + (9 * $c) + (4 * $c * $c)) * pow($A, 4.0) / 24
349 + (61 - (58 * $t) + ($t * $t) + (600 * $c) - (330 * $ePrimeSquared))
350 * pow($A, 6.0)
351 / 720)));
352
353 // Adjust for the southern hemisphere
354 if ($latitude < 0) {
355 $UTMNorthing += 10000000.0;
356 }
357
358 return new UTMRef($UTMEasting, $UTMNorthing, $UTMZone, $longitudeZone);
359 }
360 }
361
362
363 // =================================================================== OSRef
364
365 // References given with OSRef are accurate to 1m.
366 class OSRef {
367
368 var $easting;
369 var $northing;
370
371
372 /**
373 * Create a new OSRef object representing an OSGB grid reference. Note
374 * that the parameters for this constructor require eastings and
375 * northings with 1m accuracy and need to be absolute with respect to
376 * the whole of the British Grid. For example, to create an OSRef
377 * object from the six-figure grid reference TG514131, the easting would
378 * be 651400 and the northing would be 313100.
379 *
380 * Grid references with accuracy greater than 1m can be represented
381 * using floating point values for the easting and northing. For example,
382 * a value representing an easting or northing accurate to 1mm would be
383 * given as 651400.0001.
384 *
385 * @param easting the easting of the reference (with 1m accuracy)
386 * @param northing the northing of the reference (with 1m accuracy)
387 */
388 function OSRef($easting, $northing) {
389 $this->easting = $easting;
390 $this->northing = $northing;
391 }
392
393
394 /**
395 * Convert this grid reference into a string showing the exact values
396 * of the easting and northing.
397 *
398 * @return
399 */
400 function toString() {
401 return "(" . $this->easting . ", " . $this->northing . ")";
402 }
403
404 function toSplitString() {
405 $result['easting'] = $this->easting;
406 $result['northing'] = $this->northing;
407 return $result;
408 }
409
410
411 /**
412 * Convert this grid reference into a string using a standard six-figure
413 * grid reference including the two-character designation for the 100km
414 * square. e.g. TG514131.
415 *
416 * @return
417 */
418 function toSixFigureString() {
419 $hundredkmE = floor($this->easting / 100000);
420 $hundredkmN = floor($this->northing / 100000);
421 $firstLetter = "";
422 if ($hundredkmN < 5) {
423 if ($hundredkmE < 5) {
424 $firstLetter = "S";
425 } else {
426 $firstLetter = "T";
427 }
428 } else if ($hundredkmN < 10) {
429 if ($hundredkmE < 5) {
430 $firstLetter = "N";
431 } else {
432 $firstLetter = "O";
433 }
434 } else {
435 $firstLetter = "H";
436 }
437
438 $secondLetter = "";
439 $index = 65 + ((4 - ($hundredkmN % 5)) * 5) + ($hundredkmE % 5);
440 $ti = $index;
441 if ($index >= 73) $index++;
442 $secondLetter = chr($index);
443
444 $e = round(($this->easting - (100000 * $hundredkmE)) / 100);
445 $n = round(($this->northing - (100000 * $hundredkmN)) / 100);
446
447 return sprintf("%s%s%03d%03d", $firstLetter, $secondLetter, $e, $n);
448 }
449
450
451 /**
452 * Convert this grid reference into a latitude and longitude
453 *
454 * @return
455 */
456 function toLatLng() {
457 $airy1830 = new RefEll(6377563.396, 6356256.909);
458 $OSGB_F0 = 0.9996012717;
459 $N0 = -100000.0;
460 $E0 = 400000.0;
461 $phi0 = deg2rad(49.0);
462 $lambda0 = deg2rad(-2.0);
463 $a = $airy1830->maj;
464 $b = $airy1830->min;
465 $eSquared = $airy1830->ecc;
466 $phi = 0.0;
467 $lambda = 0.0;
468 $E = $this->easting;
469 $N = $this->northing;
470 $n = ($a - $b) / ($a + $b);
471 $M = 0.0;
472 $phiPrime = (($N - $N0) / ($a * $OSGB_F0)) + $phi0;
473 do {
474 $M =
475 ($b * $OSGB_F0)
476 * (((1 + $n + ((5.0 / 4.0) * $n * $n) + ((5.0 / 4.0) * $n * $n * $n))
477 * ($phiPrime - $phi0))
478 - (((3 * $n) + (3 * $n * $n) + ((21.0 / 8.0) * $n * $n * $n))
479 * sin($phiPrime - $phi0)
480 * cos($phiPrime + $phi0))
481 + ((((15.0 / 8.0) * $n * $n) + ((15.0 / 8.0) * $n * $n * $n))
482 * sin(2.0 * ($phiPrime - $phi0))
483 * cos(2.0 * ($phiPrime + $phi0)))
484 - (((35.0 / 24.0) * $n * $n * $n)
485 * sin(3.0 * ($phiPrime - $phi0))
486 * cos(3.0 * ($phiPrime + $phi0))));
487 $phiPrime += ($N - $N0 - $M) / ($a * $OSGB_F0);
488 } while (($N - $N0 - $M) >= 0.001);
489 $v = $a * $OSGB_F0 * pow(1.0 - $eSquared * sinSquared($phiPrime), -0.5);
490 $rho =
491 $a
492 * $OSGB_F0
493 * (1.0 - $eSquared)
494 * pow(1.0 - $eSquared * sinSquared($phiPrime), -1.5);
495 $etaSquared = ($v / $rho) - 1.0;
496 $VII = tan($phiPrime) / (2 * $rho * $v);
497 $VIII =
498 (tan($phiPrime) / (24.0 * $rho * pow($v, 3.0)))
499 * (5.0
500 + (3.0 * tanSquared($phiPrime))
501 + $etaSquared
502 - (9.0 * tanSquared($phiPrime) * $etaSquared));
503 $IX =
504 (tan($phiPrime) / (720.0 * $rho * pow($v, 5.0)))
505 * (61.0
506 + (90.0 * tanSquared($phiPrime))
507 + (45.0 * tanSquared($phiPrime) * tanSquared($phiPrime)));
508 $X = sec($phiPrime) / $v;
509 $XI =
510 (sec($phiPrime) / (6.0 * $v * $v * $v))
511 * (($v / $rho) + (2 * tanSquared($phiPrime)));
512 $XII =
513 (sec($phiPrime) / (120.0 * pow($v, 5.0)))
514 * (5.0
515 + (28.0 * tanSquared($phiPrime))
516 + (24.0 * tanSquared($phiPrime) * tanSquared($phiPrime)));
517 $XIIA =
518 (sec($phiPrime) / (5040.0 * pow($v, 7.0)))
519 * (61.0
520 + (662.0 * tanSquared($phiPrime))
521 + (1320.0 * tanSquared($phiPrime) * tanSquared($phiPrime))
522 + (720.0
523 * tanSquared($phiPrime)
524 * tanSquared($phiPrime)
525 * tanSquared($phiPrime)));
526 $phi =
527 $phiPrime
528 - ($VII * pow($E - $E0, 2.0))
529 + ($VIII * pow($E - $E0, 4.0))
530 - ($IX * pow($E - $E0, 6.0));
531 $lambda =
532 $lambda0
533 + ($X * ($E - $E0))
534 - ($XI * pow($E - $E0, 3.0))
535 + ($XII * pow($E - $E0, 5.0))
536 - ($XIIA * pow($E - $E0, 7.0));
537
538 return new LatLng(rad2deg($phi), rad2deg($lambda));
539 }
540 }
541
542
543 // ================================================================== UTMRef
544
545 class UTMRef {
546
547 var $easting;
548 var $northing;
549 var $latZone;
550 var $lngZone;
551
552
553 /**
554 * Create a new object representing a UTM reference.
555 *
556 * @param easting
557 * @param northing
558 * @param latZone
559 * @param lngZone
560 */
561 function UTMRef($easting, $northing, $latZone, $lngZone) {
562 $this->easting = $easting;
563 $this->northing = $northing;
564 $this->latZone = $latZone;
565 $this->lngZone = $lngZone;
566 }
567
568
569 /**
570 * Return a string representation of this UTM reference
571 *
572 * @return
573 */
574 function toString() {
575 return $this->lngZone . $this->latZone . " " .
576 $this->easting . " " . $this->northing;
577 }
578
579
580 /**
581 * Convert this UTM reference to a latitude and longitude
582 *
583 * @return the converted latitude and longitude
584 */
585 function toLatLng() {
586 $wgs84 = new RefEll(6378137, 6356752.314);
587 $UTM_F0 = 0.9996;
588 $a = $wgs84->maj;
589 $eSquared = $wgs84->ecc;
590 $ePrimeSquared = $eSquared / (1.0 - $eSquared);
591 $e1 = (1 - sqrt(1 - $eSquared)) / (1 + sqrt(1 - $eSquared));
592 $x = $this->easting - 500000.0;;
593 $y = $this->northing;
594 $zoneNumber = $this->lngZone;
595 $zoneLetter = $this->latZone;
596
597 $longitudeOrigin = ($zoneNumber - 1.0) * 6.0 - 180.0 + 3.0;
598
599 // Correct y for southern hemisphere
600 if ((ord($zoneLetter) - ord("N")) < 0) {
601 $y -= 10000000.0;
602 }
603
604 $m = $y / $UTM_F0;
605 $mu =
606 $m
607 / ($a
608 * (1.0
609 - $eSquared / 4.0
610 - 3.0 * $eSquared * $eSquared / 64.0
611 - 5.0
612 * pow($eSquared, 3.0)
613 / 256.0));
614
615 $phi1Rad =
616 $mu
617 + (3.0 * $e1 / 2.0 - 27.0 * pow($e1, 3.0) / 32.0) * sin(2.0 * $mu)
618 + (21.0 * $e1 * $e1 / 16.0 - 55.0 * pow($e1, 4.0) / 32.0)
619 * sin(4.0 * $mu)
620 + (151.0 * pow($e1, 3.0) / 96.0) * sin(6.0 * $mu);
621
622 $n =
623 $a
624 / sqrt(1.0 - $eSquared * sin($phi1Rad) * sin($phi1Rad));
625 $t = tan($phi1Rad) * tan($phi1Rad);
626 $c = $ePrimeSquared * cos($phi1Rad) * cos($phi1Rad);
627 $r =
628 $a
629 * (1.0 - $eSquared)
630 / pow(
631 1.0 - $eSquared * sin($phi1Rad) * sin($phi1Rad),
632 1.5);
633 $d = $x / ($n * $UTM_F0);
634
635 $latitude = (
636 $phi1Rad
637 - ($n * tan($phi1Rad) / $r)
638 * ($d * $d / 2.0
639 - (5.0
640 + (3.0 * $t)
641 + (10.0 * $c)
642 - (4.0 * $c * $c)
643 - (9.0 * $ePrimeSquared))
644 * pow($d, 4.0)
645 / 24.0
646 + (61.0
647 + (90.0 * $t)
648 + (298.0 * $c)
649 + (45.0 * $t * $t)
650 - (252.0 * $ePrimeSquared)
651 - (3.0 * $c * $c))
652 * pow($d, 6.0)
653 / 720.0)) * (180.0 / pi());
654
655 $longitude = $longitudeOrigin + (
656 ($d
657 - (1.0 + 2.0 * $t + $c) * pow($d, 3.0) / 6.0
658 + (5.0
659 - (2.0 * $c)
660 + (28.0 * $t)
661 - (3.0 * $c * $c)
662 + (8.0 * $ePrimeSquared)
663 + (24.0 * $t * $t))
664 * pow($d, 5.0)
665 / 120.0)
666 / cos($phi1Rad)) * (180.0 / pi());
667
668 return new LatLng($latitude, $longitude);
669 }
670 }
671
672
673 // ================================================================== RefEll
674
675 class RefEll {
676
677 var $maj;
678 var $min;
679 var $ecc;
680
681
682 /**
683 * Create a new RefEll object to represent a reference ellipsoid
684 *
685 * @param maj the major axis
686 * @param min the minor axis
687 */
688 function RefEll($maj, $min) {
689 $this->maj = $maj;
690 $this->min = $min;
691 $this->ecc = (($maj * $maj) - ($min * $min)) / ($maj * $maj);
692 }
693 }
694
695
696 // ================================================== Mathematical Functions
697
698 function sinSquared($x) {
699 return sin($x) * sin($x);
700 }
701
702 function cosSquared($x) {
703 return cos($x) * cos($x);
704 }
705
706 function tanSquared($x) {
707 return tan($x) * tan($x);
708 }
709
710 function sec($x) {
711 return 1.0 / cos($x);
712 }
713
714
715 /**
716 * Take a string formatted as a six-figure OS grid reference (e.g.
717 * "TG514131") and return a reference to an OSRef object that represents
718 * that grid reference. The first character must be H, N, S, O or T.
719 * The second character can be any uppercase character from A through Z
720 * excluding I.
721 *
722 * @param ref
723 * @return
724 * @since 2.1
725 */
726 function getOSRefFromSixFigureReference($ref) {
727 $char1 = substr($ref, 0, 1);
728 $char2 = substr($ref, 1, 1);
729 $east = substr($ref, 2, 3) * 100;
730 $north = substr($ref, 5, 3) * 100;
731 if ($char1 == 'H') {
732 $north += 1000000;
733 } else if ($char1 == 'N') {
734 $north += 500000;
735 } else if ($char1 == 'O') {
736 $north += 500000;
737 $east += 500000;
738 } else if ($char1 == 'T') {
739 $east += 500000;
740 }
741 $char2ord = ord($char2);
742 if ($char2ord > 73) $char2ord--; // Adjust for no I
743 $nx = (($char2ord - 65) % 5) * 100000;
744 $ny = (4 - floor(($char2ord - 65) / 5)) * 100000;
745 return new OSRef($east + $nx, $north + $ny);
746 }
747
748
749 /**
750 * Work out the UTM latitude zone from the latitude
751 *
752 * @param latitude
753 * @return
754 */
755 function getUTMLatitudeZoneLetter($latitude) {
756 if ((84 >= $latitude) && ($latitude >= 72)) return "X";
757 else if (( 72 > $latitude) && ($latitude >= 64)) return "W";
758 else if (( 64 > $latitude) && ($latitude >= 56)) return "V";
759 else if (( 56 > $latitude) && ($latitude >= 48)) return "U";
760 else if (( 48 > $latitude) && ($latitude >= 40)) return "T";
761 else if (( 40 > $latitude) && ($latitude >= 32)) return "S";
762 else if (( 32 > $latitude) && ($latitude >= 24)) return "R";
763 else if (( 24 > $latitude) && ($latitude >= 16)) return "Q";
764 else if (( 16 > $latitude) && ($latitude >= 8)) return "P";
765 else if (( 8 > $latitude) && ($latitude >= 0)) return "N";
766 else if (( 0 > $latitude) && ($latitude >= -8)) return "M";
767 else if (( -8 > $latitude) && ($latitude >= -16)) return "L";
768 else if ((-16 > $latitude) && ($latitude >= -24)) return "K";
769 else if ((-24 > $latitude) && ($latitude >= -32)) return "J";
770 else if ((-32 > $latitude) && ($latitude >= -40)) return "H";
771 else if ((-40 > $latitude) && ($latitude >= -48)) return "G";
772 else if ((-48 > $latitude) && ($latitude >= -56)) return "F";
773 else if ((-56 > $latitude) && ($latitude >= -64)) return "E";
774 else if ((-64 > $latitude) && ($latitude >= -72)) return "D";
775 else if ((-72 > $latitude) && ($latitude >= -80)) return "C";
776 else return 'Z';
777 }
778
779 ?>
Something went wrong with that request. Please try again.