【问题标题】:Calculating geographic distance between a list of coordinates (lat, lng)计算坐标列表之间的地理距离(lat,lng)
【发布时间】:2017-05-05 10:53:19
【问题描述】:

我正在编写一个烧瓶应用程序,使用从 GPS 传感器中提取的一些数据。我能够在地图上绘制路线,并且我想计算 GPS 传感器行进的距离。一种方法可能是只获取开始和结束坐标,但是由于传感器的行进方式,这是非常不准确的。因此,我对每 50 个传感器样本进行采样。如果实际传感器样本大小为 1000,我现在将有 20 个样本(通过提取每 50 个样本)。

现在我希望能够将我的样本列表通过一个函数来计算距离。到目前为止,我已经能够使用包 geopy,但是当我采用大型 gps 样本集时,我确实收到“请求过多”错误,更不用说处理请求时我会有额外的处理时间,这不是我想要。

有没有更好的方法来计算包含经纬度坐标的列表元素的累积距离?

positions = [(lat_1, lng_1), (lat_2, lng_2), ..., (lat_n, lng_n)]

我找到了许多仅使用 2 个坐标(lat1、lng1 和 lat2 和 lng2)计算距离的不同数学方法的方法,但没有一个支持坐标列表。

这是我当前使用 geopy 的代码:

from geopy.distance import vincenty

def calculate_distances(trips):
    temp = {}
    distance = 0
    for trip in trips:
        positions = trip['positions']
        for i in range(1, len(positions)):
            distance += ((vincenty(positions[i-1], positions[i]).meters) / 1000)
            if i == len(positions):
                temp = {'distance': distance}
                trip.update(temp)
                distance = 0

trips 是一个列表元素,其中包含有关旅行的信息(持续时间、距离、开始和停止坐标等)的键值对字典,而trips 中的位置对象是一个元组坐标列表,如上图所示.

trips = [{data_1}, {data_2}, ..., {data_n}]

【问题讨论】:

  • 所以你想要每个点之间的距离?
  • 是的。或者好吧,我想要所有距离的总和。

标签: python gps distance


【解决方案1】:

我建议您将 (x, y) 坐标转换为复数,因为计算距离更容易计算。因此,以下功能应该可以工作:

def calculate_distances(trips):
    for trip in trips:
        positions = trip['positions']
        c_pos = [complex(c[0],c[1]) for c in positions]
        distance = 0
        for i in range(1, len(c_pos)):
            distance += abs(c_pos[i] - c_pos[i-1])
        trip.update({'distance': distance})

我正在做的是将每个(lat_1, lng_1) touple 转换为单个复数c1 = lat_1 + j*lng_1,并创建一个由[c1, c2, ... , cn] 组成的列表。

总而言之,复数是一个二维数,因此,如果您有 2D 坐标,您就可以做到这一点,这对于地理定位来说是完美的,但对于 3D 空间坐标则不可能,例如.

一旦你得到这个,你可以很容易地计算出两个复数c1c2 之间的距离为dist12 = abs(c2 - c1)。递归执行此操作可获得总距离。

希望这有帮助!

【讨论】:

  • 感谢您的回答。我会检查它是否按我的代码的预期工作。但是复杂有什么作用呢?
  • 您有一个 (x, y) 坐标,当您将其转换为复数时,您只需 x + yi 的单个数字。因此,例如,位置 (1, 2) 将转换为复数 1 + 2i,这更容易管理。但是,这只能针对 2D 点进行,因此对于地理定位有效!
  • 我不太了解其中的“复杂”数学。我确实有很多关于它的讲座,但我从来没有真正有过那种“啊哈”的经历。但我会给它一个旋转,如果它有效,那就太棒了。不过还是非常感谢;)
  • 是的。甜的。我刚刚注意到您将distance = 0 进一步移动到函数中,并删除了我拥有的愚蠢的“列表末尾”语句。优化也不错;)
  • 好的,我编辑完成了,有点错误。立即尝试,对我有用!
【解决方案2】:

这是我最终使用的解决方案。如果您想查看它为自己做了什么,它被称为Haversine(距离)函数。

我也稍微改变了我的方法。我的输入(positions)是一个元组坐标列表:

def calculate_distance(positions):
    results = []
    for i in range(1, len(positions)):
        loc1 = positions[i - 1]
        loc2 = positions[i]

        lat1 = loc1[0]
        lng1 = loc1[1]

        lat2 = loc2[0]
        lng2 = loc2[1]

        degreesToRadians = (math.pi / 180)
        latrad1 = lat1 * degreesToRadians
        latrad2 = lat2 * degreesToRadians
        dlat = (lat2 - lat1) * degreesToRadians
        dlng = (lng2 - lng1) * degreesToRadians

        a = math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(latrad1) * \
        math.cos(latrad2) * math.sin(dlng / 2) * math.sin(dlng / 2)
        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
        r = 6371000

        results.append(r * c)

    return (sum(results) / 1000)  # Converting from m to km

【讨论】: