2010-08-31 74 views
8

我正在编写一个网站,基本上寻找在经纬度25英里半径内使用php和mysql的地方。PHP MySql和地理位置

我想知道这是如何工作?

我会传递一个拉特和长的脚本,并只拉出距纬度25英里以内,距我的位置数据库长的位置。

这样做的最好方法是什么?编号: 我发现这个代码来计算2点之间的距离。

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

是一个疗法办法做到这一点钙在MYSQL查找所以我只能返回,如果英里= < 25?

+0

从哪里拉其他地点?你是否每个预定位置的纬度/长度都存储在数组或数据库中? – shamittomar 2010-08-31 05:00:24

+0

我编辑了这个问题。我将在我的数据库中有特定位置,并会查看它们中的任何一个是否在25英里之内。如果不是,则不返回。 – shaneburgess 2010-08-31 05:02:12

+0

一些更多的信息在这里: http://stackoverflow.com/questions/20865747/geolocation-mysql-query – miralong 2014-12-05 16:45:02

回答

6

使用该函数来计算距离的计算相当昂贵,因为它涉及到大量的超越函数。当您需要过滤大量行时,这将会出现问题。

这里有一个备选方案中,近似认为是这样计算较不昂贵的:

近似距离英里:

sqrt(x * x + y * y) 

where x = 69.1 * (lat2 - lat1) 
and y = 53.0 * (lon2 - lon1) 

您可以通过添加余弦运算功能改善这种近似距离计算的准确性:

改进后的近似距离(英里):

sqrt(x * x + y * y) 

where x = 69.1 * (lat2 - lat1) 
and y = 69.1 * (lon2 - lon1) * cos(lat1/57.3) 

来源:http://www.meridianworlddata.com/Distance-Calculation.asp


我跑一束具有随机产生的数据集的测试。

  • 在精度为3种算法的差异是最小的,特别是在短距离
  • 最慢的算法是,当然,在一个与所述三角函数(一个对您的问题)。它比其他两个慢了4倍。

绝对不值得。只需要近似。
代码是在这里:http://pastebin.org/424186


要对MySQL的使用,创建一个stored procedure这需要协调的参数和返回的距离,那么你可以这样做:

SELECT columns 
    FROM table 
WHERE DISTANCE(col_x, col_y, target_x, target_y) < 25 
0

你可以这样做轻松分两步进行:

  • 查找点在每个方向上25英里内的所有位置。这看起来像:WHERE lat BETWEEN $lat1 AND $lat2 AND lng BETWEEN $lng1 AND $lng2

  • 然后遍历每个结果,并检查使用您的代码是否真的在25英里内。 (即,过滤掉那些在广场的角落位置)

在第一部分,这里的一些代码,我周围铺设(不记得源):

$lat_range = $radius/((6076/5280) * 60); 
$lng_range = $radius/(((cos(($city['lat'] * 3.141592653589/180)) * 6076)/5280) * 60); 

基本上只使用($lat - $lat_range, $lat + $lat_range)($lng - $lng_range, $lng + $lng_range)半径以英里为单位。

显然你可以清理一下数学。

编辑:我忘了提及,如果您需要支持赤道附近的位置,国际日期行等,那么您需要稍微调整一下。显然对于北美来说,它会很好。

+0

这当然有缺点需要两个过滤步骤,因为它返回不必要的行。 – NullUserException 2010-08-31 05:39:15

+0

是的,但它避免了对整个数据库执行计算。小半径和大数据集可能很重要。 – Matthew 2010-08-31 05:45:59