Ponto no algoritmo de polígono para vários polígonos

11

Eu tenho um mapa do Google com vários polígonos.

Aqui está um problema no qual estou interessado: Dado um ponto de lat, lng, qual é a melhor maneira de determinar todos os polígonos em que esse ponto se encontra?

A maneira óbvia é executar um algoritmo de "ponto no polígono" iterativamente para cada polígono, mas eu queria saber se existe um algoritmo eficiente para responder a essas consultas, especialmente se você tiver milhares de polígonos.

numan
fonte
Eu não sei muito sobre a API do Google Maps, mas o navegador tende a não ser o melhor lugar para fazer consultas grandes como essa. PostGIS (gratuito), ArcServer ou Oracle Spatial tendem a lidar melhor com solicitações como essa.
Canisrufus 01/11
Estou interessado em algoritmo mais do que qualquer outra coisa. BTW, como você faria isso no PostGIS.
Numan,
O seguinte URL fala sobre o ponto no polígono .. (eu nunca usei isso) .. tente ... pode dar algum ide. eriestuff.blogspot.com/2008/02/...
3
Aqui está meu comentário obrigatório de que "ponto no polígono" não faz sentido para um ponto em uma esfera, pois um polígono em uma esfera apenas divide a esfera em duas partes, sendo que uma delas tem o direito de ser chamada de "interior". O pólo norte ou sul está 'dentro' do polígono que define o equador? Lembre-se, lat-long não é cartesiano ...
Spacedman
4
@ Spaced Você confunde "polígono" com "polilinha". O ponto no polígono faz todo o sentido em uma esfera. Um polígono é mais do que apenas seu limite (uma polilinha fechada): inclui seu interior. Embora um limite de polígono divida a esfera em dois componentes conectados, há muitas maneiras de designar um deles como o interior do polígono, como por meio de uma convenção de orientação (por exemplo, o interior fica à esquerda quando se atravessa o limite ) ou usando uma representação raster.
whuber

Respostas:

12

Como em quase todas essas perguntas, a abordagem ideal depende dos "casos de uso" e de como os recursos são representados. Os casos de uso são tipicamente distinguidos por (a) se há muitos ou poucos objetos em cada camada e (b) se (ou ambas) as camadas permitem pré-computar algumas estruturas de dados; isto é, se um ou ambos são suficientemente estáticos e imutáveis ​​para fazer valer o investimento em pré-computação.

No presente caso, isso produz os seguintes cenários. Normalmente, os pontos são dinâmicos: ou seja, não são dados de antemão. (Se eles estiverem disponíveis antecipadamente ou em grupos muito grandes, algumas otimizações baseadas na classificação deles estarão disponíveis.) Seja Q o número de pontos de consulta e P o número de vértices de polígonos .

Dados de polígono de vetor

(1) Poucos pontos, poucos vértices poligonais no total . Use um procedimento de força bruta, como o algoritmo clássico de facada na linha . Para qualquer método decente, o custo é O (P * Q), porque custa O (1) tempo para comparar um ponto com uma aresta de polígono e todas essas comparações precisam ser feitas.

(2) Possivelmente muitos vértices de polígonos, mas são dinâmicos: sempre que um ponto é usado na consulta, todos os polígonos podem ter sido alterados. Novamente, use um algoritmo de força bruta. O custo ainda é O (P * Q), que será grande porque P será grande, mas não há como evitar isso. Se as alterações forem pequenas ou controladas ( por exemplo , os polígonos estão mudando ligeiramente de forma ou simplesmente se movendo lentamente), você poderá usar uma versão da próxima solução e encontrar uma maneira eficiente de atualizar as estruturas de dados à medida que os polígonos mudam. Provavelmente isso seria motivo de pesquisa original.

(3) Muitos vértices poligonais e polígonos estáticos (ou seja, a camada poligonal raramente muda). Pré-calcule uma estrutura de dados para dar suporte à pesquisa (que pode ser baseada em uma varredura de linha ou em um algoritmo quadtree ). O custo da pré-computação para esses algoritmos é O (P * log (P)), mas o custo das consultas se torna O (Q * log (P)), portanto, o custo total é O ((P + Q) * log ( P)).

