Criar mosaico como o diagrama de Voronoi a partir de polígonos disjuntos

12

A ilustração abaixo mostra o problema :

insira a descrição da imagem aqui

como em (a) , tenho um conjunto de polígonos disjuntos, como geometrias no PostGIS. Preciso de algo como (b) , o "mosaico" desse conjunto de polígonos, construindo-o por um critério de "região de influência" ... É como uma construção de Voronoi (ilustrada por (c) ): de fato, se os polígonos fossem pontos, as regiões de influência são Voronoi.

Resumindo: Eu preciso de um algoritmo SQL (ou algum específico do PostGIS) que gere o "mosaico" de um conjunto de polígonos disjuntos. (talvez um loop de pequenas operações ST_Buffer e ST_Difference)

PS: Eu preciso, como o de Voronoi, que a delimitação do espaço (uma moldura quadrada em (b) ) seja ignorada.


Esse problema é semelhante ao outro sobre linhas .

EDIT (após o comentário @FelixIP)

Prefiro permanecer no universo vetorial , sem perder a precisão (por exemplo, usando ST_DelaunayTriangles e adicionando e subtraindo interiores pelos polígonos originais, adaptando uma solução de gráfico duplo ) ... Alguns pacotes simples e automáticos como pprepair (assistido como ferramentas topológicas do QGIS não são automáticos). Mas o raster talvez seja mais simples e consome menos CPU.

Esta ilustração do "processo GRID" também é válida como solução, assumindo que pode permitir a mesma precisão e "região de influência euclidiana em crescimento".

insira a descrição da imagem aqui

No ARCGIS existe uma ferramenta de análise espacial conhecida como Alocação Euclidiana , portanto, talvez haja uma solução semelhante ao PostGIS , começando com o conjunto de polígonos (classificando, rasterizando e recuperando os polígonos).

Peter Krauss
fonte
Obrigado @Nir, desculpe a confusão com pontos, não estou usando pontos, apenas polígonos como itens (a) e (b) da ilustração ... Você tem um link da sua pista sobre a solução?
Peter Krauss
Em arcgis há uma solução raster chamada alocação eucledean ou proximidade
FelixIP
Graças @FelixIP, eu editado para "bem vir soluções raster" ;-)
Peter Krauss
Se você apagar seus polígonos da extensão.aspolygon, ficará com o polígono. Esqueleto dele gis.stackexchange.com/questions/177/… é o que você precisa, eu acho. A implementação é uma coisa
demais
1
@Cyril, posso revisar seus scripts ... Na próxima semana. A publicação de algo que pareça uma solução com as funções modernas do PostGIS será um bom primeiro passo.
Peter Krauss

Respostas:

1

Então, eu prepararei um bolo para você - bandeja de frutas, usando as ferramentas PostGis, conforme solicitado, se eu entendi corretamente a pergunta e, como mencionei, a responsabilidade pela operação do forno PostGIS é assumida por sua equipe criativa.

Pedirei para não ser ofendido por ninguém no meu estilo de humor e entendê-lo como um jogo!

O arquivo original é uma fatia de frutas e formas simples (doravante denominadas frutas), veja a Figura 1 abaixo.

insira a descrição da imagem aqui

Aqui está minha receita e serei ajudado por queridos programadores, sobre os quais você aprenderá mais tarde. Vamos começar e, para isso, criaremos uma massa na qual nossos frutos serão depositados, para a qual executamos o script:

create table poly_extent as SELECT ST_SetSRID(ST_Buffer(ST_Envelope(ST_Extent(geom)),0.05),4326) as geom FROM poly;

Veja o resultado na Figura 2 abaixo

insira a descrição da imagem aqui

Agora, se houver poucas frutas, como na minha foto, crie a borda do buffer externo na fruta, ou se houver muitas frutas, crie a borda do buffer negativo, para a qual o script é executado:

create table poly_buff_dump as SELECT ((ST_Dump(ST_Boundary(ST_Union(ST_Buffer((geom),0.01, 'join=mitre mitre_limit=5.0'))))).geom) geom FROM poly;

E corte as linhas de buffer em torno de cada fruta

UPDATE poly_buff_dump SET geom=ST_RemovePoint(geom, ST_NPoints(geom)-1) WHERE ST_IsClosed(geom)=true; Veja o resultado na Figura 3 abaixo

insira a descrição da imagem aqui

(Na verdade, pensei que, como resultado, obteria linhas quebradas (como em um círculo), mas se os números forem difíceis, às vezes são obtidas quebras, incorretas, por exemplo, um lado do retângulo caiu etc. )

Então você precisa dividir as linhas obtidas de maneira conveniente para você em segmentos iguais e extrair pontos delas

create table poly_buff_dump_pt as SELECT (ST_DumpPoints((geom))).geom geom FROM poly_buff_segm;

Resultado, veja a Figura 4 abaixo

insira a descrição da imagem aqui

Agora execute a ferramenta Voronoi, neste local usei a ferramenta sugerida pelo link MickyT: /gis//a/172246/120129 , como resultado, você criará tabelas com o nome “voronoi ”Pelo fato de que“ meu primeiro assistente ”é separado do chef, graças ao chef! :-).

A segunda maneira nesta etapa é executar a função ST_VoronoiPolygons.

Resultado, veja a Figura 5 abaixo

insira a descrição da imagem aqui

Agora, corte as partes extras executando o script:

create table poly_voronoi_cut as SELECT ST_Intersection(a.geom, b.geom) geom FROM voronoi a INNER JOIN poly_extent b ON ST_Intersects(a.geom, b.geom); Resultado, veja a Figura 6 abaixo.

insira a descrição da imagem aqui

Agora execute o script para alinhar o tipo de dados geográficos em LineString:

create table poly_voronoi_dump as SELECT (ST_Dump(geom)).geom as geom FROM poly_voronoi_cut; E agora vou pedir ao "meu segundo companheiro" para assumir meus deveres e misturar bem o bolo (Jeff - /gis//a/785/120129 ), nivelando-o em uma única camada e por isso , obrigado por isso!

CREATE TABLE poly_overlay_cut AS SELECT geom FROM ST_Dump(( SELECT ST_Polygonize(geom) AS geom FROM ( SELECT ST_Union(geom) AS geom FROM ( SELECT ST_ExteriorRing(geom) AS geom FROM poly_voronoi_dump) AS lines ) AS noded_lines ) ); Agora é hora de eu começar a trabalhar, para a qual eu executo o script:

create table poly_voronoi_union as SELECT b.id, (ST_ConvexHull(ST_Union(a.geom, b.geom))) geom FROM poly_overlay_cut a INNER JOIN poly_buff_dump b ON ST_Intersects(a.geom, b.geom) GROUP BY b.id, a.geom, b.geom; e outro script:

create table poly_voronoi_union_area as SELECT ST_Union(ST_ConvexHull(ST_BuildArea(geom))) as geom FROM poly_voronoi_union GROUP BY id; veja a figura 7 abaixo

insira a descrição da imagem aqui

Como você pode ver na figura, nossos cortes têm pequenas camadas, que podem ser removidas, como opção usando ST_SnapToGrid (ou de outra maneira):

E, finalmente, cortaremos nossa fruta assada da torta, até me cansei de pé junto ao forno :-)

create table polygon_voronoi_result as SELECT (ST_Dump(ST_Difference(a.geom, b.geom))).geom as geom FROM poly_voronoi_union_area_snap as a JOIN poly b ON ST_Intersects(a.geom, b.geom); Resultado veja figura 8 insira a descrição da imagem aqui

Tudo a partir deste dia, agora todos aprenderão a assar tortas deliciosas - prato de frutas. Sirva-se de Tudo e escolha as peças que você gosta, o suficiente para todos.

(É uma pena que eu realmente não possa alimentar todas as pessoas, não com bolos eletrônicos, mas com bolos de verdade, talvez a fome acabe na Terra ...)

Edit: A cereja na torta pode ficar assim :-):

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM poly),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT ST_Intersection(a.geom, b.geom) geom FROM tblb a JOIN poly_extent b ON ST_Intersects(a.geom,b.geom)),
tbld AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM poly GROUP BY id, geom)
SELECT id, ST_Union(a.geom) as geom FROM tblc a JOIN tbld b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

ou

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM polygons),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM polygons GROUP BY id, geom)
SELECT id, ST_Union(a.geom) geom FROM tblb a JOIN tblc b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

Com você foi bom e justo Mr.Baker, obrigado a todos e boa sorte,: -) ...

Soluções originais.

Este script é chamado: ST_VoronoiDiagramsFromPolygons.

