Недавно я начал изучать 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 миль. Может ли кто-нибудь сказать мне, как я буду заниматься этим, пожалуйста?
Спасибо за любую помощь
Обновление : я написал более подробный блог-блог об этом конкретном предмете на 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; }
Заметки о вышеуказанном коде:
Я попытаюсь проиллюстрировать это:
_________________ | / \ | | 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-выборку, но не достаточно близко, чтобы фактически оказаться в пределах ваших границ.