首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于最小和最大半径的PHP距离

基于最小和最大半径的PHP距离
EN

Stack Overflow用户
提问于 2013-09-03 02:36:17
回答 2查看 607关注 0票数 0

首先,我知道有关于这个函数的问题的答案,我浏览了其中的大多数,我可以找到我正在寻找的答案。我想要做的事情可以很简单地用图片来解释:

image diagram of php distance function http://stokemandevelopment.com/pictures/image1.JPG

现在,让我们在这张图片中添加一些叙述。我正在尝试做的是,在MySQL中,计算从机场到我数据库中所有机场的距离,如果它们落在半径A和半径B之间,将它们添加到我的数组中,以便以后执行某些操作。

代码语言:javascript
运行
复制
function distance($lat1, $lon1, $lat2, $lon2, $unit) {
  $theta = $lon1 - $lon2;
  $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
  $dist = acos($dist);
  $dist = rad2deg($dist);
  $miles = $dist * 60 * 1.1515;
  $unit = strtoupper($unit);

  if ($unit == "K") {
    return ($miles * 1.609344);
  } else if ($unit == "N") {
     return ($miles * 0.8684);
    } else {
        return $miles;
        }
}

我目前使用的是THis进行计算,但它是用php编写的,而且速度非常慢。我希望升级代码,以便mysql服务器进行计算。我也在尝试用PDO来完成这一切。如果有人能帮助我,我将不胜感激。

EN

回答 2

Stack Overflow用户

发布于 2013-09-03 02:43:19

选项1:通过切换到支持GeoIP的数据库或使用MySQL的基本GeoIP功能,在数据库上执行计算。

选项2:在数据库上进行计算:您使用的是MySQL,因此下面的存储过程应该会有所帮助

代码语言:javascript
运行
复制
CREATE FUNCTION distance (latA double, lonA double, latB double, LonB double)
    RETURNS double DETERMINISTIC
BEGIN
    SET @RlatA = radians(latA);
    SET @RlonA = radians(lonA);
    SET @RlatB = radians(latB);
    SET @RlonB = radians(LonB);
    SET @deltaLat = @RlatA - @RlatB;
    SET @deltaLon = @RlonA - @RlonB;
    SET @d = SIN(@deltaLat/2) * SIN(@deltaLat/2) +
    COS(@RlatA) * COS(@RlatB) * SIN(@deltaLon/2)*SIN(@deltaLon/2);
    RETURN 2 * ASIN(SQRT(@d)) * 6371.01;
END//

如果你的数据库中有一个纬度和经度的索引,你可以减少需要计算的计算次数,方法是在PHP中创建一个初始边界框( $minLat,$maxLat,$minLong和$maxLong),并基于此将行限制为条目的子集(其中纬度在$minLat和$maxLat之间,经度在$minLong和$maxLong之间)。然后,MySQL只需要对该行的子集执行距离计算。

如果您只是使用skv提供的SQL语句(或存储过程来计算距离),那么SQL仍然需要查看数据库中的每条记录,并计算数据库中每条记录的距离,然后才能决定是返回该行还是丢弃该行。

因为计算的执行速度相对较慢,所以如果您可以减少需要计算的行集,消除明显超出所需距离的行,这样我们只对较少的行数执行开销较大的计算,这会更好。

考虑到你正在做的基本上是在地图上画一个圆,以你的初始点为中心,并有一个距离半径;然后这个公式简单地识别出哪些行属于这个圆……但它仍然需要检查每一行。

使用边界框就像在地图上绘制一个正方形,首先在离中心点适当的距离上画出左、右、上和下的边。然后,我们的圆将在该框中绘制,圆上的最北点、最东点、最南点和最西点将与框的边界接触。一些行将落在该框之外,因此SQL甚至不会费心计算这些行的距离。它只计算那些落在边界框内的行的距离,以查看它们是否也落在圆内。

在PHP中,我们可以使用一个非常简单的计算方法,根据距离计算出最小和最大纬度和经度,然后在SQL语句的WHERE子句中设置这些值。这实际上是我们的盒子,任何落在盒子之外的东西都会被自动丢弃,而不需要实际计算它的距离。

Movable Type website上有一个很好的解释(用PHP代码),这应该是任何计划用PHP做任何GeoPositioning工作的人的必备读物。

票数 0
EN

Stack Overflow用户

发布于 2013-09-03 08:34:57

你可以在机场周围使用六边形网格和螺旋搜索。下面是一个包含相邻磁贴的示例:Optimizing search through large list of lat/long coords to find match

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18579078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档