Расчет географического расстояния между списком координат (широта, долгота)

Я пишу колбу, используя некоторые данные, извлеченные из датчика GPS. Я могу нарисовать маршрут на карте и хочу рассчитать расстояние, пройденное датчиком GPS. Одним из способов может быть просто получить начальную и конечную координаты, однако из-за того, как датчик перемещается, это довольно неточно. Поэтому я делаю выборку из каждых 50 образцов датчиков. Если реальный размер выборки датчика составлял 1000, у меня теперь будет 20 выборок (путем извлечения каждых 50 выборок).

Теперь я хочу, чтобы мой список образцов можно было использовать для вычисления расстояния. До сих пор я был в состоянии использовать географию пакета, но когда я беру большие наборы образцов 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 = [{data_1}, {data_2}, ..., {data_n}]

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

Я бы порекомендовал преобразовать ваши координаты (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-координаты, которые идеально подходят для геолокации, но, например, не могут быть доступны для трехмерных пространственных координат.

Получив это, вы можете легко вычислить расстояние между двумя комплексными числами c1 а также c2 как dist12 = abs(c2 - c1), Делая это рекурсивно, вы получаете общее расстояние.

Надеюсь, это помогло!

Другие вопросы по тегам