You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.5 KiB
50 lines
1.5 KiB
from math import radians
|
|
|
|
from django.db.models import F, Value
|
|
from django.db.models.functions import Radians, Sin, ATan2, Sqrt, Cos
|
|
|
|
|
|
def calculate_distance(qs, client_lat: float, client_lon: float):
|
|
"""
|
|
Based on stackoverflow question: https://stackoverflow.com/a/19412565/10261581
|
|
Distance Unit is in Kilometres
|
|
|
|
R = 6373.0
|
|
|
|
lat1 = radians(52.2296756)
|
|
lon1 = radians(21.0122287)
|
|
lat2 = radians(52.406374)
|
|
lon2 = radians(16.9251681)
|
|
|
|
dlon = lon2 - lon1
|
|
dlat = lat2 - lat1
|
|
|
|
a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
|
|
c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
|
|
|
distance = R * c
|
|
|
|
print("Result: ", distance)
|
|
print("Should be: ", 278.546, "km")
|
|
"""
|
|
earth_radius = 6373.0
|
|
|
|
client_lat, client_lon = radians(float(client_lat)), radians(float(client_lon))
|
|
if not client_lat:
|
|
return qs.annotate(
|
|
distance=Value(0),
|
|
)
|
|
|
|
return qs.annotate(
|
|
rlat=Radians('latitude'),
|
|
rlon=Radians('longitude'),
|
|
|
|
# a=sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
|
|
# c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
|
lat_diff=F('rlat') - client_lat,
|
|
lon_diff=F('rlon') - client_lon,
|
|
a=Sin(F('lat_diff') / 2.0) ** 2.0 + Cos(client_lat) * Cos(F('rlat')) * Sin(
|
|
F('lon_diff') / 2.0) ** 2.0,
|
|
c=2.0 * ATan2(Sqrt(F('a')), Sqrt(1.0 - F('a'))),
|
|
distance=F('c') * earth_radius
|
|
)
|