Consulta Recursiva PostGIS Baseada em Conectividade de Linha

9

Estou tendo dificuldades com uma consulta. Eu tenho uma rede de cadeias de linhas, cada uma com um valor na coluna n_type. Essa pode ser uma das poucas opções. Eu gostaria de gerar uma nova tabela que agrupe todas as cadeias de linha que são do mesmo tipo e que formam uma linha contínua.

Antes:

insira a descrição da imagem aqui

Depois de:

insira a descrição da imagem aqui

Aqui está o que eu tenho até agora. Ele retorna resultados, mas eles não fazem sentido - os tipos não correspondem e retornam muitos recursos.

Observe também que eu defini "contínua" como qualquer linha a um metro e meio de distância do seu vizinho e que se encontre com um ângulo inferior a 30 graus.

WITH RECURSIVE all_links (i, pk_uid, n_type, geom) AS (
    SELECT  1 AS i,
            pk_uid,
            n_type,
            geom
    FROM    network
    WHERE   n_type != 'none'

    UNION ALL

    SELECT  a.i + 1,
            b.pk_uid,
            b.n_type,
            b.geom
    FROM    network b, all_links a
    WHERE   b.n_type = a.n_type
    AND     b.geom <#> a.geom <= 5  --lines are continuous if within 5 feet of neighbor
    AND     ABS( DEGREES( 3*pi() - st_azimuth(st_startpoint(a.geom),st_endpoint(a.geom)) + st_azimuth(st_startpoint(b.geom),st_endpoint(b.geom)))::int % 360 - 180) <= 30 )  --only take links within 30 degrees of the same angle

SELECT i, n_type, ST_Union(the_geom) FROM all_links GROUP BY i, n_type

Eu assumi que uma consulta recursiva é o caminho a percorrer, mas estou feliz por ter provado que está errado nisso. As recursivas são um pouco difíceis de entender.

Editar: devo acrescentar que já tentei agregar usando ST_Union e ST_Linemerge e depois despejar o resultado. Isso meio que funciona, mas não representa interseções de mais de 30 graus e também não pode respeitar a tolerância de cinco pés para conectividade.

spencerrecneps
fonte
Sem se aprofundar nisso, algumas observações. Você precisará unir a.geom e b.geom na sua cláusula de seleção. Você provavelmente deve ter certeza de que você não tentar e juntar-se uma linha para si, bem como coma.pk_uid != b.pk_uid
MickyT
@MickyT thanks. Eu deveria ter mencionado que posso fazer a união na última cláusula SELECT, mas, por enquanto, acabei de selecionar * para que eu possa ver todos os resultados. Modificarei meu snippet de código para mostrar como ele deve se parecer.
Spencerrecneps
É difícil obter consultas recursivas. Lol e +1
John Powell
Uma rápida olhada sugere que você pode ter problemas com sua consulta de base / âncora. Você precisa selecionar o ponto inicial de cada linha, A, B, C, etc., que você constrói na parte recursiva. Possivelmente, você precisa adicionar algum tipo de ordem à consulta âncora (talvez na direção x ou y, difícil de saber sem ver os dados). Eu dividiria isso e garantiria que eu estivesse obtendo pontos de partida sensatos primeiro, antes de continuar com a parte recursiva. Eu usei uma consulta recursiva para encontrar faixas nas séries temporais recentemente, e uma vez que eu tinha os pontos de ancoragem identificado corretamente, o resto foi fácil (ish)
John Powell
@dbaston. Bom ponto, mas você pode fazer isso com uma consulta recursiva também, e nem todo mundo tem isso instalado ainda.
John Powell

Respostas:

1

Sua solução está, pelo menos, faltando uma pré-encomenda dos componentes da linha, como disse John Barça.

Consultas recursivas são muito, muito difíceis de entender, eu diria.

Você deve tentar replicar o comportamento ST_Linemerge em uma nova função de banco de dados. Eu tentaria primeiro examinar a origem de uma implementação ST_Linemerge e replicar, alterando-a para produzir a contração de um ângulo de 30 graus.

Para descartar da agregação os segmentos que não estão em um ângulo de <30 graus., Você deve compará-los DENTRO de um loop de agregação.

rpcavaco
fonte