Ajustando nós iniciais e finais das linhas para outras linhas no PostGIS

9

Existem muitos exemplos que mostram como ajustar linhas a pontos, mas não consegui encontrar nenhuma maneira (rápida!) De ajustar os nós de início e de fim das cadeias de linhas para os de outras linhas.

Essencialmente, quero "limpar" minha camada no postgis (2.0), juntando pontos quase semelhantes e costurando pequenas aberturas entre as linhas.

Não importa muito se eu adiciono outro nó, movo o primeiro / último nó de qualquer linha ou movo os dois pontos para o centro.

Encontrei duas opções, mas não sei como começar com uma delas:

A segunda opção parece viável, mas qualquer ajuda sobre como seguir esse método seria muito apreciada.

Jelmer Baas
fonte

Respostas:

6

Consegui resolver isso, sem usar as ferramentas GRASS ou funções topológicas mencionadas.

Basicamente, pego todos os nós de início e de fim, os coloco em uma nova tabela temporária, coloco um buffer em torno deles, uno os objetos de buffer e movo todos os nós encontrados em cada buffer para o centróide do buffer.

Quando isso é feito, movo os pontos inicial e final originais para o novo local.

Mais fácil do que o esperado e ainda rápido, mas eu esperava que o PostGIS tivesse alguma função interna para isso - isso seria ainda mais rápido.

Edit: no interesse de retribuir à comunidade, este é o meu código (bastante ruim) por enquanto.

drop table if exists nodes;
drop table if exists nodes2;
drop table if exists buffers;

-- Get Start and End nodes
select ST_StartPoint(wkb_geometry) startnode,  ST_EndPoint(wkb_geometry) endnode,    ogc_fid into nodes  from sourceTable;
-- Combine all nodes into one table for easier queries
select startnode node, ogc_fid into nodes2 from nodes;
insert into nodes2 select endnode node, ogc_fid from nodes;

-- Some indexes to speed everything up
CREATE INDEX nodesstart_idx ON nodes USING gist  (startnode);
CREATE INDEX nodesend_idx ON nodes USING gist  (endnode);
CREATE INDEX nodes2_idx ON nodes2 USING gist  (node);
CREATE INDEX nodes_ogcfid_idx ON nodes USING btree (ogc_fid ASC NULLS LAST);

-- Create buffers, combine them, split combined objects again
select (ST_Dump(ST_Union(ST_Buffer(node, 1)))).geom geom into buffers from nodes2;
CREATE INDEX buffers_idx ON buffers USING gist  (geom);

-- Update start/end nodes table
UPDATE nodes SET startnode = ST_Centroid((select geom from buffers WHERE geom && startnode));
UPDATE nodes SET endnode = ST_Centroid((select geom from buffers WHERE geom && endnode));
-- Update original points
update sourceTable set wkb_geometry = ST_SetPoint(
ST_SetPoint(wkb_geometry, 0, (select startnode from nodes where ogc_fid=sourceTable.ogc_fid)), 
ST_NumPoints(wkb_geometry) - 1, (select endnode from nodes where ogc_fid=sourceTable.ogc_fid));

DROP TABLE nodes;
DROP TABLE nodes2;
DROP TABLE buffers;
Jelmer Baas
fonte
Essa resposta se parece bastante com a sugestão "não topológica" da minha resposta. Seria gentil se você desse um voto positivo ou selecionasse a resposta. São esses os alimentos que alimentam a comunidade aqui :) #
484
Você está certo. Votei sua resposta de forma positiva e editarei minha resposta para incluir meu código.
Jelmer Baas
4

Aqui estão três opções. Espero que alguém ajude.

v.clean

Usando as ferramentas GRASS no QGIS, você pode limpar a topologia de um objeto espacial. O usuário @RK fornece um bom conjunto de instruções sobre como fazer isso em resposta a uma pergunta diferente . A vantagem que o GRASS oferece é que ele inferirá a topologia do shapefile. A desvantagem da sua situação é que seus dados não estão em um shapefile. Obviamente, você pode exportar os dados do Postgres para um shapefile usando a ferramenta "Adicionar camada PostGIS", mas essa é uma etapa extra.

Funções PostGIS não topológicas

Em PostGIS você pode usar as ST_Endpoint e ST_StartPoint funções para obter o fim e começar a ponto para uma cadeia de linha. Em seguida, usando uma combinação de ST_DWithi n e ST_Distance , você pode encontrar o ponto inicial ou final mais próximo em uma geometria próxima. Se você tiver muitos pontos, o ST_DWithin acelerará bastante a consulta - supondo que você tenha um índice no lugar. A partir daí, você precisará estabelecer uma regra que defina quais pontos serão modificados e quais serão corrigidos.

A vantagem aqui é que você não precisa enviar seus dados ao GRASS para limpeza, mas existem algumas armadilhas a serem observadas.

Funções topológicas PostGIS

A questão referenciou as funções topológicas do PostGIS. Eles funcionam muito bem, mas, como o wiki descreve , é necessário definir explicitamente as arestas, nós e faces. Claramente, isso será um problema para o seu conjunto de dados, pois você conhece problemas com a topologia.

katahdin
fonte
1

O PostGIS possui funções de encaixe. Talvez elas ajudem?

ST_Snap: Encaixe segmentos e vértices da geometria de entrada nos vértices de uma geometria de referência.

ST_SnapToGrid: Encaixe todos os pontos da geometria de entrada em uma grade regular.

Jordan Arseno
fonte
11
Obrigado, estou ciente dessas funções. ST_Snap encaixa TODOS os nós, só quero o nó inicial e final. ST_SnapToGrid não é realmente adequado porque modifica toda a geometria existente e tem a chance de mover nós que estão mais distantes, porque mal caem em outro segmento.
Jelmer Baas