noa*_*ale 9 python django haversine
我有以下型号.
class Location(models.Model):
name = models.CharField(max_length = 128, blank = True)
address =models.CharField(max_length = 200, blank= True)
latitude = models.DecimalField(max_digits=6, decimal_places=3)
longitude = models.DecimalField(max_digits=6, decimal_places=3)
def __unicode__(self):
return self.name
Run Code Online (Sandbox Code Playgroud)
如果我目前的纬度和经度是:
current_lat = 43.648
current_long = 79.404
Run Code Online (Sandbox Code Playgroud)
我做了一些研究并遇到了Haversine方程,它计算了两个位置坐标之间的距离.以下是我发现的等式:
import math
def distance(origin, destination):
lat1, lon1 = origin
lat2, lon2 = destination
radius = 6371 # km
dlat = math.radians(lat2-lat1)
dlon = math.radians(lon2-lon1)
a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \
* math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
d = radius * c
return d
Run Code Online (Sandbox Code Playgroud)
我想返回半径10公里范围内的所有位置对象,如何过滤它只会返回落在这10公里范围内的所有位置对象?
LocationsNearMe = Location.objects.filter(#This is where I am stuck)
Run Code Online (Sandbox Code Playgroud)
无论如何,我可以将Haversine方程实现到滤波中,以便它只返回半径10公里范围内的位置对象吗?
我正在寻找一个详细的答案.感谢帮助.
Bri*_*ian 11
你可以用filter.做范围查询.
LocationsNearMe = Location.objects.filter(latitude__gte=(the minimal lat from distance()),
latitude__lte=(the minimal lat from distance()),
(repeat for longitude))
Run Code Online (Sandbox Code Playgroud)
不幸的是,这会以几何方形(而不是圆形)的形式返回结果
and*_*abs 10
但是你总是可以通过过滤前一步骤中的结果(可能是较小的子集)来更好地通过Brian方法提出建议,并且每次检查它们是否在半径范围内.
您的用户处于黑点.Brian给出的平方近似值返回绿色,但也返回橙色点.在最坏的情况下,距离的差异可能是显着的,用户必须比预期的更多(比额外的40%)达到sqrt(2)倍.因此,对于所有橙色和绿色点,有必要检查它们与黑点的距离(例如,如果这是真正的短距离,例如欧几里德,例如城市中的导航)不大于假定半径.

更新:
如果您想使用Haversine距离或(更好)提到GeoDjango hava,请查看此片段,比较两个处理附近搜索的django视图:
https://gist.github.com/andilabs/4232b463e5ad2f19c155
如果你不想使用GeoDjango,那么你可以考虑用Django的数据库函数来写出来。与原始 SQL 相比,这还为您提供了能够轻松附加/前置其他 ORM 过滤器的优势。
from django.db.models.functions import Radians, Power, Sin, Cos, ATan2, Sqrt, Radians
from django.db.models import F
dlat = Radians(F('latitude') - current_lat)
dlong = Radians(F('longitude') - current_long)
a = (Power(Sin(dlat/2), 2) + Cos(Radians(current_lat))
* Cos(Radians(F('latitude'))) * Power(Sin(dlong/2), 2)
)
c = 2 * ATan2(Sqrt(a), Sqrt(1-a))
d = 6371 * c
LocationsNearMe = Location.objects.annotate(distance=d).order_by('distance').filter(distance__lt=10)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5386 次 |
| 最近记录: |