寻找距离邮编10英里范围内的城镇。谷歌地图API。

13

我最近开始研究Google Maps API,想在我的网站上尝试一些新的东西。我目前正在使用以下代码:

<?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);


?>

我定义了一个邮政编码,使用这个邮政编码在谷歌数据库中搜索,并返回城镇、县等信息。

如果可能的话,我不仅想显示最近的城镇,还想显示5-10英里范围内的任何城镇。请问有人可以告诉我如何实现吗?

非常感谢任何帮助。


在stackoverflow上有几个有前途的问答,网址为:http://stackoverflow.com/search?q=radius+search+google+maps+php - 你看过这些问题中的哪些,为什么它们不能帮助你解决问题呢? - Gordon
我会浏览一下这些内容,我在输入问题时确实看了建议的帖子,但没有看到太有用的东西。你知道我能在哪里获取英国邮政编码数据库而不必为此付出荒谬的费用吗?我看到一篇文章说维基解密发布了它,但这是在2009年,所以我猜它可能不是完全更新的。 - Daniel Hutton
抱歉,我不知道。快速谷歌搜索出现了https://www.ordnancesurvey.co.uk/opendatadownload/products.html,但我不确定这些是否免费使用或有帮助。 - Gordon
1个回答

59

更新:我撰写了一篇更详细的关于这个特定主题的博客文章,位于http://www.mullie.eu/geographic-searches/

--

使用 Google Maps API 循环遍历所有可用城镇并获取它们的纬度和经度。将这些信息保存在某个地方(数据库)中。- 注意,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)落在这些最大和最小边界内,尽管它们实际上不在请求的半径内。但是,这些可以稍后通过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之间的(准确)距离,然后您可以过滤掉那些足够接近以通过粗略的数据库提取,但实际上并不在您的范围内的城市。

5
我不知道为什么你只有六个赞 =) - user292916

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接