SHOW:
|
|
- or go back to the newest paste.
| 1 | <?php | |
| 2 | ||
| 3 | /** | |
| 4 | * Class Earth | |
| 5 | * Земляшка | |
| 6 | * | |
| 7 | * @copyright https://tech.yandex.ru/maps/ | |
| 8 | */ | |
| 9 | abstract class Earth {
| |
| 10 | /** | |
| 11 | * Длина одного градуса на конкретной широте | |
| 12 | * | |
| 13 | * @param float $gps_y Широта | |
| 14 | * | |
| 15 | * @return float | |
| 16 | */ | |
| 17 | static function get_x_length($gps_y) {
| |
| 18 | return 0.00008516452991 * pow($gps_y, 3) - 0.02385660256 * pow($gps_y, 2) + 0.2589428868 * $gps_y + 107.75; | |
| 19 | } | |
| 20 | ||
| 21 | /** | |
| 22 | * Длина половины градуса на конкретной широте | |
| 23 | * | |
| 24 | * @param float $gps_x Широта | |
| 25 | * | |
| 26 | * @return float | |
| 27 | */ | |
| 28 | static function get_y_length_05($gps_x) {
| |
| 29 | return -0.000002053898482 * pow($gps_x, 3) + 0.0002813579278 * pow($gps_x, 2) + 0.007 * $gps_x + 55.135; | |
| 30 | } | |
| 31 | ||
| 32 | static function P($t) {
| |
| 33 | return max(min($t, 89.999), -89.999); | |
| 34 | } | |
| 35 | ||
| 36 | static function h($t) {
| |
| 37 | return 0 > $t ? -1 : $t > 0 ? 1 : 0; | |
| 38 | } | |
| 39 | ||
| 40 | const M = 6378137; | |
| 41 | const i = 0.00335281066474682000653026208241;// 1 - sqrt(1 - 0.00669437999014); | |
| 42 | const o = 6356752.3142451837116840090937925;// (1 - i) * M; | |
| 43 | const c = 1e-10; | |
| 44 | ||
| 45 | static function r($t) {
| |
| 46 | return abs($t - self::h($t) * M_PI / 2) < self::c ? self::h($t) * M_PI / 2 : atan((1 - self::i) * tan($t)); | |
| 47 | } | |
| 48 | ||
| 49 | /** | |
| 50 | * Вычисление расстояния между двумя точками на планете Земля | |
| 51 | * | |
| 52 | * @param float[] $t | |
| 53 | * @param float[] $s | |
| 54 | * | |
| 55 | * @return float | |
| 56 | */ | |
| 57 | static function get_distance($t, $s) {
| |
| 58 | if ($t == $s || $t[0] == $s[0] && $t[1] == $s[1]) {
| |
| 59 | return 0; | |
| 60 | } | |
| 61 | $t[0] = self::P($t[0]); | |
| 62 | $s[0] = self::P($s[0]); | |
| 63 | if (($t[0] == 0) && ($s[0] == 0)) {
| |
| 64 | $O = min(abs($s[1] - $t[1]), 180); | |
| 65 | ||
| 66 | return 2 * M_PI * self::M / 360 * abs($O); | |
| 67 | } | |
| 68 | ||
| 69 | $f = $t[0] * M_PI / 180; | |
| 70 | $g = $s[0] * M_PI / 180; | |
| 71 | $m = ($s[1] - $t[1]) * M_PI / 180; | |
| 72 | $D = self::r($f); | |
| 73 | $b = self::r($g); | |
| 74 | $q = $m; | |
| 75 | $p = $q; | |
| 76 | $y = 0; | |
| 77 | do {
| |
| 78 | $R = sqrt(pow(cos($b) * sin($q), 2) + pow(cos($D) * sin($b) - sin($D) * cos($b) * cos($q), 2)); | |
| 79 | $S = sin($D) * sin($b) + cos($D) * cos($b) * cos($q); | |
| 80 | $z = atan2($R, $S); | |
| 81 | $j = cos($D) * cos($b) * sin($q) / sin($z); | |
| 82 | $k = 1 - pow($j, 2); | |
| 83 | $A = cos($z) - 2 * sin($D) * sin($b) / $k; | |
| 84 | $B = self::i / 16 * $k * (4 + self::i * (4 - 3 * $k)); | |
| 85 | $q = min( | |
| 86 | max($m + (1 - $B) * self::i * $j * ($z + $B * sin($z) * ($A + $B * cos($z) * (-1 + 2 * $A * $A))), | |
| 87 | -2 * M_PI), 2 * M_PI); | |
| 88 | $v = abs($p - $q); | |
| 89 | $p = $q; | |
| 90 | $y++; | |
| 91 | } while ($v > self::c && 10 > $y); | |
| 92 | $C = $k * (self::M * self::M - self::o * self::o) / (self::o * self::o); | |
| 93 | $E = 1 + $C * (4096 + $C * (-768 + $C * (320 - 175 * $C))) / 16384; | |
| 94 | $G = $C * (256 + $C * (-128 + $C * (74 - 47 * $C))) / 1024; | |
| 95 | $H = $G * sin($z) * | |
| 96 | ($A + 0.25 * $G * | |
| 97 | (cos($z) * (-1 + 2 * $A * $A) - | |
| 98 | 1 / 6 * $G * $A * (-3 + 4 * sin($z) * sin($z)) * (-3 + 4 * $A * $A))); | |
| 99 | ||
| 100 | return self::o * $E * ($z - $H); | |
| 101 | } | |
| 102 | } | |
| 103 | ||
| 104 | $collection = []; | |
| 105 | for ($i = 0; $i < 20; $i++) {
| |
| 106 | $a = [mt_rand(20, 169), mt_rand(40, 77)]; | |
| 107 | $b = [mt_rand(20, 169), mt_rand(40, 77)]; | |
| 108 | ||
| 109 | print_r(a, $b, Earth::get_distance($a, $b)); | |
| 110 | } | |
| 111 | ||
| 112 | ?> |