N
N
Network20202020-11-15 18:15:16
JavaScript
Network2020, 2020-11-15 18:15:16

How to divide the world map into equal parts (squares)?

It is necessary to break the world map into equal sections (hereinafter squares). The task is to figure out which of these squares a point with a certain latitude and longitude falls into. Due to the fact that the length of the longitude is not fixed, it is not possible to split the map into equal parts.
Suppose you need to find out in which square a point with coordinates falls:
Latitude 30.95 degrees
Longitude 40.80 degrees
Height and length of the square into which the map is divided 200x200 meters

My solution was to find out the distance (in meters) from zero degree (latitude and longitude 0;0) to the longitude of the point (0;40.80) and divide the found distance by 200, then remove the remainder to find the point. Then find the distance from the received point to the point with the longitude coordinates that we received and latitude 30.95 and divide the result by 200 and remove the remainder here too. But the solution doesn't work, because the length of the longitude at all points is different. I have been trying to find a solution for 10 days, but my knowledge is not enough for this. I ask for any help! Thanks in advance!

The solution can be written in any language, well, or just a formula)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
N, 2020-11-15
@Fernus

Right now, I rummaged in my own project ... I solved a slightly different problem, but I think it can be finalized ...
I had the following task:
1. There is a point on the map;
2. There are polygons (polygons) on the map;
3. There is a point inside each polygon in case the point from item 1 does not fall into any polygon, then you need to find the nearest point from item 3 for the point from item 1 ...
Below is an example of how to check the occurrence of a point from item 1. 1 into polygons (polygons) from item 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= ;
        $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;

}

To solve point 3, the distance function is used ... if this logic suits your tasks ... then I will show another example further ...
I just have to rewrite the code before posting it ...))
PS: All the coordinates are stupidly out of my head ...it's better to test on real data...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question