基于Haversine的服务器仅在坐标完全匹配时才返回数据

2024-10-17 06:19:41 发布

您现在位置:Python中文网/ 问答频道 /正文

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

此图像显示已收到请求,坐标正确,但结果集仍然为空:(

Server out put


Tags: 代码self服务器getmathsincosdistance
3条回答

看起来你通过的是lat1lng1弧度,但通过的是lat2lng2度。(您将lat1lng1转换为弧度,但从未将其更改回度。)

所以。。我发现算法哪里出错了。。感谢@ncole458的帖子Answer source

以下是功能齐全的服务器代码:

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)

对于您来说,切换到位置感知数据库(如postgresql(带有postgis扩展)或mysql 5.7)要容易得多。如果您查看与某个点具有给定距离的对象,那么对于这样一个数据库来说,这是一个微不足道的查询,并且是fully supported by django

Dwithin Returns models where the distance to the geometry field from the lookup geometry are within the given distance from one another. Note that you can only provide Distance objects if the targeted geometries are in a projected system. For geographic geometries, you should use units of the geometry field (e.g. degrees for WGS84) .

Example:

Zipcode.objects.filter(poly__dwithin=(geom, D(m=5)))

这样,您的复杂代码就变成了一行代码。地理空间数据库中有许多功能,您会发现这些功能相当有用。你知道吗

相关问题 更多 >