下面就是计算球面间两点(lat0, lng)-(lat1, lng1)之间距离的函数。
from math import sin, asin, cos, radians, fabs, sqrt EARTH_RADIUS=6371 # 地球平均半径,6371km def hav(theta): s = sin(theta / 2) return s * s def get_distance_hav(lat0, lng0, lat1, lng1): "用haversine公式计算球面两点间的距离。" # 经纬度转换成弧度 lat0 = radians(lat0) lat1 = radians(lat1) lng0 = radians(lng0) lng1 = radians(lng1) dlng = fabs(lng0 - lng1) dlat = fabs(lat0 - lat1) h = hav(dlat) + cos(lat0) * cos(lat1) * hav(dlng) distance = 2 * EARTH_RADIUS * asin(sqrt(h)) return distance在庞大的地理数据库中搜索地点,索引是很重要的。但是,我们的需求是搜索附近地点,例如,坐标(39.91, 116.37)附近500米内有什么地点?搜索条件是地点坐标与当前坐标之间的距离,显然是无法应用索引的。
那么换个思路:首先算出“给定坐标附近500米”这个范围的坐标范围。虽然它是个圆,但我们可以先求出该圆的外接正方形,然后拿正方形的经纬度范围去搜索数据库。
先来求东西两侧的的范围边界。在haversin公式中令φ1 = φ2,可得
写成python代码就是
dlng = 2 * asin(sin(distance / (2 * EARTH_RADIUS)) / cos(lat)) dlng = degrees(dlng) # 弧度转换成角度然后求南北两侧的范围边界,在haversin公式中令 Δλ = 0,可得
写成python代码就是
dlat = distance / EARTH_RADIUS dlng = degrees(dlat) # 弧度转换成角度这样,根据当前点坐标,我们可以得出搜索范围为
left-top : (lat + dlat, lng - dlng) right-top : (lat + dlat, lng + dlng) left-bottom : (lat - dlat, lng - dlng) right-bottom: (lat - dlat, lng + dlng) 代码总结如下: def point(lat, lng, distance): dlng = 2 * asin(sin(distance / (2 * EARTH_RADIUS)) / cos(lat)) dlng = math.degrees(dlng) # 弧度转换成角度 dlat = distance / EARTH_RADIUS dlat = math.degrees(dlat) # 弧度转换成角度 return dlng,dlat