Punto en algoritmo de polígono para múltiples polígonos

11

Tengo un mapa de Google con un montón de polígonos.

Aquí hay un problema que me interesa: dado un punto lat, lng, ¿cuál es la mejor manera de determinar todos los polígonos en los que se encuentra este punto?

La forma obvia es ejecutar un algoritmo de "punto en el polígono" de forma iterativa para cada polígono, pero me preguntaba si existe un algoritmo eficiente para responder a esas consultas, especialmente si tiene miles de polígonos.

numan
fuente
No sé mucho sobre la API de Google Maps, pero el navegador no suele ser el mejor lugar para realizar consultas grandes como esta. PostGIS (gratis), ArcServer u Oracle Spatial tienden a manejar mejor solicitudes como esta.
Canisrufus
Estoy interesado en el algoritmo más que cualquier otra cosa. Por cierto, ¿cómo harías esto en PostGIS?
numan 01 de
La siguiente url habla sobre el punto en el polígono ... (nunca he usado esto) ... pruébalo ... puede dar algo de ide. eriestuff.blogspot.com/2008/02/…
3
Aquí está mi comentario obligatorio de que "punto en el polígono" no tiene sentido para un punto en una esfera, ya que un polígono en una esfera simplemente divide la esfera en dos partes, cualquiera de las cuales tiene derecho a ser llamado 'dentro'. ¿El polo norte o sur está 'dentro' del polígono que define el ecuador? Recuerde, lat-long no es cartesiano ...
Spacedman
44
@Spaced Confunde "polígono" con "polilínea". El punto en el polígono tiene mucho sentido en una esfera. Un polígono es más que su límite (una polilínea cerrada): incluye su interior. Aunque un límite de polígono divide la esfera en dos componentes conectados, hay muchas formas de designar uno de ellos como el interior del polígono, por ejemplo, mediante una convención de orientación (por ejemplo, el interior se encuentra a la izquierda cuando uno atraviesa el límite ) o mediante el uso de una representación ráster.
whuber

Respuestas:

12

Como con casi todas estas preguntas, el enfoque óptimo depende de los "casos de uso" y de cómo se representan las características. Los casos de uso se distinguen típicamente por (a) si hay muchos o pocos objetos en cada capa y (b) si cualquiera de las capas (o ambas) permiten precalcular algunas estructuras de datos; es decir, si uno o ambos son suficientemente estáticos e inmutables para que la inversión en precomputación valga la pena.

En el presente caso, esto produce los siguientes escenarios. Normalmente los puntos son dinámicos: es decir, no se dan de antemano. (Si están disponibles por adelantado, o en grupos muy grandes, algunas optimizaciones basadas en su clasificación estarán disponibles). Deje que Q sea ​​el número de puntos de consulta y P el número de vértices de polígono .

Datos poligonales vectoriales

(1) Pocos puntos, pocos vértices poligonales en toto . Utilice un procedimiento de fuerza bruta, como el clásico algoritmo de apuñalamiento de línea . Para cualquier método decente, el costo es O (P * Q), porque le cuesta a O (1) tiempo comparar un punto con un borde de polígono y todas esas comparaciones deben hacerse.

(2) Posiblemente muchos vértices de polígonos, pero son dinámicos: cada vez que se usa un punto en la consulta, los polígonos podrían haber cambiado. Nuevamente use un algoritmo de fuerza bruta. El costo sigue siendo O (P * Q), que será grande porque P será grande, pero eso no ayuda. Si los cambios son pequeños o controlados ( por ejemplo , los polígonos cambian ligeramente de forma o simplemente se mueven lentamente), puede utilizar una versión de la próxima solución y encontrar una manera eficiente de actualizar las estructuras de datos a medida que cambian los polígonos. Eso probablemente sería un tema de investigación original.

(3) Muchos vértices de polígonos y polígonos estáticos (es decir, la capa de polígonos rara vez cambiará). Precalcule una estructura de datos para admitir la búsqueda (que podría basarse en un barrido de línea o un algoritmo quadtree ). El costo de la precomputación para estos algoritmos es O (P * log (P)), pero el costo de las consultas se convierte en O (Q * log (P)), por lo que el costo total es O ((P + Q) * log ( PAG)).

