如何在给定半径内从数据库中检索经度和纬度?

时间:2011-12-25 17:44:19

标签: php mysql geolocation

这是我的数据库表(点)。

enter image description here

在地图P(longitude, latitude)上给出一个点,我想从数据库中检索的是给定半径内以P为中心的点集。我尝试使用经度和纬度的简单公式进行简单查询,遗憾的是结果总是为空:(。我在这里做错了什么?有什么想法吗?

$sql = "SELECT * FROM $tbl_name 
WHERE ACOS(SIN('".$latitude."') * SIN(spots.latitude) + COS('".$latitude."') * COS(spots.latitude) * COS(spots.longitude - '".$longitude    ."')) * 6371 <= '".$radius."'";

3 个答案:

答案 0 :(得分:4)

我解决这个问题的方法是创建一个地理“框”,只需选择使用半径和纬度 - 最大纬度距离(经度相同)的纬度和最大纬度之间的纬度。

然后,我会在PHP中计算出哪些点实际上满足您的标准(框中的圆圈),而不是在每一行上执行复杂的计算。这应该使计算更容易并提高性能。

这是查询的C#示例(lon1和lat1是中心lat和lon)。我不擅长在PHP中创建一个PHP示例,如果有人想添加一个很棒的例子:

        double minLon = lon1 - maxDistance / Math.Abs(Math.Cos((lat1 / 180) * Math.PI) * 69);
        double maxLon = lon1 + maxDistance / Math.Abs(Math.Cos((lat1 / 180) * Math.PI) * 69);
        double minLat = lat1 - (maxDistance / 69);
        double maxLat = lat1 + (maxDistance / 69);
        String query = "SELECT [idColumn], [latitude], [longitude] FROM [db].[dbo].[table] WHERE [latitude] BETWEEN " + minLat + " AND " + maxLat + " AND [longitude] BETWEEN " + minLon + " AND " + maxLon;

以下是我如何计算这些点的距离:

        double r = 3956.087107103049;
        return (r * 2) * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin((lat1 - lat2) / 2), 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Pow(Math.Sin((lon1 - lon2) / 2), 2)));

答案 1 :(得分:2)

基于Cameron S&amp; MrGlass的想法,以及在互联网上的一些搜索,我找到了一个有效的解决方案:

$R = 6371;
$max_lat = $lat + rad2deg($r/$R);
$min_lat = $lat - rad2deg($r/$R);

$max_lon = $lon + rad2deg($r/$R/cos(deg2rad($lat)));
$min_lon = $lon - rad2deg($r/$R/cos(deg2rad($lat)));
$lat = deg2rad($lat);
$lon = deg2rad($lon);

$sql = "
select id, name, description, latitude, longitude, 
       acos(sin($lat)*sin(radians(latitude)) + cos($lat)*cos(radians(latitude))*cos(radians(longitude)-$lon)) * $R as D
from (
  select id, name, description, latitude, longitude 
  from $tbl_name 
  where latitude > $min_lat and latitude < $max_lat
    and longitude > $min_lon and longitude < $max_lon
  ) as first_cut 
where acos(sin($lat)*sin(radians(latitude)) + cos($lat)*cos(radians(latitude))*cos(radians(longitude) - $lon)) * $R < $r
order by D";

答案 2 :(得分:0)

我会计算PHP中纬度和经度的最大/最小可能值。然后,您可以使用非常简单的SQL选择该范围内的所有位置:

$sql = "SELECT * from locations where latitude >= $minLat and latitude <= $maxLat and longitude >= $minLong and longitude <= $maxLong