View difference between Paste ID: SsZ98U7M and ZEK5y1WE
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
?>