Algunas mejoras están disponibles en casos especiales , como

(a) Todos los polígonos son convexos (el preprocesamiento de los polígonos se puede hacer más rápidamente ),

(b) Todos los interiores de polígonos son disjuntos , en cuyo caso puede pensar que su unión es un polígono único (que permite algoritmos directos eficientes, como los basados ​​en triangulación, y

(c) La mayoría de los polígonos no son muy tortuosos , es decir, ocupan grandes porciones de sus cuadros delimitadores, en cuyo caso puede hacer una prueba inicial basada solo en los cuadros delimitadores y luego refinar esa solución. Esta es una optimización popular.

(d) El número de puntos es grande. Ordenarlos podría mejorar el tiempo. Por ejemplo, al implementar un algoritmo de barrido de línea de izquierda a derecha de punto en polígono, debe ordenar los puntos en su primera coordenada, lo que le permite barrer sobre los puntos al mismo tiempo que barre sobre los bordes del polígono. No estoy al tanto de que tal optimización haya sido publicada. Sin embargo, uno que se ha publicado es realizar una triangulación restringida de la unión de todos los puntos y vértices poligonales: una vez que se completa esa triangulación, la identificación de los puntos interiores debe ser rápida. El costo computacional se escalará como O (Q * log (Q) + (P + Q) * log (P + Q)).

Datos de polígono ráster

Esto es increíblemente fácil: vea la capa de polígono como un ráster indicador binario (1 = dentro de un polígono, 0 = afuera). (Esto podría requerir una tabla de búsqueda para convertir los valores ráster en indicadores internos / externos). Cada sonda puntual ahora requiere un esfuerzo O (1) para indexar la celda ráster y leer su valor. El esfuerzo total es O (Q).

En general

Una buena solución híbridaen el caso de muchos polígonos de vectores estáticos (el caso del vector 3 anterior) es inicialmente rasterizar los polígonos, quizás incluso con una resolución aproximada, esta vez distinguiendo las celdas que intersecan cualquier parte de un límite de polígono (dándoles un valor de 2, por ejemplo) . El uso de una sonda ráster (costo: O (1)) generalmente da como resultado una respuesta definitiva (se sabe que el punto está dentro o fuera), pero ocasionalmente da como resultado una respuesta indefinida (el punto cae en una celda a través de la cual al menos un borde pasa), en cuyo caso se realiza la consulta vectorial O (log (P)) más costosa. Este método incurre en un costo de almacenamiento adicional para el ráster, pero en muchos casos incluso un ráster pequeño (un MB permitirá un ráster 2000 por 2000 que almacena {0,1,2, nulo} valores) puede conferir enormes ventajas en el tiempo computacional . Asintóticamente

whuber
fuente
7

Si tuviera los cuadros delimitadores de polígonos almacenados en algo así como un árbol cuádruple, entonces podría usarlos para determinar rápidamente qué polígonos verificar. Como mínimo, podría ver si el punto está dentro de cada cuadro delimitador del polígono en lugar de hacer un punto completo en el polígono para cada polígono. Personalmente, configuraría un servicio web que almacenaría en caché los polígonos en la memoria y usaría algo como JTS o NetTopology para hacer la consulta de intersección por mí.

Peter Smith
fuente
1

En postgis, ST_Intersects usa índices para encontrar primero si el punto está dentro del cuadro delimitador del polígono y luego realiza una nueva verificación para ver si realmente está dentro del polígono. Eso es rápido, a menudo muy rápido.

Si ha almacenado sus datos en PostGIS, no debe haber ninguna duda de que la base de datos es el lugar correcto para hacer el cálculo. En otros casos, deberá enviar sus polígonos a algún programa intermedio o de cliente. Eso, en sí mismo, tomará mucho más tiempo que hacer los cálculos y solo obtendrá los polígonos relevantes.

/ Nicklas

Nicklas Avén
fuente