Algoritmo punto poligonale per più poligoni


11

Ho una mappa di Google con un mucchio di poligoni.

Ecco un problema a cui sono interessato: dato un punto lat, lng, qual è il modo migliore per determinare tutti i poligoni in cui si trova questo punto?

Il modo ovvio è eseguire un algoritmo "point in poligono" in modo iterativo per ciascun poligono, ma mi chiedevo se esistesse un algoritmo efficiente per rispondere a tali domande, specialmente se si hanno migliaia di poligoni.


Non so molto dell'API di Google Maps, ma il browser tende a non essere il posto migliore per fare query di grandi dimensioni come questa. PostGIS (gratuito), ArcServer o Oracle Spatial tendono a gestire meglio richieste come questa.
canisrufus,

Sono interessato all'algoritmo più di ogni altra cosa. A proposito, come faresti in PostGIS.
numan

L'URL seguente parla del punto in poligono .. (non l'ho mai usato) .. provalo .. potrebbe dare qualche idea. eriestuff.blogspot.com/2008/02/…

3
Ecco il mio commento obbligatorio che "punto-in-poligono" non ha senso per un punto su una sfera, dal momento che un poligono su una sfera divide semplicemente la sfera in due parti, ognuna delle quali ha il diritto di essere chiamata 'dentro'. Il polo nord o sud è "dentro" il poligono che definisce l'equatore? Ricorda, lat-long non è cartesiano ...
Spacedman

