Алгоритм пошуку найближчої точки


18

У мене є список кількох сотень міст з їх широтою / довготою. Враховуючи інше місце розташування (також у лат. / Довгий), мені потрібно знайти найближче місто.

Оскільки я не використовую жодного ГІС, на сьогодні очевидним алгоритмом є створення циклу для всіх міст, обчислення відстані між точками.

Зробити цикл для мене практично, але є якийсь простий втілити алгоритм, щоб досягти цього більш ефективно? Або якась легка бібліотека Java, яка може допомогти вирішити це?

Примітки . Мені не потрібно / хочу повноцінного рішення GIS або важкої / складної бібліотеки. Я віддаю перевагу менш хорошому, але найпростішому і легшому рішенню, тому що це єдине, що мені потрібно вирішити.


Тож не має значення, що відстань не буде правильною? І ви не хочете рахувати дороги, які можуть зробити одне місто далі за інше (діагональ проти площі)?
Бред Несом

Так, дороги для мене не важливі. Мені потрібне найближче місто на лінійній відстані, тому що це для прогнозів погоди.
lujop

1
Прогнози погоди? Сподіваюся, у вас є суперкомп'ютер та персонал навчених метеорологів.
Майкл Тодд

Прогнози зроблені Майклом, тільки я повинен взяти найближчий :)
lujop

Відповіді:


24

Я саме досліджував це питання 20 років тому, коли розробляв настільний ГІС. Нам потрібно було інтерактивно знаходити відстані «точка-точка»; нашою метою було зробити обчислення за менше ніж 1/2 секунди на тисячі точок. Тестування (на 25 МГц 486 ПК!) Показало, що ми можемо обчислити всі відстані, точно так, як ви описуєте (за допомогою простого очевидного алгоритму), так швидко, що не було сенсу створювати більш складне рішення, наприклад, квадратна структура .

Для обчислення відстаней до однієї точки "зонда" ваші варіанти включають: (а) проектування всіх точок, використовуючи рівновіддалену проекцію, орієнтовану в точці зонда, або (b) прийняття сферичної моделі землі та використання формули Гаверсіна . Перший доречний, якщо вам потрібна точність еліпсоїдальної моделі. У будь-якому випадку обчислення досить швидкі, ймовірно, забираючи менше 1000 тиків: ви можете запитувати близько мільйона балів в секунду за допомогою одного процесора.

Досить швидко для вас? Якщо ні, метод грубої сили легко паралелізується і масштабується безпосередньо з кількістю процесорів: просто розділіть точки між процесорами, а потім зробіть остаточне порівняння найближчого, знайденого кожним процесором.

Якщо вам потрібно пройти швидше, ви можете використовувати різні наближення до точок екрана. Наприклад, якщо ви знаходитесь в межах від -88 до +88 градусів широти, а найближча знайдена поки що точка знаходиться на відстані 200 км, то будь-яка точка, широта якої відрізняється від ширини зонда більш ніж на 2 градуси, не може бути ближчою (тому що в будь-якому місці землі, один градус широти перевищує близько 110 км). У багатьох випадках такий вид попереднього екранування може давати вам змогу обробляти сотні мільйонів балів в секунду.


1
Для обговорення формули геверсину див. Gis.stackexchange.com/q/4906/664
whuber

4

Я погоджуюся з іншими, що простий цикл повинен бути ефективним для «кількох сотень міст».

З огляду на вашу заявку, розгляд еліпсоїдальних відстаней, ймовірно, є великим надмірним рівнем - ви, мабуть, маєте справу з прогнозами погоди, місцевість яких навряд чи до кількох метрів. Сферична геометрія досить проста, щоб ви могли легко це зробити у своєму циклі.

Це може бути ще простіше (наприклад, використовувати delta lat як y і delta lon * cos (lat) як x і знайти мінімум x ^ 2 + y ^ 2). Ви використовуєте косинус цільової широти, який ви обчислюєте лише один раз. Це буде дедалі неточнішим для віддалених міст, але їх все одно буде відхилено, тому не важливо. Якщо припустити, що ваше найближче місто, як правило, знаходиться в межах декількох сотень кілометрів, шанси на інший результат (найближче місто), використовуючи це проти використання більш точної формули, досить малі і виникатимуть лише тоді, коли відмінності досить малі, що "прогноз більше точний ", ймовірно, залежатиме від інших факторів у будь-якому випадку (тобто: втрачений шум).

Якщо ви не використовуєте вбудовану систему або повільний перекладач, ви, мабуть, можете дозволити собі просто використовувати сферичні формали, які пропонують інші, тхо.


1

Це на додаток до вже сказаного, але я думав, що зазначу важливість вибору відповідної структури даних. Я написав власний код для K-Function в .NET і виявив, що за допомогою ефективних колекцій значно покращився. Вибачте, я не знаю позначення O для точних швидкостей. Я використовував два словники для координат x і y з ідентифікатором точки в якості ключа. Я не знаю Java, тому я нічого не міг запропонувати.

Ура, Давид

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.