这是我的数据库表(点)。
在地图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."'";
答案 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