Python 基于Haversine的服务器仅在坐标完全匹配时返回数据
我在Django中有一个位置感知服务器,它应该只在用户位于数据库条目的给定半径内时返回数据。。我在python中发现了一个代码片段,它在网上(这里或其他地方,我真的不记得了)就可以做到这一点。当我在坐标为0,0的情况下对它进行测试时,它似乎起到了作用,而当我设置两个不同的坐标时,它就不起作用了。我现在有一个数据库条目,它位于我当前位置300米以内,半径设置为10公里,但出于某种原因,服务器没有将结果返回给我。这段代码哪里出了问题,因为我完全不知道如何修复它,是python的新手,无助地迷失了方向,在我的项目到期前的5天内离开了haversine。 以下是我的基于haversine的查询代码:Python 基于Haversine的服务器仅在坐标完全匹配时返回数据,python,django,django-rest-framework,haversine,location-aware,Python,Django,Django Rest Framework,Haversine,Location Aware,我在Django中有一个位置感知服务器,它应该只在用户位于数据库条目的给定半径内时返回数据。。我在python中发现了一个代码片段,它在网上(这里或其他地方,我真的不记得了)就可以做到这一点。当我在坐标为0,0的情况下对它进行测试时,它似乎起到了作用,而当我设置两个不同的坐标时,它就不起作用了。我现在有一个数据库条目,它位于我当前位置300米以内,半径设置为10公里,但出于某种原因,服务器没有将结果返回给我。这段代码哪里出了问题,因为我完全不知道如何修复它,是python的新手,无助地迷失了方向
class StoreList(generics.ListAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
serializer_class = StoreSerializer
def get_queryset(self):
lat = self.request.query_params.get('lat', None)
lon = self.request.query_params.get('lng', None)
if lat and lon:
lat = float(lat)
lon = float(lon)
# Haversine formula = https://en.wikipedia.org/wiki/Haversine_formula
lat1 = math.radians(lat) # lat in radians
lng1 = math.radians(lon) # lng in radians
lat2 = math.asin(math.sin(lat1)*math.cos(distance/R) +
math.cos(lat1)*math.sin(distance/R)*math.cos(bearing))
lng2 = lng1 + math.atan2(math.sin(bearing)*math.sin(distance/R)*math.cos(lat1),
math.cos(distance/R)-math.sin(lat1)*math.sin(lat2))
lat2 = math.degrees(lat2)
lng2 = math.degrees(lng2)
return Store.objects.filter(latitude__gte=lat1, latitude__lte=lat2)\
.filter(longitude__gte=lng1, longitude__lte=lng2)
此图显示已收到请求,坐标正确,但结果集仍然为空:(
看起来您通过的是
lat1
和lng1
弧度,但lat2
和lng2
度。(您将lat1
和lng1
转换为弧度,但从未将其更改回度。)看起来你通过的是以弧度表示的lat1
和lng1
,但以度表示的lat2
和lng2
(你将lat1
和lng1
转换为弧度,但从未将它们改回度。)切换到postgresql这样的位置感知数据库会容易得多(使用postgis扩展)或mysql 5.7。如果您查看与某个点有给定距离的对象,对于这样一个数据库来说,这是一个微不足道的查询,并且
Dwithin返回模型,其中到几何体字段的距离
查找几何图形彼此之间的距离在给定范围内。
请注意,仅当目标对象
几何图形位于投影系统中。对于地理几何图形,您可以
应使用几何字段的单位(例如WGS84的度数)
例如:
Zipcode.objects.filter(poly_uudwithin=(geom,D(m=5))
这样,您的复杂代码就变成了一行代码。地理空间数据库中有很多功能,您会发现这些功能非常有用。切换到位置感知数据库(如postgresql(带有postgis扩展)会容易得多或者mysql 5.7。如果您查看与某个点有给定距离的对象,这对于这样的数据库来说是一个微不足道的查询,并且 Dwithin返回模型,其中到几何体字段的距离 查找几何图形彼此之间的距离在给定范围内。 请注意,仅当目标对象 几何图形位于投影系统中。对于地理几何图形,您可以 应使用几何字段的单位(例如WGS84的度数) 例如:
Zipcode.objects.filter(poly_uudwithin=(geom,D(m=5))
因此,您的复杂代码就变成了一行代码。地理空间数据库中有很多功能,您会发现它们非常有用。因此..我发现了算法的错误之处..感谢@ncole458的帖子 以下是功能齐全的服务器代码:
class StoreList(generics.ListAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
serializer_class = StoreSerializer
def get_queryset(self):
lat = self.request.query_params.get('lat', None)
lon = self.request.query_params.get('lng', None)
if lat and lon:
lat = float(lat)
lon = float(lon)
# Haversine formula = https://en.wikipedia.org/wiki/Haversine_formula
"""
lat1 = math.radians(lat) # lat in radians
lng1 = math.radians(lon) # lng in radians
lat2 = math.asin(math.sin(lat1)*math.cos(distance/R) +
math.cos(lat1)*math.sin(distance/R)*math.cos(bearing))
lng2 = lng1 + math.atan2(math.sin(bearing)*math.sin(distance/R)*math.cos(lat1),
math.cos(distance/R)-math.sin(lat1)*math.sin(lat2))
lat1 = math.degrees(lat1)
lat2 = math.degrees(lat2)
lat2 = math.degrees(lat2)
lng2 = math.degrees(lng2)
"""
lat1 = lat - math.degrees(distance / R)
lat2 = lat + math.degrees(distance / R)
lng1 = lon - math.degrees(distance / R / math.cos(math.degrees(lat)))
lng2 = lon + math.degrees(distance / R / math.cos(math.degrees(lat)))
return Store.objects.filter(latitude__gte=lat1, latitude__lte=lat2)\
.filter(longitude__gte=lng1, longitude__lte=lng2)
所以..我发现了算法哪里出了问题..多亏了@ncole458的帖子 以下是功能齐全的服务器代码:
class StoreList(generics.ListAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
serializer_class = StoreSerializer
def get_queryset(self):
lat = self.request.query_params.get('lat', None)
lon = self.request.query_params.get('lng', None)
if lat and lon:
lat = float(lat)
lon = float(lon)
# Haversine formula = https://en.wikipedia.org/wiki/Haversine_formula
"""
lat1 = math.radians(lat) # lat in radians
lng1 = math.radians(lon) # lng in radians
lat2 = math.asin(math.sin(lat1)*math.cos(distance/R) +
math.cos(lat1)*math.sin(distance/R)*math.cos(bearing))
lng2 = lng1 + math.atan2(math.sin(bearing)*math.sin(distance/R)*math.cos(lat1),
math.cos(distance/R)-math.sin(lat1)*math.sin(lat2))
lat1 = math.degrees(lat1)
lat2 = math.degrees(lat2)
lat2 = math.degrees(lat2)
lng2 = math.degrees(lng2)
"""
lat1 = lat - math.degrees(distance / R)
lat2 = lat + math.degrees(distance / R)
lng1 = lon - math.degrees(distance / R / math.cos(math.degrees(lat)))
lng2 = lon + math.degrees(distance / R / math.cos(math.degrees(lat)))
return Store.objects.filter(latitude__gte=lat1, latitude__lte=lat2)\
.filter(longitude__gte=lng1, longitude__lte=lng2)
我希望我可以,但我没有使用mysql的vcvar.bat,我想但不能,因为vcvar缺少错误我希望我可以,但我没有使用mysql的vcvar.bat,我想但不能,因为vcvar缺少错误,我有,但结果集仍然是empty@CoolBeans当前位置如果不知道发生了什么,就很难知道发生了什么你的数据库。再次查看你的代码,看起来你正在检查纬度大于
lat1
——但lat1
不是你原始点的纬度吗?看起来你想使用哈弗森计算两个新的纬度和经度(对于NSEW边界),而不是传递原始点的lat/long。Tanks..我最终设法找到了一个解决方法..用答案进行了更新,但结果集仍然是empty@CoolBeans:如果不知道数据库中有什么内容,就很难知道发生了什么。再次查看代码,看起来您正在检查纬度为i的点s大于lat1
——但不是lat1
原点的纬度吗?似乎你想用哈弗森计算两个新的纬度和经度(对于NSEW边界),而不是通过原点的lat/long。Tanks..我最终找到了一个解决办法..用答案更新