Точка в алгоритмі багатокутника для декількох багатокутників


11

У мене є карта Google з купою багатокутників на ній.

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

Очевидним способом є запуск алгоритму "точка в полігоні" повторно для кожного багатокутника, але мені було цікаво, чи існує ефективний алгоритм для відповіді на такі запити, особливо якщо у вас є тисячі полігонів.


Я мало знаю про API Google Maps, але браузер, як правило, не найкраще місце для великих запитів. PostGIS (безкоштовно), ArcServer або Oracle Spatial, як правило, краще обробляють такі запити.
canisrufus

Мене більше цікавить алгоритм. До речі, як би ви це зробили в PostGIS.
numan

Наступний URL говорить про точку в полігоні .. (я ніколи цього не використовував) .. спробуйте .. він може дати деяку ідею. eriestuff.blogspot.com/2008/02/…

3
Ось мій обов’язковий коментар, що "точка-в-полігон" не має сенсу для точки на кулі, оскільки багатокутник на кулі просто ділить сферу на дві частини, кожна з яких має право називатися "всередині". Чи північний чи південний полюс 'всередині' багатокутника, який визначає екватор? Пам’ятайте, Lat-long не є декартовим ...
Spacedman

4
@Spaced Ви плутаєте "багатокутник" з "поліліній". Точка в полігоні має ідеальний сенс на кулі. Полігон - це більше, ніж просто його межа (замкнута полілінія): він включає його інтер'єр. Хоча межа багатокутника розділяє сферу на два з'єднані компоненти, існує багато способів позначити одну з них як внутрішню частину багатокутника, як, наприклад, за допомогою орієнтації на орієнтацію (наприклад, внутрішня частина лежить ліворуч, коли проходить кордон ) або за допомогою растрового зображення.
whuber

Відповіді:


12

Як і майже у всіх подібних питаннях, оптимальний підхід залежить від "випадків використання" та того, як представлені функції. Випадки використання, як правило, розрізняють (а) чи є багато або кілька об'єктів у кожному шарі та (b) чи допускає будь-який (або обидва) шари для попереднього обчислення деяких структур даних; тобто чи достатньо статичного та незмінного один чи обидва з них, щоб зробити інвестиції в попередні обчислення доцільними.

У цьому випадку це дає такі сценарії. Зазвичай бали динамічні: тобто вони не наводяться заздалегідь. (Якщо вони доступні заздалегідь, або в дуже великих групах, будуть доступні деякі оптимізації, засновані на їх сортування.) Нехай Q - кількість точок запиту, а P - кількість вершин багатокутника .

Векторні дані багатокутника

(1) Мало точок, кілька вершин багатокутника в тото . Використовуйте грубу силу, наприклад класичний алгоритм колючої лінії . Для будь-якого пристойного методу вартість становить O (P * Q), оскільки коштує O (1) час порівняння точки з краєм багатокутника, і всі подібні порівняння повинні бути виконані.

(2) Можливо, багато вершин багатокутника, але вони динамічні: кожного разу, коли в запиті використовується точка, всі полігони можуть змінитися. Знову використовуйте алгоритм грубої сили. Вартість все ще O (P * Q), яка буде великою, тому що P буде великою, але в цьому нічого не допоможе. Якщо зміни невеликі або контрольовані ( наприклад , багатокутники трохи змінюють форму або просто повільно рухаються навколо), можливо, ви зможете скористатися версією наступного рішення і знайти ефективний спосіб оновити структури даних під час зміни полігонів. Це, ймовірно, буде справою для оригінальних досліджень.

(3) Багато вершин вершин і статичних багатокутників (тобто шар багатокутника буде рідко змінюватися). Попередньо обчисліть структуру даних для підтримки пошуку (яка може базуватися на розгортанні рядків або алгоритмі квадратури ). Вартість попередніх обчислень для цих алгоритмів становить O (P * log (P)), але вартість запитів стає O (Q * log (P)), тому загальна вартість - O ((P + Q) * log ( П)).

Деякі вдосконалення доступні в особливих випадках , таких як

(a) Всі багатокутники опуклі ( попередня обробка полігонів може бути виконана швидше ),

(b) Усі інтер'єри полігонів роз'єднуються , і в цьому випадку ви можете вважати їх об'єднання як єдиний багатокутник (що дозволяє створювати прямо ефективні алгоритми, наприклад, засновані на тріангуляції, і

(c) Більшість багатокутників не дуже звивисті - тобто вони займають великі ділянки обмежувальних коробок - у цьому випадку ви можете зробити початковий тест лише на основі обмежувальних коробок, а потім уточнити це рішення. Це популярна оптимізація.

(г) Кількість балів велика. Сортування їх може покращити терміни. Наприклад, впроваджуючи алгоритм розгортки ліворуч на правий рядок з точкою в полігоні, ви б сортували точки за їх першою координатою, що дозволяє вам переміщати точки, одночасно переміщуючи їх по краях полігону. Мені невідомо, що така оптимізація була опублікована. Однак, опублікованим є виконання обмеженої тріангуляції об'єднання всіх точок і вершин багатокутника: після того, як триангуляція завершена, виявлення внутрішніх точок повинно бути швидким. Обчислювальна вартість буде масштабуватися як O (Q * log (Q) + (P + Q) * log (P + Q)).

Дані полігону растрових

Це неймовірно просто: розглядайте шар багатокутника як растровий бінарний індикатор (1 = всередині багатокутника, 0 = зовні). (Це може зажадати таблиці пошуку для конвертації растрових значень у внутрішні та зовнішні індикатори.) Кожен точковий зонд тепер потребує зусиль O (1) для індексації растрової комірки та зчитування її значення. Загальне зусилля - O (Q).

В загальному

Приємне гібридне рішенняу випадку багатьох статичних векторних багатокутників (векторний випадок 3 вище) спочатку є растерізація полігонів, можливо, навіть із грубою роздільною здатністю, на цей раз розрізняючи будь-які клітини, що перетинають будь-яку частину межі полігона (дайте їм значення 2, скажімо) . Використання растрового зонда (вартість: O (1)) зазвичай призводить до визначеної відповіді (точка, як відомо, всередині або зовні), але іноді призводить до невизначеної відповіді (точка падає в клітинку, через яку хоча б один край проходи), і в цьому випадку робиться більш дорогий векторний запит O (log (P)). Цей метод вимагає певних додаткових витрат на зберігання растру, але у багатьох випадках навіть невеликий растр (один МБ дозволить отримати растр 2000 на 2000 рік, який зберігає значення {0,1,2, null}) може надати величезні переваги в обчислювальний час . Асимптотично,


7

Якщо у вас обмежувальні полігони зберігалися у чомусь на зразок квадратичного дерева, ви можете використовувати це для швидкого визначення, які багатокутники потрібно перевірити. Як мінімум, ви можете просто побачити, чи знаходиться точка всередині кожного обмежувального поля багатокутника, а не робити повну точку в полігоні для кожного багатокутника. Особисто я створив веб-сервіс, який би кешував полігони в пам'яті і використовував щось на зразок набору JTS або NetTopology, щоб зробити запит перехрестя для мене.


1

У postgis ST_Intersects використовує індекси, щоб спочатку виявити, чи знаходиться точка всередині обмежувального поля полігону, а потім зробить повторну перевірку, щоб побачити, чи справді він знаходиться всередині полігону. Це швидко, часто дуже швидко.

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

/ Ніклас

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