Python 基于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的新手,无助地迷失了方向

我在Django中有一个位置感知服务器,它应该只在用户位于数据库条目的给定半径内时返回数据。。我在python中发现了一个代码片段,它在网上(这里或其他地方,我真的不记得了)就可以做到这一点。当我在坐标为0,0的情况下对它进行测试时,它似乎起到了作用,而当我设置两个不同的坐标时,它就不起作用了。我现在有一个数据库条目,它位于我当前位置300米以内,半径设置为10公里,但出于某种原因,服务器没有将结果返回给我。这段代码哪里出了问题,因为我完全不知道如何修复它,是python的新手,无助地迷失了方向,在我的项目到期前的5天内离开了haversine。 以下是我的基于haversine的查询代码:

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..我最终找到了一个解决办法..用答案更新