У меня есть целевая пара координат (широта, долгота) и список других пар координат. Единицы указаны в десятичных градусах.
Я хотел бы найти пару, ближайшую к цели, а не на расстояние, так что чисто для сравнения.
Точнее, я хотел бы знать, насколько простой расчет я могу использовать/или какой самый быстрый метод?
Мне нужна точность до 10 м, и я бы не хотел использовать для этого модули.
Сначала я думал, что это будет легко, например.
coord_set = [{lat, long}, {..}]
target_lat = 20.1234
target_long = -120.5678
pair1 = abs(target_lat - coord_set[0][lat]) + abs(target_long - coord_set[0][long])
pair2 = abs(..) + abs(..)
if pair1 < pair2:
closest = coord_set[0]
...
Я подумал, что, возможно, я мог бы просто сравнить итоги, т.е.
total = target_lat + target_long
(total - (pair1[lat] + pair1[long])) > (total - (pair2[lat] + pair2[long]))
Но я обнаружил, что у этого есть некоторые проблемы.
Наконец я обнаружил, что мне следует использовать евклидово расстояние (мне не нужно расстояние по Большому кругу, поскольку эти координаты обычно находятся на расстоянии менее 2-3 км друг от друга).
Я нашел это ТАК Ответ отметив, что сравнения не обязательно должны иметь квадратный корень, поскольку расстояние не требуется.
**Но тогда я спрашиваю, зачем вообще их выравнивать? ** Упрощение -
pair1 = ((lat - pair1[lat])**2 + (long - pair1[long])**2)**(1/2)
pair2 = ((lat - pair2[lat])**2 + (long - pair2[long])**2)**(1/2)
К этому
pair1 = (lat - pair1[lat])**2 + (long - pair1[long])**2
pair2 = (lat - pair2[lat])**2 + (long - pair2[long])**2
Наконец, это, по сути, то, с чего я начал
pair1 = (lat - pair1[lat]) + (long - pair1[long])
pair2 = (lat - pair2[lat]) + (long - pair2[long])
Это потому, что это 2D-плоскость? Или мне следует использовать его для большей точности?
Я изо всех сил пытаюсь визуализировать это на графике, поэтому не могу понять, почему для моей проблемы мне следует использовать евклидово расстояние.
@lastchance Спасибо, это добавляет ясности и хороший момент сократить некоторые вычисления в последнем предложении (извините, я не могу проголосовать за него, но +1)






