Qual é a maneira mais eficiente de encontrar a espessura mínima da parede (valor e localização) de uma área complexa e não convexa de polígonos, incluindo orifícios? Veja o exemplo de um polígono em azul, com a espessura mínima da parede em vermelho, embora neste caso a localização seja ambígua, se as duas linhas adjacentes forem paralelas.
Até agora, tentamos:
- Subdividir linhas de polígono e encontrar linhas de ponto de ponto mínimo dentro do polígono (força bruta, não eficiente para polígonos complexos com> 10.000 pontos)
- Triangulação de Delaunay e localização de arestas mínimas dentro do polígono. Não é preciso o suficiente, apenas possível se combinado com a subdivisão das linhas poligonais primeiro. Aqui está um exemplo (Nr 3), em que a triangulação de Delaunay não encontraria bordas simples em vermelho, mas perderia a espessura mínima da parede na caixa verde:
- Aumento iterativo do buffer de erosão para encontrar a inserção mínima, onde o polígono da erosão se divide em várias partes = metade da espessura mínima da parede. O problema é encontrar a localização da espessura mínima da parede com essa abordagem posteriormente. Além disso, a erosão nem sempre quebra em várias partes e perde "becos sem saída". Aqui está um exemplo (Nr 2) que corroer para uma linha e fornecer a espessura mínima incorreta da parede:
- Localizando primeiro o eixo medial, procure o círculo mínimo no eixo medial que está cobrindo, mas não sobrepondo, a área do polígono. Edit: problemáticos são os muitos "candidatos errados" no eixo medial: por exemplo. (Nr 1) o círculo A estaria errado, o círculo B indicaria a espessura mínima correta da parede:
Respostas:
Um dos métodos mais eficientes para encontrar a espessura mínima da parede (valor e localização) de uma área complexa de polígonos não convexos, incluindo orifícios, poderia ser usando uma camada regularmente espaçada (ou aleatória) de pontos para determinar o primeiro segmento mais próximo com contexto para cada ponto e, a seguir, o ponto de interseção entre o segmento incremental e o polígono do lado oposto; baseado em diretores cossenos.
Distâncias incrementais podem ser usadas até o primeiro segmento atingir e cruzar algum polígono lateral (a espessura mínima da parede).
Para experimentar minha abordagem, clonei seu polígono com furos e criei uma camada de pontos aleatórios dentro do polígono com 100 pontos; como pode ser observado na seguinte imagem:
O código usado do PyQGIS é o seguinte:
e produz uma camada de memória de distâncias incrementais (apenas para fins de visualização) e imprime uma espessura mínima da parede no formato WKT.
Depois de executar o código no Python Console do QGIS, obtive resultado da seguinte imagem:
Pode-se observar que apenas uma distância incremental alcançou o lado oposto primeiro na área esperada.
O formato WKT impresso (para espessura mínima da parede) é usado com o plug-in QuickWKT do QGIS para visualizar esse segmento na seguinte imagem:
A leve inclinação foi produzida porque "o segmento mais próximo ao contexto" foi associado a um vértice; polígono lateral. No entanto, isso pode ser evitado com uma exceção de código ou mais pontos.
fonte
Mais duas idéias para jogar no pote:
Rasterize seu polígono e use uma transformação de distância (retorna a imagem da distância mais curta de cada pixel diferente de zero para um pixel zero). Esqueletize sua imagem rasterizada e, em seguida, calcule os valores da imagem transformada à distância ao longo do esqueleto. Nesse conjunto, você terá alguns mínimos que devem corresponder à sua largura mais estreita. Esse conjunto pode ser usado como pontos de pesquisa inicial para implementar sua abordagem de força bruta. Devo observar que o esqueleto dividirá os cantos dos objetos e, nesses locais, a transformação de distância se aproximará de zero (à medida que você se aproxima do limite do objeto). Isso pode ser problemático, mas representa um problema com o seu problema - por que ' t a menor largura está em um canto (e é essencialmente zero)? Você pode solucionar esse problema definindo um limite na menor distância ao redor do perímetro entre os dois pontos (se eles estiverem no mesmo objeto). Você pode usar uma transformação de distância geodésica no conjunto de pixels de perímetro para encontrar rapidamente esse valor.
Esse método exige que você tome uma decisão sobre a resolução do polígono rasterizado, o que introduz alguma dependência de escala. E se você escolher uma resolução muito alta, a transformação da distância poderá consumir tempo. Mas geralmente são bem rápidos. Esse método pode não fornecer a precisão desejada, mas pelo menos pode fornecer um conjunto muito menor de locais que precisam ser verificados.
Seu método de força bruta não é um mau lugar para começar. Eu tive um problema semelhante em que tive que encontrar todas as interseções de uma linha (longa) consigo mesma e consegui acelerar bastante o tempo de pesquisa usando um algoritmo de pesquisa em árvore kd (usei o rangeearch no Matlab na época) para encontrar pontos dentro de um bairro primeiro. Dessa forma, você está forçando brutalmente um pequeno subconjunto do número total de pontos.
fonte
A abordagem do eixo medial está correta, você só precisa de um critério para ignorar os círculos defeituosos: Cada círculo no eixo medial toca a superfície em dois (ou mais) pontos. Imagine vetores do centro do círculo até esses pontos na superfície e observe que o ângulo entre é 180 ° para o círculo bom B e apenas 90 ° para o círculo ruim A.
fonte
Um algoritmo de desenho de polígono genérico funciona classificando os segmentos de linha de cima para baixo e trabalhando neles para desenhar linhas ortogonais de pixels. Como essa maneira de quebrar polígonos (sem curvaturas) é muito rápida, pode ser usada como base. Em vez de ir de cima para baixo, você pode ir 0, 30, 60 e 90 graus e encontrar sua seção ortogonal mais curta (= espessura mínima da parede!), Você só precisa calcular isso uma vez por ponto e não para qualquer tipo de 'resolução de pixel'.
Consulte algoritmo de preenchimento de gráficos de linha de computador com polígonos de preenchimento
fonte