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,