Основная проблема с добавлением смещения по долготе к смещению по широте заключается в том, что эти два числа подписаны.
Если взять сумму двух, можно предположить, что отрицательное смещение по долготе будет противодействовать положительному смещению по широте.
Например, если целью является (0,0), то (1,-1) должно быть на некотором расстоянии, однако, если вы просто возьмете итоговые значения без возведения в квадрат, они кажутся совпадающими.
Вам нужно использовать возведение в квадрат для расстояний, поскольку оно правильно подчеркивает, что (0,2) дальше, чем (1,1).
Это объясняет проблему, с которой я столкнулся при использовании метода суммирования, и дает повод для возведения в квадрат, спасибо! +1
Вам обязательно следует установить геодезическую библиотеку, чтобы иметь точные результаты для тестирования: в вашем случае вы можете сделать много упрощений, а может и нет. Это действительно зависит от требуемой точности, расстояния, а также от крайних широт (вблизи полюсов вы не можете слишком упрощать), поэтому общие ответы непрактичны, особенно если вы ищете скорость.
Затем я бы вычислил разницу широты и долготы, умножил оба фактора (зависит от широты и долготы) и использовал нормальные декартовы координаты (корень из суммы квадратов каждого компонента дельта-координаты). Таким образом, вы должны иметь хорошую точность (в зависимости от того, насколько точно вы выбираете факторы).
Хитрость заключается в том, чтобы выбрать факторы, математические данные и подробности вы увидите в https://en.wikipedia.org/wiki/Geographic_coordinate_system#Length_of_a_grade (и в двух связанных статьях: одна о широте, другая о долготе). Возможно, всего несколько значений и интерполяция должны быть достаточно хорошими (больше элементов для большей точности, и в любом случае поиск в таблице должен быть быстрым или, в конечном итоге, для большей точности формулы, но это будет медленно и, вероятно, не понадобится). По этой причине вам необходимо установить геодезическую библиотеку, чтобы быстро проверить точность. Вы будете впечатлены тем, насколько точными будут результаты при небольшом количестве данных.
Примечание: такой метод работает только в континентальном масштабе (лучше в пределах 10 градусов), но не вблизи полюсов (действительно вблизи).
Спасибо за это, мне определенно стоит задуматься, если я масштабирую расчеты на более крупные области, особенно с точки зрения точности и причин использовать некоторые библиотеки.
В ваших рассуждениях есть некоторые математические нестыковки.
Я хотел бы найти пару, ближайшую к цели, а не на расстоянии, так чисто сравнение.
Нахождение пары координат, ближайшей к цели, математически представляет собой пару, которая находится на кратчайшем расстоянии от цели. Итак, это само расстояние.
Квадратный корень — это монотонно возрастающая функция, поэтому для сравнения расстояний вам действительно не обязательно использовать квадратный корень. Таким образом, ваше первое упрощение математически корректно, а второе — нет. Как упомянул Нил в первом ответе, широта и долгота являются знаковыми значениями! Итак, вы не можете «упростить», удалив квадраты.
Вот пример:
target = (0, 0)
pair_1 = (-1, 1)
pair_2 = (1, 1)
Тогда квадраты расстояний будут равны:
squared_distance_pair_1 = (0-(-1))**2 + (0-1)**2 = 1 + 1 = 2
squared_distance_pair_2 = (0-1)**2 + (0-1)**2 = 1 + 1 = 2
Итак, вы видите, что обе точки равноудалены от цели (в данном случае начала координат). Если вы нарисуете эти точки, вы легко увидите, что это правда.
Но если вы вставите эти значения во второе выражение упрощения:
pair1 = (lat - pair1[lat]) + (long - pair1[long])
pair2 = (lat - pair2[lat]) + (long - pair2[long])
вы получите:
pair1 = (0 - (-1)) + (0 - 1) = 0
pair2 = (0 - 1) + (0 - 1) = -2
который не дает вам никакой информации о расстоянии.
В заключение вам нужно вычислить все расстояния и найти самое короткое. И имейте в виду, что у вас может быть более одной точки на одном и том же кратчайшем расстоянии от целевой точки:
coords = [(lat, long), ...]
target_lat = 2.0
target_long = -3.0
distances = [(c[0] - target_lat)**2 + (c[1] - target_long)**2 for c in coords]
shortest_distance = min(distances)
closest_pairs = [coords[i] for i, d in enumerate(distances) if d == shortest_distance]
Я написал это так, потому что вы сказали, что не хотите использовать какие-либо внешние библиотеки, но для повышения производительности вы можете хотя бы использовать numpy.
С наилучшими пожеланиями.
Спасибо, что раскрыли это и объяснили! У меня возникли некоторые проблемы с корреляцией знаковости и возведения в квадрат, но это моя собственная проблема. Думаю, я понял, что, поскольку он двумерный, мне нужно его возвести в квадрат? Но для меня это в основном имеет смысл, так что большое спасибо. Не могли бы вы объяснить разницу с абсолютированием? Или возведение в квадрат просто быстрее? Или может быть, абсолютизация в данном случае работает, а в более сложных уравнениях — нет? Или точность? Извините, мои познания в математике весьма ограничены!
Представьте себе прямоугольный треугольник: гипотенуза НЕ является суммой двух других сторон, а квадрат гипотенузы представляет собой сумму квадратов. В конечном итоге вам придется возвести в квадрат... Однако вы можете использовать неквадратные расстояния - а иногда просто широту или длинну, чтобы исключить точки, которые явно не находятся на минимальном расстоянии.