4
@Spaced Confondi "poligono" con "polilinea". Point-in-poligono ha perfettamente senso su una sfera. Un poligono non è solo il suo confine (una polilinea chiusa): include il suo interno. Sebbene un confine poligonale divide la sfera in due componenti collegati, ci sono molti modi per designarne uno come interno del poligono, ad esempio mediante una convenzione di orientamento (ad esempio, l'interno si trova a sinistra mentre si attraversa il confine ) o usando una rappresentazione raster.
whuber

Risposte:


12

Come con quasi tutte queste domande, l'approccio ottimale dipende dai "casi d'uso" e dal modo in cui le caratteristiche sono rappresentate. I casi d'uso si distinguono in genere per (a) se ci sono molti o pochi oggetti in ciascun livello e (b) se uno (o entrambi) livelli consentono di precomputare alcune strutture di dati; vale a dire se uno o entrambi sono sufficientemente statici e immutabili per rendere utile l'investimento in precomputazione.

Nel caso presente, ciò produce i seguenti scenari. Normalmente i punti sono dinamici: cioè non vengono assegnati in anticipo. (Se sono disponibili in anticipo o in gruppi molto grandi, saranno disponibili alcune ottimizzazioni basate sul loro ordinamento.) Sia Q il numero di punti di query e P il numero di vertici poligonali .

Dati poligonali vettoriali

(1) Pochi punti, pochi vertici poligonali in toto . Utilizzare una procedura a forza bruta, come il classico algoritmo di pugnalamento di linea . Per qualsiasi metodo decente, il costo è O (P * Q), perché costa O (1) tempo per confrontare un punto con un bordo poligonale e tutti questi confronti devono essere fatti.

(2) Forse molti vertici poligonali, ma sono dinamici: ogni volta che un punto viene utilizzato nella query, i poligoni potrebbero essere tutti cambiati. Usa di nuovo un algoritmo a forza bruta. Il costo è ancora O (P * Q), che sarà grande perché P sarà grande, ma non è di aiuto. Se le modifiche sono piccole o controllate ( ad esempio , i poligoni cambiano leggermente forma o semplicemente si muovono lentamente) potresti essere in grado di utilizzare una versione della soluzione successiva e trovare un modo efficiente per aggiornare le strutture dei dati man mano che i poligoni cambiano. Sarebbe probabilmente una questione di ricerca originale.

(3) Molti vertici poligonali e poligoni statici (ovvero, lo strato poligonale cambierà raramente). Calcola preventivamente una struttura di dati per supportare la ricerca (che potrebbe basarsi su uno sweep di linea o su un algoritmo quadtree ). Il costo della precomputazione per questi algoritmi è O (P * log (P)), ma il costo delle query diventa O (Q * log (P)), quindi il costo totale è O ((P + Q) * log ( P)).

Alcuni miglioramenti sono disponibili in casi speciali , come ad esempio

(a) Tutti i poligoni sono convessi (la preelaborazione dei poligoni può essere eseguita più rapidamente ),

(b) Tutti gli interni poligonali sono disgiunti , nel qual caso puoi pensare alla loro unione come a un singolo poligono (che consente algoritmi semplici ed efficienti, come quelli basati sulla triangolazione, e

(c) La maggior parte dei poligoni non sono molto tortuosi , cioè occupano grandi porzioni delle loro scatole di delimitazione, nel qual caso è possibile eseguire un test iniziale basato solo sulle scatole di delimitazione e quindi perfezionare quella soluzione. Questa è un'ottimizzazione popolare.

(d) Il numero di punti è elevato. Ordinarli potrebbe migliorare i tempi. Ad esempio, quando si implementa un algoritmo punto-in-poligono di sweep di linea da sinistra a destra, è necessario ordinare i punti sulla loro prima coordinata, consentendoti di scorrere sui punti contemporaneamente ai bordi del poligono. Non sono a conoscenza del fatto che tale ottimizzazione sia stata pubblicata. Uno che è stato pubblicato, tuttavia, è quello di eseguire una triangolazione vincolata dell'unione di tutti i punti e vertici poligonali: una volta completata la triangolazione, l'identificazione dei punti interni dovrebbe essere rapida. Il costo di calcolo verrà ridimensionato come O (Q * log (Q) + (P + Q) * log (P + Q)).

Dati poligonali raster

Questo è incredibilmente facile: visualizza il layer poligonale come un raster indicatore binario (1 = all'interno di un poligono, 0 = esterno). (Ciò potrebbe richiedere una tabella di ricerca per convertire i valori raster in indicatori interni / esterni.) Ogni sonda a punti ora richiede uno sforzo O (1) per indicizzare la cella raster e leggerne il valore. Lo sforzo totale è O (Q).

In generale

Una bella soluzione ibridanel caso di molti poligoni vettoriali statici (caso vettoriale 3 sopra) è inizialmente di rasterizzare i poligoni, forse anche con una risoluzione approssimativa, questa volta distinguendo tutte le celle che intersecano qualsiasi parte di un confine poligonale (diamo loro un valore di 2, diciamo) . L'uso di una sonda raster (costo: O (1)) di solito porta a una risposta definita (si sa che il punto si trova all'interno o all'esterno), ma a volte provoca una risposta indefinita (il punto cade in una cella attraverso la quale almeno un bordo passa), nel qual caso viene eseguita la query vettoriale O (log (P)) più costosa. Questo metodo comporta costi di archiviazione aggiuntivi per il raster, ma in molti casi anche un piccolo raster (un MB consentirà un raster 2000 per 2000 che memorizza i valori {0,1,2, null}) può conferire enormi vantaggi in termini di tempo di calcolo . asintoticamente,


7

Se avessi le scatole di delimitazione poligonali memorizzate in qualcosa come un albero quad, puoi usarlo per determinare rapidamente quali poligoni controllare. Come minimo potevi semplicemente vedere se il punto si trova all'interno di ogni riquadro di delimitazione poligonale anziché fare un punto intero in poligono per ciascun poligono. Personalmente avrei impostato un servizio web che memorizzasse nella cache i poligoni e usasse qualcosa come JTS o la suite NetTopology per fare la query di intersezione per me.


1

In postgis ST_Intersects utilizza gli indici per trovare innanzitutto se il punto si trova all'interno del riquadro di delimitazione del poligono e quindi ricontrolla per vedere se si trova davvero all'interno del poligono. È veloce, spesso molto veloce.

Se hai archiviato i tuoi dati in PostGIS, non dovresti avere dubbi sul fatto che il database sia il posto giusto per eseguire il calcolo. In altri casi dovrai inviare i tuoi poligoni a un programma intermedio o client. Ciò, di per sé richiederà molto più tempo rispetto ai calcoli e otterrà solo i poligoni pertinenti.

/ Nicklas

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.