首先,我知道有关此功能的问题有答案,我查看了大部分内容,我可以找到我正在寻找的答案。我想做的事情可以简单地用图片来解释:
image diagram of php distance function http://stokemandevelopment.com/pictures/image1.JPG
现在让我们为这张图片添加一些叙述。我想要做的是,在MySQL中,计算从机场到我的数据库中所有机场的距离,如果它们介于Radius A和Radius B之间,请将它们添加到我的数组中,以便在晚点。
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;
}
}
这是我目前用来做我的caluclations但是它在php中,并且非常慢。我希望升级代码,以便mysql服务器进行计算。我也试图在PHP PDO中完成所有这些。如果有人可以帮助我,我们将不胜感激。
答案 0 :(得分:0)
选项1: 通过切换到支持GeoIP的数据库或使用MySQL的基本GeoIP功能对数据库进行计算。
选项2: 在数据库上进行计算:您正在使用MySQL,因此以下存储过程应该有帮助
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) ,并根据该行将子行限制为条目的子集(WHERE纬度BETWEEN $ minLat和$ maxLat以及经度BETWEEN $ minLong和$ maxLong)。然后,MySQL只需要为该行子集执行距离计算。
如果您只是使用skv提供的SQL语句(或存储过程来计算距离),那么SQL仍然必须查看数据库中的每条记录,并计算数据库中每条记录的距离它可以决定是返回该行还是丢弃它。
因为计算执行起来相对较慢,所以如果你可以减少需要计算的行集会更好,消除明显超出所需距离的行,这样我们才会执行对于较少行数的昂贵计算。
考虑到你正在做的事情基本上是在地图上绘制一个圆圈,以你的初始点为中心,并且距离的半径;那么公式只是简单地确定哪些行属于那个圈子......但它仍然必须检查每一行。
使用边界框就像在地图上首先绘制一个正方形,左边,右边,顶边和底边与我们的中心点保持适当的距离。然后我们的圆圈将被绘制在该框内,圆圈上的最北端,最东端,最南端和最西端的点接触到框的边界。有些行会落在该框之外,因此SQL甚至不愿意尝试计算这些行的距离。它只计算那些落在边界框内的行的距离,看它们是否也属于圆圈。
在PHP中,我们可以使用一个非常简单的计算,根据距离计算出最小和最大纬度和经度,然后在SQL语句的WHERE子句中设置这些值。这实际上就是我们的盒子,任何不属于它的东西都会被自动丢弃,而不需要实际计算它的距离。
Movable Type website对此(使用PHP代码)有一个很好的解释,对于计划在PHP中进行任何GeoPositioning工作的人来说,这应该是必不可少的阅读。
答案 1 :(得分:0)
您可以在机场周围使用六边形网格和螺旋搜索。以下是相邻切片的示例:Optimizing search through large list of lat/long coords to find match