Identificando polígonos "longos e estreitos" no PostGIS

10

Eu tenho um conjunto de polígonos representando grandes áreas, digamos bairros da cidade. Quero identificar as grandes áreas sobrepostas entre elas.

Mas há um problema: às vezes esses polígonos se sobrepõem ao longo de seus perímetros (porque foram desenhados com pouca precisão). Isso irá gerar sobreposições longas e estreitas com as quais não me importo.

Outras vezes, porém, haverá grandes sobreposições de polígonos robustos, o que significa grandes áreas em que o polígono de um bairro se sobrepõe a outro. Eu quero selecionar apenas estes.

Veja a figura abaixo apenas das sobreposições. Imagine que eu queria selecionar apenas o polígono azul no canto inferior esquerdo.

sobreposição

Eu podia olhar para as áreas, mas às vezes as estreitas são tão longas que acabam tendo áreas tão grandes quanto o polígono azul. Eu tentei fazer uma proporção de área / perímetro, mas isso também produziu resultados mistos.

Eu até tentei usar ST_MinimumClearance, mas às vezes as grandes áreas terão uma parte estreita anexada a ela, ou dois vértices muito próximos.

Alguma idéia de outras abordagens?


No final, o que funcionou melhor para mim foi usar um buffer negativo, conforme sugerido por @Cyril e @FGreg abaixo.

Eu usei algo como:

ST_Area(ST_Buffer(geom, -10)) as neg_buffer_area

No meu caso, as unidades eram metros, portanto 10 m de buffer negativo.

Para polígonos estreitos, essa área retornou zero (também, a geometria estaria vazia). Então usei essa coluna para filtrar os polígonos estreitos.

bplmp
fonte
4
Certamente a relação área / perímetro poderia ser usada para isso.
Vince
É difícil dizer onde estão os polígonos distintos da imagem, mas fazer algo assim gis.stackexchange.com/a/265233/64838 pode funcionar? Calcule a caixa delimitadora girada mínima e descarte as de largura ou altura pequenas.
FGreg 20/03/19
Você também pode tentar usar um buffer negativo, conforme descrito aqui: Como identificar polígonos realmente finos no meu arquivo de formas?
FGreg 20/03/19

Respostas:

5

Eu tentaria criar um buffer negativo, se ele come polígonos finos, então é bom, se não comer o polígono, então é meu ... :-)

execute este script, tendo previamente definido 2/3 da largura dos polígonos lineares ...

create table name_table as
SELECT ST_Buffer(
(ST_Dump(
(ST_Union(
ST_Buffer(
(geom),-0.0001))))).geom,
0.0001)) as geom from source_table

OS: -) ...

Cyril Mikhalchenko
fonte
no final, sua sugestão é a que funcionou melhor para mim. Acabei usando algo como ST_Area(ST_Buffer(geom, -10))-10 sendo -10 metros no meu caso. Se alguma coisa retornasse 0 dessa expressão, eu poderia filtrá-la.
bplmp
9

Em vez de área / perímetro, é melhor usar a área dividida pelo quadrado do perímetro (ou seu inverso).

Isso também é chamado de "índice de forma". O quadrado do perímetro dividido pela área tem um valor mínimo de 4 * Pi () (no caso de um disco, que é a geometria 2D mais compacta), para que possa ser normalizado por 4 * Pi () para facilitar interpretação (valores normalizados próximos a 1 significam que você tem objetos muito compactos e quadrados têm valores de aproximadamente 1,27).

EDIT: Um limite na área seria útil para remover os artefatos muito pequenos, que poderiam ser compactos. Em seguida, o índice de forma mostraria melhor contraste. EDIT: além desta resposta, o uso do ST_Snap pode ajudá-lo a resolver o problema antes que ele ocorra.

