计算一组坐标(纬度,经度)之间的地理距离

5
我正在编写一个 Flask 应用程序,使用从 GPS 传感器中提取的一些数据。我能在地图上绘制路径,并想计算 GPS 传感器行驶的距离。一种方法是只获取起点和终点坐标,但由于传感器行驶的方式,这种方法相当不准确。因此,我对每 50 个传感器样本进行采样。如果实际传感器样本大小为 1000,则现在将有 20 个样本(通过提取每 50 个样本)。
现在,我希望能够通过一个函数来计算我的样本列表的距离。到目前为止,我已经能够使用 geopy 包,但当我采用大量 GPS 样本集时,我会收到“请求过多”的错误,更不用说我还会有额外的处理时间来处理这些请求,这不是我想要的。
是否有更好的方法来计算包含纬度和经度坐标的列表元素的累积距离?
我找到了很多不同数学方法的计算距离的方式,仅使用 2 个坐标(lat1、lng1 和 lat2 和 lng2),但没有支持坐标列表的方法。
下面是我当前使用 geopy 的代码: positions = [(lat_1, lng_1), (lat_2, lng_2), ..., (lat_n, lng_n)]
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 中的 positions 对象是元组坐标的列表,如上图所示。

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

所以你想知道每个点之间的距离? - ebeneditos
是的。或者,我想要所有距离的总和。 - Zeliax
2个回答

4
以下是我最终使用的解决方案。如果您想要自己查看该函数的作用,它被称为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

0

我建议将你的(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)元组转换为一个单一的复数c1 = lat_1 + j*lng_1,并创建一个由[c1, c2, ..., cn]形成的列表。
总而言之,复数是一个二维数字,因此如果您有2D坐标,这样做是完美的地理定位,但对于3D空间坐标来说则不可能。
一旦得到了这个,您可以轻松计算两个复数c1和c2之间的距离,如dist12 = abs(c2 - c1)。递归执行此操作可获得总距离。
希望这能帮到您!

谢谢你的回答。我会在我的代码上测试一下看看是否按照预期工作。但是 complex 是什么意思? - Zeliax
1
你有一个(x,y)坐标,当你将其转换成复数时,你会得到一个单一的数字x + yi。例如,位置(1,2)将被转换为复数1 + 2i,这样更容易处理。然而,这只适用于二维点,因此对于地理定位工作! - ebeneditos
我并不是很理解其中的“复杂”数学。虽然我听过很多关于它的讲座,但我从未真正有过那种“恍然大悟”的经历。但我会尝试一下,如果它有效的话,那就太棒了。再次感谢你;) - Zeliax
是的。太好了。我刚刚注意到你把 distance = 0 移到了函数更深的位置,并删除了我写的愚蠢的“列表末尾”的 if 语句。还进行了不错的优化 ;) - Zeliax
好的,我完成了编辑,有一个小错误。现在试试看,对我来说它可以工作! - ebeneditos
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接