Algumas melhorias estão disponíveis em casos especiais , como

(a) Todos os polígonos são convexos (o pré-processamento dos polígonos pode ser feito mais rapidamente ),

(b) Todos os interiores dos polígonos são disjuntos ; nesse caso, você pode pensar na união deles como um único polígono (o que permite algoritmos eficientes e diretos, como os baseados na triangulação, e

(c) A maioria dos polígonos não é muito tortuosa - ou seja, eles ocupam grandes partes de suas caixas delimitadoras - nesse caso, você pode fazer um teste inicial baseado apenas nas caixas delimitadoras e refinar a solução. Esta é uma otimização popular.

(d) O número de pontos é grande. Classificá-los pode melhorar o tempo. Por exemplo, ao implementar um algoritmo de varredura de linha da esquerda para a direita, classifique os pontos na primeira coordenada, permitindo varrer os pontos ao mesmo tempo em que varre as bordas dos polígonos. Não sei que essa otimização foi publicada. Um que foi publicado, no entanto, é realizar uma triangulação restrita da união de todos os pontos e vértices poligonais: uma vez concluída a triangulação, a identificação dos pontos internos deve ser rápida. O custo computacional será escalado como O (Q * log (Q) + (P + Q) * log (P + Q)).

Dados de varredura de polígono

Isso é incrivelmente fácil: visualize a camada de polígono como uma varredura de indicador binário (1 = dentro de um polígono, 0 = fora). (Isso pode exigir uma tabela de pesquisa para converter valores de varredura em indicadores internos / externos.) Cada sonda de ponto agora requer esforço O (1) para indexar a célula de varredura e ler seu valor. O esforço total é O (Q).

Em geral

Uma boa solução híbridano caso de muitos polígonos de vetor estático (caso de vetor 3 acima), é inicialmente rasterizar os polígonos, talvez mesmo com uma resolução grosseira, desta vez distinguindo todas as células que cruzam qualquer parte de um limite de polígono (dê um valor de 2, digamos) . O uso de uma sonda raster (custo: O (1)) normalmente resulta em uma resposta definida (o ponto é conhecido por estar dentro ou fora), mas ocasionalmente resulta em uma resposta indefinida (o ponto cai em uma célula através da qual pelo menos uma extremidade) passa), nesse caso a consulta mais cara do vetor O (log (P)) é feita. Esse método incorre em algum custo extra de armazenamento para a varredura, mas em muitos casos, mesmo uma pequena varredura (um MB permitirá uma varredura de 2000 por 2000 que armazena valores {0,1,2, null}) pode conferir enormes vantagens no tempo computacional . Assintoticamente,

whuber
fonte
7

Se você tiver as caixas delimitadoras de polígonos armazenadas em algo como uma árvore quádrupla, poderá usá-las para determinar rapidamente quais polígonos verificar. No mínimo, você pode ver se o ponto está dentro de cada caixa delimitadora de polígonos, em vez de fazer um ponto completo no polígono para cada polígono. Pessoalmente, eu configuraria um serviço da Web que armazenaria em cache os polígonos na memória e usaria algo como o JTS ou o NetTopology para fazer a consulta de interseção por mim.

Peter Smith
fonte
1

No postgis, o ST_Intersects usa índices para descobrir primeiro se o ponto está dentro da caixa delimitadora do polígono e, em seguida, verifica novamente se realmente está dentro do polígono. Isso é rápido, geralmente muito rápido.

Se você armazenou seus dados no PostGIS, não há dúvida de que o banco de dados é o lugar certo para fazer o cálculo. Em outros casos, você precisará enviar seus polígonos para algum programa do meio ou do cliente. Isso, por si só, levará muito mais tempo do que os cálculos e apenas obterá os polígonos relevantes.

/ Nicklas

Nicklas Avén
fonte