EpsgConversion.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <?php
  2. class EpsgConversion {
  3. private static $fe = 500000;
  4. private static function CalculateESquared($a, $b) {
  5. return (pow($a, 2) - pow($b, 2)) / pow($a, 2);
  6. }
  7. private static function CalculateE2Squared($a, $b) {
  8. return (pow($a, 2) - pow($b, 2)) / pow($b, 2);
  9. }
  10. private static function denom ($es, $sphi) {
  11. $sinSphi = sin($sphi);
  12. return sqrt(1 - $es * pow($sinSphi, 2));
  13. }
  14. private static function sphsr ($a, $es, $sphi) {
  15. $dn = self::denom($es, $sphi);
  16. return $a * (1 - $es) / pow($dn, 3);
  17. }
  18. private static function sphsn ($a, $es, $sphi) {
  19. $sinSphi = sin($sphi);
  20. return $a / sqrt(1 - $es * pow($sinSphi, 2));
  21. }
  22. private static function sphtmd ($ap, $bp, $cp, $dp, $ep, $sphi) {
  23. return ($ap * $sphi) - ($bp * sin(2 * $sphi)) + ($cp * sin(4 * $sphi)) - ($dp * sin(6 * $sphi)) + ($ep * sin(8 * $sphi));
  24. }
  25. private static function LonLatToPUWG($a, $f, $lon, $lat, $proj) {
  26. if ($lon < 13.5 || $lon >= 25.5) throw new Exception("Wrong longitude - {$lon}");
  27. if ($proj == 1) {
  28. $alam = 19 * M_PI / 180;
  29. $strf = 0;
  30. $nfn = -5300000.0;
  31. $ok = 0.9993;
  32. } else {
  33. $nfn = 0;
  34. $olam = floor(($lon + 1.5)/3) * M_PI / 60;
  35. $strf = floor(($lon + 1.5)/3) * 1000000;
  36. $ok = 0.999923;
  37. }
  38. $result = new StdClass();
  39. $latRad = $lat * M_PI / 180;
  40. $lonRad = $lon * M_PI / 180;
  41. $recf = 1 / $f;
  42. $b = $a * ($recf - 1) / $recf;
  43. $eSquared = self::CalculateESquared($a, $b);
  44. $e2Squared = self::CalculateE2Squared ($a, $b);
  45. $tn = ($a - $b) / ($a + $b);
  46. $ap = $a * (1 - $tn + 5 * (pow($tn, 2) - pow($tn, 3)) / 4 + 81 * (pow($tn, 4) - pow($tn, 5)) / 64);
  47. $bp = 3 * $a * ($tn - pow($tn, 2) + 7 * (pow($tn, 3) - pow($tn, 4)) / 8 + 55 * pow($tn, 5) / 64) / 2;
  48. $cp = 15 * $a * (pow($tn, 2) - pow($tn, 3) + 3 * (pow($tn, 4) - pow($tn, 5)) / 4) / 16;
  49. $dp = 35 * $a * (pow($tn, 3) - pow($tn, 4) + 11 * pow($tn, 5) / 16) / 48;
  50. $ep = 315 * $a * (pow($tn, 4) - pow($tn, 5)) / 512;
  51. $dlam = $lonRad - $olam;
  52. $s = sin($latRad);
  53. $c = cos($latRad);
  54. $t = $s / $c;
  55. $eta = $e2Squared * pow($c, 2);
  56. $sn = self::sphsn($a, $eSquared, $latRad);
  57. $tmd = self::sphtmd($ap, $bp, $cp, $dp, $ep, $latRad);
  58. $t1 = $tmd * $ok;
  59. $t2 = $sn * $s * $c * $ok / 2;
  60. $t3 = $sn * $s * pow($c, 3) * $ok * (5 - pow($t, 2) + 9 * $eta + 4 * pow($eta, 2)) / 24;
  61. $t4 = $sn * $s * pow($c, 5) * $ok * (61 - 58 * pow($t, 2) + pow($t, 4) + 270 * $eta - 330 * pow($t, 2) * $eta + 445 * pow($eta, 2) + 324 * pow($eta, 3) - 680 * pow($t, 2) * pow($eta, 2) + 88 * pow($eta, 4) - 600 * pow($t, 2) * pow($eta, 3) - 192 * pow($t, 2) * pow($eta, 4)) / 720;
  62. $t5 = $sn * $s * pow($c, 7) * $ok * (1385 - 3111 * pow($t, 2) + 543 * pow($t, 4) - pow($t, 6)) / 40320;
  63. $t6 = $sn * $c * $ok;
  64. $t7 = $sn * pow($c, 3) * $ok * (1 - pow($t, 2) + $eta) / 6;
  65. $t8 = $sn * pow($c, 5) * $ok * (5 - 18 * pow($t, 2) + pow($t, 4) + 14 * $eta - 58 * pow($t, 2) * $eta + 13 * pow($eta, 2) + 4 * pow($eta, 3) - 64 * pow($t, 2) * pow($eta, 2) - 24 * pow($t, 2) * pow($eta, 3)) / 120;
  66. $t9 = $sn * pow($c, 7) * $ok * (61 - 479 * pow($t, 2) + 179 * pow($t, 4) - pow($t, 6)) / 5040;
  67. $result->x = self::$fe + $strf + $dlam * $t6 + pow($dlam, 3) * $t7 + pow($dlam, 5) * $t8 + pow($dlam, 7) * $t9;
  68. $result->y = $nfn + $t1 + pow($dlam, 2) * $t2 + pow($dlam, 4) * $t3 + pow($dlam, 6) * $t4 + pow($dlam, 8) * $t5;
  69. return $result;
  70. }
  71. private static function PUWGToLonLat ($a, $f, $lon, $lat, $proj) {
  72. $result = new StdClass();
  73. $ok = 0.999923;
  74. if ($proj == 1) $ok = 0.9993;
  75. $recf = 1 / $f;
  76. $b = $a * ($recf - 1) / $recf;
  77. $eSquared = self::CalculateESquared($a, $b);
  78. $e2Squared = self::CalculateE2Squared($a, $b);
  79. $tn = ($a - $b) / ($a + $b);
  80. $ap = $a * (1 - $tn + 5 * (pow($tn, 2) - pow($tn, 3)) / 4 + 81 * (pow($tn, 4) - pow($tn, 5)) / 64);
  81. $bp = 3 * $a * ($tn - pow($tn, 2) + 7 * (pow($tn, 3) - pow($tn, 4)) / 8 + 55 * pow($tn, 5) / 64) / 2;
  82. $cp = 15 * $a * (pow($tn, 2) - pow($tn, 3) + 3 * (pow($tn, 4) - pow($tn, 5)) / 4) / 16;
  83. $dp = 35 * $a * (pow($tn, 3) - pow($tn, 4) + 11 * pow($tn, 5) / 16) / 48;
  84. $ep = 315 * $a * (pow($tn, 4) - pow($tn, 5)) / 512;
  85. if ($proj == 1) {
  86. $olam = 19 * M_PI / 180;
  87. $strf = 0;
  88. $nfn = -5300000;
  89. } else {
  90. $nfn = 0;
  91. $strf = floor($lon / 1000000) * 1000000;
  92. $olam = $strf / 60000000 * M_PI;
  93. }
  94. $tmd = ($lat - $nfn) / $ok;
  95. $sr = self::sphsr($a, $eSquared, 0);
  96. $ftphi = $tmd / $sr;
  97. for ($i = 0; $i < 5; $i++) {
  98. $t10 = self::sphtmd($ap, $bp, $cp, $dp, $ep, $ftphi);
  99. $sr = self::sphsr($a, $eSquared, $ftphi);
  100. $ftphi = $ftphi + ($tmd - $t10) / $sr;
  101. }
  102. $sr = self::sphsr($a, $eSquared, $ftphi);
  103. $sn = self::sphsn($a, $eSquared, $ftphi);
  104. $s = sin($ftphi);
  105. $c = cos($ftphi);
  106. $t = $s / $c;
  107. $eta = $e2Squared * pow($c, 2);
  108. $de = $lon - self::$fe - $strf;
  109. $t10 = $t / (2 * $sr * $sn * pow($ok, 2));
  110. $t11 = $t * (5 + 3 * pow($t, 2) + $eta - 4 * pow($eta, 2) - 9 * pow($t, 2) * $eta) / (24 * $sr * pow($sn, 3) * pow($ok, 4));
  111. $t12 = $t * (61 + 90 * pow($t, 2) + 46 * $eta + 45 * pow($t, 4) - 252 * pow($t, 2) * $eta - 3 * pow($eta, 2) + 100 * pow($eta, 3) - 66 * pow($t, 2) * pow($eta, 2) - 90 * pow($t, 4) * $eta + 88 * pow($eta, 4) + 225 * pow($t, 4) * pow($eta, 2) + 84 * pow($t, 2) * pow($eta, 3) - 192 * pow($t, 2) * pow($eta, 4)) / (720 * $sr * pow($sn, 5) * pow($ok, 6));
  112. $t13 = $t * (1385 + 3633 * pow($t, 2) + 4095 * pow($t, 4) + 1575 * pow($t, 6)) / (40320 * $sr * pow($sn, 7) * pow($ok, 8));
  113. $t14 = 1 / ($sn * $c * $ok);
  114. $t15 = (1 + 2 * pow($t, 2) + $eta) / (6 * pow($sn, 3) * $c * pow($ok, 3));
  115. $t16 = 1 * (5 + 6 * $eta + 28 * pow($t, 2) - 3 * pow($eta, 2) + 8 * pow($t, 2) * $eta + 24 * pow($t, 4) - 4 * pow($eta, 3) + 4 * pow($t, 2) * pow($eta, 2) + 24 * pow($t, 2) * pow($eta, 3)) / (120 * pow($sn, 5) * $c * pow($ok, 5));
  116. $t17 = 1 * (61 + 662 * pow($t, 2) + 1320 * pow($t, 4) + 720 * pow($t, 6)) / (5040 * pow($sn, 7) * $c * pow($ok, 7));
  117. $dlam = $de * $t14 - pow($de, 3) * $t15 + pow($de, 5) * $t16 - pow($de, 7) * $t17;
  118. $result->x = ($olam + $dlam) * 180 / M_PI;
  119. $result->y = ($ftphi - pow($de, 2) * $t10 + pow($de, 4) * $t11 - pow($de, 6) * $t12 + pow($de, 8) * $t13) * 180 / M_PI;
  120. return $result;
  121. }
  122. public static function getEpsg($lon, $lat = 0) {
  123. if ($lon < 13.5 || $lon >= 25.5) throw new Exception("Wrong longitude - {$lon}");
  124. return floor(($lon + 1.5) / 3) + 2171;
  125. }
  126. public static function LonLatToPUWGWGS84($lon, $lat) {
  127. $result = self::LonLatToPUWG(6378137, 1 / 298.257223563, $lon, $lat, 4);
  128. $result->epsg = self::getEpsg($lon);
  129. return $result;
  130. }
  131. public static function PUWGToLonLatWGS84($lon, $lat) {
  132. $result = self::PUWGToLonLat(6378137, 1 / 298.257223563, $lon, $lat, 4);
  133. $result->epsg = self::getEpsg($result->x);
  134. return $result;
  135. }
  136. }