radouxju
fonte
Obrigado! Mas não tenho certeza de como o ST_Snap poderia ajudar nesse caso ... Se eu entendi direito, você está sugerindo algo como (o.overlap_perimeter^2 / o.overlap_area) / (4 * Pi()) as overlap_ratio? Isso está tendo resultados piores para mim do que apenas área / perímetro.
bplmp
Agora, usando de o.overlap_perimeter / (4 * sqrt(o.overlap_area)) as overlap_ratioacordo com este artigo, mas resultados ainda piores (embora seja difícil quantificar o que quero dizer com pior) é: prs-ann-photogramm-remote-sens-spatial-inf-sci.net/I-7/135/… , página 183.
bplmp 20/03/19
2
Obrigado por isso, eu nunca tinha ouvido falar do "índice de forma". Eu sempre pensei que usar um retângulo delimitador mínimo era a melhor maneira de responder a esse tipo de pergunta. Eu achei isso, repository.asu.edu/attachments/111230/content/… , o que é interessante.
John Powell
@JohnPowell artigo interessante, obrigado. Vejo que o que eu sei como índice de forma é chamado índice de circularidade no artigo. Meu problema com retângulos de limite mínimo é que ele não funciona com objetos muito côncavos (por exemplo, em forma de U)
radouxju
@bplmp ST_Snap ajudaria você a remover os vértices dos polígonos "quase" adjacentes, para que eles não se sobreponham mais. Não há escala nas figuras, mas seu artefato se parece com linhas, então acho que você pode usar um valor de tolerância que seja suficiente para evitar artefatos, mas não afeta os polígonos grandes.
Radouxju 21/03/19
5

Uma opção seria usar a proporção da área do polígono para a linha mais longa que pode ser desenhada usando suas extremidades. Identificando polígonos estreitos e longos.

select * from polygons where ST_Length(ST_LongestLine(geom, geom)) < ST_Area(geom) * 4

Isso funciona muito bem para polígonos de fita. Você pode ajustar a proporção (com a qual você multiplica a área) para atender às suas necessidades e projeção.

HeikkiVesanto
fonte
1

Parece que isso pode corresponder ao seu caso de uso: Eliminar polígonos selecionados

Combina polígonos selecionados da camada de entrada com certos polígonos adjacentes, apagando seus limites comuns. O polígono adjacente pode ser aquele com a área maior ou menor ou aquele que compartilha o maior limite comum com o polígono a ser eliminado.

Eliminate é normalmente usado para se livrar dos polígonos da tira, ou seja, polígonos minúsculos resultantes de processos de interseção de polígonos em que os limites das entradas são semelhantes, mas não idênticos.

Parece que você deseja experimentar a opção "Maior limite comum".

FGreg
fonte
Percebo agora que você estava pedindo soluções postgis, não soluções qgis. Peço desculpas, não acho que o postgis tenha uma função equivalente, mas deixarei isso para a posteridade.
FGreg 20/03/19
0

Isso me parece um caso de uso perfeito para a extensão de topologia PostGIS . O parâmetro de tolerância da topologia determinará até que ponto você permite que os vértices se ajustem a outros polígonos existentes, para lidar com a baixa precisão dos dados de origem e limpá-los.

Em suma, a estratégia é:

1. Habilite a extensão de topologia

CREATE EXTENSION postgis_topology;

2. Crie uma nova topologia vazia

SELECT topology.CreateTopology('neighborhoods_topo', 4326, 1e-7);

O terceiro parâmetro é a tolerância, nas unidades do SRC; escolha sabiamente. Idealmente, você deseja um CRS em que a unidade é metros. Se a unidade CRS não tiver medidores, como no WGS 84 aka 4326, use ST_Transformpara reprojetar seus polígonos.

3. Adicione uma coluna TopoGeometry à tabela de polígonos

SELECT topology.AddTopoGeometryColumn('neighborhoods_topo', 'public', 'neighborhoods', 'topogeom', 'POLYGON');

Isso retorna um novo layer_id. Salve, será necessário mais tarde. Será uma camada 1se você começar do zero e incrementado a cada nova chamada.

4. Adicione todos os polígonos à topologia

UPDATE public.neighborhoods
SET topogeom = topology.toTopoGeom(geom, 'neighborhoods_topo', 1, 1e-7);

Isso pode levar várias horas para um grande conjunto de dados, seja paciente. 1é o layer_id retornado anteriormente.

5. Encontre rostos aparecendo em vários bairros

Encontre todas as faces da topologia presentes em 2 ou mais topogeometrias. Vou deixar a consulta como um exercício. O mais fácil é provavelmente com a GetTopoGeomElementsfunção, em seguida, agrupe por ID do rosto e observe os com uma contagem de 2 ou mais. Como alternativa, você pode criar uma nova tabela com a geometria limpa da coluna topogeom, apenas convertê-la na geometria padrão topogeom::geometrye repetir o que você já tem agora, mas agora com um conjunto de dados limpo sem a sobreposição da tira.

François
fonte