Подтвердить что ты не робот

Поиск городов в радиусе 10 миль от почтового индекса. API карт Google

Недавно я начал изучать API Карт Google, чтобы попробовать что-то новое на своих сайтах. В настоящее время я использую этот код:

<?php

$postcode = $_REQUEST['postcode'];

$url = 'http://maps.googleapis.com/maps/api/geocode/xml?address='.$postcode.'&sensor=false';
$parsedXML = simplexml_load_file($url);

if($parsedXML->status != "OK") {
echo "There has been a problem: " . $parsedXML->status;
}

$myAddress = array();
foreach($parsedXML->result->address_component as $component) {
if(is_array($component->type)) $type = (string)$component->type[0];
else $type = (string)$component->type;

$myAddress[$type] = (string)$component->long_name;
}
header('Content-Type: application/json');
echo json_encode($myAddress);


?>

который просто использует почтовый индекс, который я определяю и просматриваю базу данных Google, а затем возвращает город, графство и т.д.

Если возможно, я хотел бы не только показать ближайший город, но и любой в радиусе 5-10 миль. Может ли кто-нибудь сказать мне, как я буду делать это, пожалуйста?

Спасибо за любую помощь

4b9b3361

Ответ 1

Обновление. Я написал более подробный блог-блог об этом конкретном предмете на http://www.mullie.eu/geographic-searches/

-

Прокрутите все доступные города, используя API Карт Google, чтобы получить их широту и долготу. Сохраните их где-нибудь (база данных). - Остерегайтесь, Google не будет принимать огромное количество звонков, поэтому дросселируйте ваши звонки.

Затем, выбирая город, вы можете использовать код, похожий на код ниже, чтобы захватить города с определенным диапазоном:

public static function getNearby($lat, $lng, $type = 'cities', $limit = 50, $distance = 50, $unit = 'km')
{
    // radius of earth; @note: the earth is not perfectly spherical, but this is considered the 'mean radius'
    if ($unit == 'km') $radius = 6371.009; // in kilometers
    elseif ($unit == 'mi') $radius = 3958.761; // in miles

    // latitude boundaries
    $maxLat = (float) $lat + rad2deg($distance / $radius);
    $minLat = (float) $lat - rad2deg($distance / $radius);

    // longitude boundaries (longitude gets smaller when latitude increases)
    $maxLng = (float) $lng + rad2deg($distance / $radius / cos(deg2rad((float) $lat)));
    $minLng = (float) $lng - rad2deg($distance / $radius / cos(deg2rad((float) $lat)));

    // get results ordered by distance (approx)
    $nearby = (array) FrontendDB::getDB()->retrieve('SELECT *
                                                    FROM table
                                                    WHERE lat > ? AND lat < ? AND lng > ? AND lng < ?
                                                    ORDER BY ABS(lat - ?) + ABS(lng - ?) ASC
                                                    LIMIT ?;',
                                                    array($minLat, $maxLat, $minLng, $maxLng, (float) $lat, (float) $lng, (int) $limit));

    return $nearby;
}

Заметки о приведенном выше коде:

  • Используется собственная оболочка базы данных, поэтому преобразуем ее в mysql_query, PDO,...
  • Это не будет точно. Мы не можем делать точные сферические вычисления в БД, поэтому мы взяли верхний и нижний пределы широты и долготы. Это в основном означает, что местоположение, которое немного дальше вашего расстояния (например, на крайнем северо-востоке, прямо за пределами фактического радиуса (на самом деле это почти круг), но все же внутри максимальной широты и долготы (потому что мы сравниваем это на квадратные пределы в базе данных). Это просто даст приблизительный, но ореховый 100% точный выбор городов с вашим радиусом.

Я попытаюсь проиллюстрировать это:

_________________
|      / \      |
| Y  /     \    |
|  /         \  |
|(      X      )|
|  \         /  |
|    \     /    |
|______\_/______|

Вышеуказанный круг (несколько) является фактическим радиусом, в котором вы хотите найти местоположения внутри, в зависимости от местоположения X. Это слишком сложно сделать прямо из вашей БД, поэтому то, что мы на самом деле извлекаем из БД, это окружающая площадь, Как вы можете видеть, возможно, что местоположения (например, Y) попадают в эти границы max и min, хотя на самом деле они не имеют требуемого радиуса. Затем они могут быть отфильтрованы через PHP.

Чтобы решить эту последнюю проблему, вы можете закодировать все результаты и рассчитать точное расстояние между вашим корневым местоположением и найденными совпадениями, чтобы рассчитать, действительно ли они находятся в пределах вашего радиуса. Для этого вы можете использовать этот код:

public static function getDistance($lat1, $lng1, $lat2, $lng2, $unit = 'km')
{
    // radius of earth; @note: the earth is not perfectly spherical, but this is considered the 'mean radius'
    if ($unit == 'km') $radius = 6371.009; // in kilometers
    elseif ($unit == 'mi') $radius = 3958.761; // in miles

    // convert degrees to radians
    $lat1 = deg2rad((float) $lat1);
    $lng1 = deg2rad((float) $lng1);
    $lat2 = deg2rad((float) $lat2);
    $lng2 = deg2rad((float) $lng2);

    // great circle distance formula
    return $radius * acos(sin($lat1) * sin($lat2) + cos($lat1) * cos($lat2) * cos($lng1 - $lng2));
}

Это будет вычислять (квази) точное расстояние между местоположением X и местоположением Y, а затем вы можете отфильтровать именно те города, которые были достаточно близко, чтобы передать грубую db-выборку, но не достаточно близко, чтобы фактически быть в пределах вашего границы.