@Network2020

Как разделить карту мира на равные части (квадраты)?

Необходимо разбить карту мира на равные участки (далее квадраты). Задача в том, чтобы выяснить в какую из этих квадратов попадает точка с определенной широтой и долготой. Из-за того, что длина долготы не фиксированная, не удается разбить карту на равные части.
Допустим, необходимо выяснить, в какой квадрат попадает точка с координатами:
Широты 30.95 градусов
Долготы 40.80 градусов
Высота и длина квадрата, на которые разделена карта 200х200 метров

Мое решение состояло в том, чтобы узнать расстояние (в метрах) от нулевого градуса (широты и долготы 0;0) до долготы точки (0;40.80) и разделить найденное расстояние на 200,затем убрав остаток найти точку. Затем найти расстояние от полученной точки до точки с координатами долготы, которые мы получили и широты 30.95 и разделить результат на 200 и тут тоже убрать остаток. Но решение не работает, т.к. длина долготы во всех точках разное. Уже 10 дней пытаюсь найти решение, но моих знаний на это не хватает. Прошу любой помощи! Спасибо заранее!

Решение можно писать на любом языке, ну или просто формулу)
  • Вопрос задан
  • 501 просмотр
Пригласить эксперта
Ответы на вопрос 1
Fernus
@Fernus
Техник - Механик :)
Щас порылся в проекте одном своём...я немного другую задачу решал, но доработать, думаю можно...
У меня была такая задача:
1. Есть точка на карте;
2. Есть полигоны (многоугольники) на карте;
3. Есть внутри каждого многоугольника точка на случай, если точка из п.1 не попала ни в один многоугольник, то нужно найти ближайшую точку из п.3 для точки из п.1...

Ниже пример как проверять вхождение точки из п.1 в полигоны (многоугольники) из п.2...

class Polygon {
    /**
     * @var array
     */
    var $polygon = [];
    /**
     * Polygon itself, with basic vector-based structure
     * Array: [ [1,1], [2,1], [3,0], [2,-1] ]
     *
     * @var $polygon array
     */
    function setPolygon($polygon) {
        if (count($polygon) < 3) {
            return false;
        }

        if (!isset($polygon[0]['x'])) {
            foreach ($polygon as &$point) {
                //$point = ['x' => round($point[0] + 300, 4), 'y' => round($point[1] + 300, 4)];
                //$point = ['x' => round($point[0], 4), 'y' => round($point[1], 4)];

                if($point[0] < 0)
                    $point[0] = 90 + 90 - abs($point[0]);
                if($point[1] < 0)
                    $point[1] = 180 + 180 - abs($point[1]);

                $point = ['x' => round($point[0], 4), 'y' => round($point[1], 4)];
            }
        }
        $this->polygon = $polygon;
    }
    /**
     * Check if $polygon contains $test value
     *
     * @var $test array(x=>decimal, y=>decimal)
     */
    function calc($test) {

        if($test['x'] < 0)
            $test['x'] = 90 + 90 - abs($test['x']);
        if($test['y'] < 0)
            $test['y'] = 180 + 180 - abs($test['y']);

        $q_patt= [[0, 1], [3, 2]];
        $end = end($this->polygon);

        $pred_pt = end($this->polygon);
        $pred_pt['x'] -= $test['x'];
        $pred_pt['y'] -= $test['y'];
        $pred_q = $q_patt[$pred_pt['y'] < 0][$pred_pt['x'] < 0];
        $w = 0;

        for ($iter = reset($this->polygon); $iter !== false; $iter = next($this->polygon)) {
            $cur_pt = $iter;
            $cur_pt['x'] -= $test['x'];
            $cur_pt['y'] -= $test['y'];
            $q = $q_patt[$cur_pt['y'] < 0][$cur_pt['x'] < 0];

            switch ($q - $pred_q) {
                case -3:
                    ++$w;
                    break;
                case 3:
                    --$w;
                    break;
                case -2:
                    if ($pred_pt['x'] * $cur_pt['y'] >= $pred_pt['y'] * $cur_pt['x']) {
                        ++$w;
                    }
                    break;
                case 2:
                    if (!($pred_pt['x'] * $cur_pt['y'] >= $pred_pt['y'] * $cur_pt['x'])) {
                        --$w;
                    }
                    break;
            }
            $pred_pt = $cur_pt;
            $pred_q = $q;
        }

        return $w != 0;
    }

    public static function distance($lat1, $lng1, $lat2, $lng2) {

        $lat1=deg2rad($lat1);
        $lng1=deg2rad($lng1);
        $lat2=deg2rad($lat2);
        $lng2=deg2rad($lng2);

        $delta_lat=($lat2 - $lat1);
        $delta_lng=($lng2 - $lng1);

        return round( 6378137 * acos( cos( $lat1 ) * cos( $lat2 ) * cos( $lng1 - $lng2 ) + sin( $lat1 ) * sin( $lat2 ) ) );
    }

    public static function closestPoint($x, $y, $arPoints) {

        $RESULT = false;

        $x = floatval($x);
        $y = floatval($y);

        if(!empty($arPoints) && is_array($arPoints) && count($arPoints) > 0) {

            $arRes = array();

            foreach ($arPoints as $KEY => $VAL) {

                $x2 = floatval($VAL[0]);
                $y2 = floatval($VAL[1]);

                $distance = self::distance($x, $y, $x2, $y2);

                $arRes[$KEY] = $distance;

            }

            if(count($arRes) > 0) {

                natsort($arRes);
                reset($arRes);

                //$RESULT[key($arRes)] = current($arRes);

                $RESULT = array(
                    'ID' => key($arRes),
                    'DISTANCE' => current($arRes)
                );

            }

        }

        return $RESULT;
    }
}

/* Ипользование */

// Координаты точки, которую проверяем на вхождение в "полигон"
$X = 33.45;
$Y = 44.25;

// "Полигоны"
$arCheckPoints = [
    'КЛЮЧ_МНОГОУГОЛЬНИКА' => [22.45, 44.55, 11.22, 55.66], // Координаты вершин
    'КЛЮЧ_МНОГОУГОЛЬНИКА_2' => [33.45, 66.55, 77.22, 99.66], // Координаты вершин
    'КЛЮЧ_МНОГОУГОЛЬНИКА_3' => [12.45, 15.55, 17.22, 54.66], // Координаты вершин
];

$arResults = [];

$p = new \App\Helpers\Polygon();

foreach ($arCheckPoints as $KEY_POLYGON => $arPolygon) {

    $p->setPolygon($arPolygon);

    if($p->calc(array('x' => $X, 'y' => $Y)))
        $arResults[$KEY_POLYGON] = $arPolygon;

}


Для решения п.3 используется функция distance...если под твои задачи это логика подходит...то дальше покажу ещё пример...

Мне просто код переписывать приходится прежде, чем выложить...))

P.S.: Все координаты тупо из головы...на реальных данных лучше тестить...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы