Created
April 26, 2018 06:28
-
-
Save kosmosr/5d599a6cc7bd55fe34197044af105255 to your computer and use it in GitHub Desktop.
距离排序
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
from sqlalchemy import asc, func | |
from model.device.station import Station | |
def station_nearby_list(distance, longitude, latitude, page=None, limit=None): | |
minlat, maxlat, minlng, maxlng = __get_area(latitude, longitude, distance) | |
# 按距离最近排序 | |
order_by = asc( | |
func.round(6371 * func.acos( | |
func.cos(func.radians(Station.latitude)) | |
* func.cos(func.radians(latitude)) | |
* func.cos(func.radians(longitude) - func.radians(Station.longitude)) | |
+ func.sin(func.radians(Station.latitude)) | |
* func.sin(func.radians(latitude)) | |
)) | |
) | |
station_nearby = Station.query.filter(Station.longitude.between(minlng, maxlng), | |
Station.latitude.between(minlat, maxlat), | |
Station.enable == bool(True), | |
Station.is_deleted == bool(False), | |
).order_by(order_by) | |
total = station_nearby.count() if station_nearby else 0 | |
if limit and page: | |
offset = (int(page) - 1) * int(limit) | |
station_nearby = station_nearby.offset(offset).limit(int(limit)) | |
result = [item.to_json() for item in station_nearby] | |
return result, total | |
def pile_nearby_list(distance, longitude, latitude, page=None, limit=None): | |
minlat, maxlat, minlng, maxlng = __get_area(latitude, longitude, distance) | |
# 按距离最近排序 | |
order_by = asc( | |
func.round(6371 * func.acos( | |
func.cos(func.radians(Station.latitude)) | |
* func.cos(func.radians(latitude)) | |
* func.cos(func.radians(longitude) - func.radians(Station.longitude)) | |
+ func.sin(func.radians(Station.latitude)) | |
* func.sin(func.radians(latitude)) | |
)) | |
) | |
station_nearby = Station.query.filter(Station.longitude.between(minlng, maxlng), | |
Station.latitude.between(minlat, maxlat), | |
Station.enable == bool(True), | |
Station.is_deleted == bool(False), | |
).order_by(order_by) | |
total = station_nearby.count() if station_nearby else 0 | |
if limit and page: | |
offset = (int(page) - 1) * int(limit) | |
station_nearby = station_nearby.offset(offset).limit(int(limit)) | |
result = [item.to_json() for item in station_nearby] | |
return result, total | |
def __get_area(latitude, longitude, dis): | |
""" | |
确定查询经纬度范围 | |
:param latitude:中心纬度 | |
:param longitude:中心经度 | |
:param dis:半径 | |
:return:(minlat, maxlat, minlng, maxlng) | |
""" | |
r = 6371.137 | |
dlng = 2 * math.asin(math.sin(dis / (2 * r)) / math.cos(latitude * math.pi / 180)) | |
dlng = dlng * 180 / math.pi | |
dlat = dis / r | |
dlat = dlat * 180 / math.pi | |
minlat = latitude - dlat | |
maxlat = latitude + dlat | |
minlng = longitude - dlng | |
maxlng = longitude + dlng | |
return minlat, maxlat, minlng, maxlng | |
def cal_dis(longitude1: float, latitude1: float, longitude2: float, latitude2: float): | |
""" | |
根据经纬度计算距离 | |
:param longitude1: 经度1 | |
:param latitude1: 纬度1 | |
:param longitude2: 经度2 | |
:param latitude2: 纬度2 | |
:return: 返回为km单位 保留两位小数 | |
""" | |
latitude1 = (math.pi / 180.0) * latitude1 | |
latitude2 = (math.pi / 180.0) * latitude2 | |
longitude1 = (math.pi / 180.0) * longitude1 | |
longitude2 = (math.pi / 180.0) * longitude2 | |
# 因此AB两点的球面距离为:{arccos[sina*sinx+cosb*cosx*cos(b-y)]}*R (a,b,x,y) | |
# 地球半径 | |
R = 6378.1 | |
temp = math.sin(latitude1) * math.sin(latitude2) + \ | |
math.cos(latitude1) * math.cos(latitude2) * math.cos(longitude2 - longitude1) | |
if float(repr(temp)) > 1.0: | |
temp = 1.0 | |
d = math.acos(temp) * R | |
return round(d, 2); | |
if __name__ == '__main__': | |
# result, total = station_nearby_list(distance=4, latitude=28.6712732625, longitude=115.8807849884) | |
print(cal_dis(longitude1=115.860788, latitude1=28.698319, longitude2=115.859198, latitude2=28.682587)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment