php 查找邮政编码 10 英里范围内的城镇。谷歌地图API

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8135243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 04:02:11  来源:igfitidea点击:

Finding towns within a 10 mile radius of postcode. Google maps API

phpgoogle-mapsgoogle-maps-api-3

提问by Daniel Hutton

I've recently started looking at the Google Maps API to try out something new in my websites. I am currently using this code:

我最近开始研究 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);


?>

which simply uses a postcode that I define and searches the Google database and then returns the town, county etc.

它只是使用我定义的邮政编码并搜索 Google 数据库,然后返回城镇、县等。

If possible, I would like to not only show the nearest town but also any within a 5-10 mile radius. Could someone tell me how I would go about doing this please?

如果可能的话,我不仅想显示最近的城镇,还想显示 5-10 英里范围内的任何城镇。有人能告诉我我会怎么做吗?

Thanks for any help

谢谢你的帮助

回答by matthiasmullie

Update: I wrote up a more detailed blogpost about this specific subject on http://www.mullie.eu/geographic-searches/

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

--

——

Loop through all available towns using the Google Maps API to fetch their latitude & longitude. Save these somewhere (database). - Beware, Google will not accept an enormous amount of calls, so throttle your calls.

使用 Google Maps API 遍历所有可用城镇以获取其纬度和经度。将这些保存在某处(数据库)。- 请注意,Google 不会接听大量电话,因此请限制您的电话。

Then, when fetching a town, you can use code similar to the code below to grab the cities withing a certain range:

然后,在获取城镇时,您可以使用类似于下面的代码的代码来获取一定范围内的城市:

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;
}

Notes about the above code:

关于上述代码的注意事项:

  • Own database wrapper is used, so transform to mysql_query, PDO, ...
  • This will not be exact. We can't do exact spherical calculations in the DB, so we've taken the upper & lower latitude & longitude limits. This basically means that a location which is slightly further than your distance (e.g. in the far north-east, just outside of the actual radius (which actually is pretty much a circle), but still inside the max latitude & longitude (because we compare it to square limits in the database). This will just give a rough but nut 100% accurate selection of cities withing your radius.
  • 使用了自己的数据库包装器,因此转换为 mysql_query、PDO、...
  • 这不会是准确的。我们无法在 DB 中进行精确的球面计算,因此我们采用了上下纬度和经度限制。这基本上意味着一个位置比您的距离稍远(例如在远东北,就在实际半径之外(实际上几乎是一个圆),但仍在最大纬度和经度内(因为我们比较它到数据库中的平方限制)。这只会给出一个粗略但 100% 准确的城市选择在你的半径范围内。

I'll try to illustrate this:

我将尝试说明这一点:

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

The above circle (somewhat) is the actual radius where you want to find locations within, based upon location X. This is too hard to accomplish straight out of your DB, so what we actually fetch from the DB is the surrounding square. As you can see, it's possible that locations (like Y) fall within these max & min boundaries, though they aren't actually withing the requested radius. These can later be filtered out through PHP though.

上面的圆(有点)是您想要根据位置 X 在其中查找位置的实际半径。这很难直接从您的数据库中完成,因此我们实际从数据库中获取的是周围的正方形。如您所见,位置(如 Y)有可能落在这些最大和最小边界内,尽管它们实际上并不在请求的半径范围内。不过,这些稍后可以通过 PHP 过滤掉。

To tackle this last issue, you could loop all results and calculate the exact distance between both your root location, and the close matches found, to calculate if they're actually within your radius. For that, you could use this code:

为了解决最后一个问题,您可以循环所有结果并计算您的根位置和找到的接近匹配之间的确切距离,以计算它们是否实际上在您的半径内。为此,您可以使用以下代码:

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

This will calculate the (quasi) exact distance between location X and location Y, and then you can filter out exactly those cities that were near enough to pass the rough db-fetch, but not just near enough to actually be within your bounds.

这将计算位置 X 和位置 Y 之间的(准)精确距离,然后您可以准确地过滤掉那些足够接近以通过粗略数据库获取的城市,但又不仅仅是足够接近以实际在您的范围内。