Cyril M
fonte
1
Olá, boas ilustrações e parece ser um bom resultado (!). Sugestão para uma breve discussão, consulte a solução @geogeek, as etapas no QGis parecem as principais etapas do PostGIS aqui ... Por que precisamos ST_Buffere ST_ConvexHull? Existe um algoritmo alternativo?
22419 Peter Krauss
1) Veja, ST_Buffer e nos polígonos são criados para reduzir as linhas de separação entre as figuras originais durante a aplicação da função Voronoi. Portanto, quanto maior o tamanho do buffer que você pode especificar, mais suavemente as linhas de separação serão construídas. uma função Voronoi ... 2) ST_ConvexHull da multidão de figuras em cada polígono, o polígono de que precisamos ... 3) Hoje, esta é minha visão de resolver sua pergunta, não sei o que acontecerá com todos nós. e nossas decisões no futuro ...
Cyril M
Outro valor importante das linhas de tampão é que eles vão ajudar a seleccionar nos fragmentos a partir do resultado da função de Voronoi para criar polígonos combinados para cada forma ...
Cyril H
By the way, congratulo-me com a melhora do código e abordagem, de modo que eles não piorar o resultado ...
Cyril M
1
Oi Cyril, eu concordo que ST_Buffer é uma boa opção para normalizar as linhas de contorno, perfeitas (!). Sobre ST_ConvexHull, é apenas uma curiosidade, que tipo de resultados podemos obter após a Figura 6, poly_voronoi_unionsem ST_ConvexHull.
22419 Peter Krauss
8

O Postgis não possui uma função dedicada ao voronoi, mas o Qgis contém a função vornoi, que pode criar polígonos voronoi a partir de pontos, portanto, usando o qgis, segui as seguintes etapas para obter este resultado:

- faça pontos de polígonos usando extract nodesfunções.

-Faça polígonos vornoi usando funções voroi no Qgis.

-Faça uma junção espacial no Qgis.

-dissolver resultados.

insira a descrição da imagem aqui

geogeek
fonte
1
Ótima solução (!), E obrigado pela ilustração. Você pode melhorar isso? Veja o retângulo esquerdo abaixo, tinha 4 pontos em Voronoi, e o centro do retângulo não tem representação, distorcendo sua região (perdendo para o triângulo) ... Talvez seja possível melhorar fazendo uma amostragem regular de cada polígono ... e talvez também alguns pontos interiores.
Peter Krauss
Eu uso a ferramenta densify no ArcGIS. Isso melhora significativamente os polígonos de proximidade. +1
FelixIP
3

OK - Pensei um pouco sobre isso e achei que era algo que eu tenho visto ultimamente.

Pegue suas políticas iniciais:

insira a descrição da imagem aqui

Gere um novo atributo com um número (100 no meu caso) Use a ferramenta Vetor-> Pesquisa -> Pontos aleatórios dentro dos polígonos, isso gerará (100) pontos dentro de cada polígono: insira a descrição da imagem aqui

Então Vector-> Ferramentas de geometria -> Voronoi para gerar polys com base nessa camada de pontos.

insira a descrição da imagem aqui

Agora, você pode usar a ferramenta Vetor -> Consulta espacial: Selecione os pontos que pertencem a um polígono (ou um dos polígonos). Use a ferramenta de consulta espacial para gerar uma seleção dos seus polígonos voronoi que se aplicam a esse polígono. Adicione um atributo ao polígono de voroni que corresponda ao polígono de interesse. (Acabei de usar 1,2,3,4)

Agora você pode Vector-> Ferramentas de Geoprocessamento-> dissolver com base no seu novo atributo.

insira a descrição da imagem aqui

AA
fonte
Obrigado @AAmes (!), As ilustrações são boas e o método é uma boa alternativa ... Mas a pergunta é sobre "um algoritmo SQL (ou algum específico para o PostGIS)" e agora, a recompensa pelo uso da função ST_VoronoiPolygons () , que, talvez, resolver todos os problemas em um clique ;-)
Peter Krauss
@AAmes Uma pesquisa rápida revela que esse método também pode ser usado no PostGIS. Como criar pontos aleatórios em um polígono no postgis explica a criação de pontos a partir de polígonos e a partir daí deve ser bastante simples.
Phil G
Minha recompensa foi para você, como incentivo (seja bem-vindo aqui!), Mas ESTA RESPOSTA ESTÁ FUNCIONANDO para os requisitos de perguntas e recompensas.
Peter Krauss
Obrigado Peter, eu vi suas anotações, mas infelizmente não tive a oportunidade de voltar e abordá-las. Ainda não tenho nenhuma experiência no PostGIS e levaria mais tempo do que eu tinha disponível para dar qualquer tipo de boa resposta. Espero que a nossa exploração deste espaço seja útil para as pessoas no futuro, talvez Se eu tiver uma brecha no PostGIS em breve, voltarei e darei outra batida nele para a prática!
AA
2

Pontos aleatórios são uma boa idéia para gerar um polígono de voronoi a partir de polígonos, funciona muito bem, mas é muito ruim para polígonos próximos um do outro: insira a descrição da imagem aqui insira a descrição da imagem aqui

ST_ApproximateMedialAxis é outra boa alternativa se estiver usando o PostGIS: calculando diagramas de Voronoi para polígonos

Leo
fonte