Python расстояние в милях до евклидова расстояния между двумя координатами gps

#python #gis

#python #гис

Вопрос:

Я пытаюсь придумать функцию, где…
Ввод: геодезическое расстояние в милях или км
Вывод: евклидово расстояние между любыми двумя точками gps, которые находятся на расстоянии ввода друг от друга

Я чувствую, что у меня есть некоторые компоненты

 import numpy as np
from numpy import linalg as LA
from geopy.distance import geodesic

loc1 = np.array([40.099993, -83.166000])
loc2 = np.array([40.148652, -82.903962])
  

Это евклидово расстояние между этими двумя точками

 LA.norm(loc1-loc2)
#0.2665175636332336
  

Это геодезическое расстояние в милях между этими двумя точками

 geodesic(loc1,loc2).miles
#14.27909749425243
  

У моего мозга сейчас не хватает сока, у кого-нибудь есть идеи о том, как я могу создать такую функцию, как:

 geodesic_to_euclidean(14.27909749425243)
#0.2665175636332336
  

Комментарии:

1. Вам нужно расстояние дуги, соединяющей две геолокации, предполагая, что поверхность земли представляет собой сферу?

2. Я смотрю только на диапазоны в пределах 50 миль, поэтому я думаю, что было бы справедливо предположить даже плоскую поверхность?

3. LA.norm в любом случае не даст вам правильного значения, потому что вы не работаете с декартовыми координатами. вам нужно вычислить угол между двумя точками относительно центра земли (в радианах), затем умножить на радиус земли.

4. Итак, я использую евклидово расстояние в качестве параметра в алгоритме кластеризации DBSCAN. Единственными измерениями, вводимыми в алгоритм, являются широта и долгота. Поэтому мне не нужно евклидово расстояние для представления чего-либо реального, просто 2-нормальное расстояние между любыми двумя векторами. Это проблематично ?… Я новичок в ГИС…

5. @Jamalan вы теряете точность, чем ближе вы подходите к полюсам. По этой же причине картографическая проекция Меркатора раздувает Антарктиду намного больше, чем она есть на самом деле.

Ответ №1:

Если вас устраивает расстояние по большому кругу, как указано в комментариях, то это должно сработать. Это расстояние haversine:

 def haversine(origin, destination, units='mi'):
    # Radian deltas
    origin_lat = radians(float(origin[0]))
    origin_lon = radians(float(origin[1]))
    destination_lat = radians(float(destination[0]))
    destination_lon = radians(float(destination[1]))
    lat_delta = destination_lat - origin_lat
    lon_delta = destination_lon - origin_lon

    # Radius of earth in meters
    r = 6378127

    # Haversine formula
    a = sin(lat_delta / 2) ** 2   cos(origin_lat) * 
        cos(destination_lat) * sin(lon_delta / 2) ** 2
    c = 2 * asin(sqrt(a))
    meters_traveled = c * r

    scaling_factors = {
        "m:": 1,
        "km": 1 / 1000,
        "ft": 3.2808,  # meters to feet
        "mi:": 0.000621371  # meters to miles
    }

    return meters_traveled * scaling_factors[units]

  

Если у вас уже есть геодезическое (большое окружное) расстояние в метрах и вам нужна длина хорды, вы можете сделать следующее

 def chord(geodesic_distance):
    """
    Chord length
    C = 2 * r * sin(theta/2)

    Arc length; which is geodesic distance in this case
    AL = R * theta

    therefore
    C = 2 * R * sin(AL/(2*R))
    """
    r = 6378127  # Radius of earth in meters

    return 2 * r * sin(geodesic_distance / (2 * r))
  

Комментарии:

1. для справки: Формула haversine определяет расстояние по большому кругу между двумя точками на сфере с учетом их долготы и широты.

2. @Jamalan определенно не равномерно распределенная сетка. Я знаю, что это может показаться не тем, о чем вы думаете в своей голове, но то, что вы говорите, — это спросить разницу в длине между хордой и дугой с одинаковым углом. Для малых углов (небольших расстояний по отношению к радиусу земли) эта разница будет минимальной.

3. @Jamalan c этот угол уже в радианах. просто умножьте на 180 / пи

4. @Jamalan пожалуйста, посмотрите приведенное выше редактирование длины аккорда. Хотя Аарон прав — для близлежащих расстояний на поверхности Земли это будет минимально отличаться

5. Вы, ребята, потрясающие. Это хорошая часть stack overflow. Не циничные, просто полезные люди. Огромное вам обоим спасибо. Я преобразоваю вашу мудрость и код в изящную вспомогательную функцию.