Atualmente, estou trabalhando no campo de isócronas e nos algoritmos subjacentes. O que agora causa problemas não é o cálculo da própria isócrona, mas a visualização dos resultados.
O resultado do meu algoritmo de isócrona são pontos e arestas. Na verdade, eu tenho uma solução funcional, mas para 3873 bordas e para 1529 nós as coisas parecem durar uma eternidade (cerca de 2,0 segundos no meu laptop Lenovo T440s, que contém uma CPU Core i7 2015 e um SSD bastante rápido). Em vez de segundos, quero algo mais como msec :-).
Talvez alguém possa me ajudar a reduzir o tempo de cálculo necessário para construir os polígonos que visualizam as áreas acessíveis.
Mas espere ... as primeiras coisas primeiro!
Aqui está uma visualização das arestas que são o resultado do cálculo da minha isócrona:
essas arestas são armazenadas em uma tabela de banco de dados PostGIS e são cadeias de linhas simples.
O que quero mostrar ao usuário é o seguinte: Observe as áreas desconectadas no sul e leste da imagem. Elas devem ser desenhadas como áreas separadas (portanto, nenhuma fusão é permitida aqui :-))
Atualmente, estou usando esta consulta:
SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
SELECT ST_MakePolygon(ST_ExteriorRing(ST_GeometryN(segments, generate_series(1, ST_NumGeometries(segments))))) AS polygons FROM (
SELECT ST_Union(ST_Buffer("GEOMETRY", 20, 'quad_segs=2')) AS segments FROM my_edges AS a
) AS b
) AS c
Eu já fiz algumas experiências e também li muita documentação, mas simplesmente não consigo encontrar uma solução melhor.
A meu ver, o grande problema é o uso do ST_Union (conforme declarado nos documentos, essa função pode ser lenta). O mais interessante é que substituí-lo por ST_Collect parece desacelerar o cálculo ST_Buffer para que a consulta a seguir leve mais tempo, embora não preencha as áreas entre as bordas (apenas cria um buffer ao redor das linhas ):
SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
SELECT ST_Buffer(ST_Collect(ST_LineMerge("GEOMETRY")), 20, 'quad_segs=2') AS polygons FROM my_edges AS a
) AS b
Isso leva cerca de 3,8 segundos no meu sistema (quase o dobro do tempo). Minha primeira conclusão dessa pequena referência é que ST_Buffer fica inesperadamente lento quando se trata de MultiLineStrings (ainda mais lento do que ao criar buffers para cada linha e mesclar os buffers - o que aos meus olhos é estranho)
Também tentei usar formas alfa (usando a implementação de pgRouting), mas como não há valor alfa a ser definido (e, na verdade, não seria agora a que valor definir esse valor), apenas recebo um ótimo polígono ( então eu perderia as regiões no sul e leste como regiões separadas, e não é isso que eu quero).
O ST_Polygonize (que foi a primeira coisa que me veio à cabeça) não produziu nenhum resultado utilizável, mas talvez eu tenha perdido algo aqui ...
Existe uma maneira melhor de criar a área mostrada no PostGIS? Talvez também usando o código java (jts) ou o código javascript do lado do cliente (jsts)? Na verdade, eu poderia perder alguns detalhes, desde que as áreas mostradas em meu resultado permaneçam separadas e o cálculo fique (muito) mais rápido.
fonte
Respostas:
Deixando de lado a serialização GeoJSON, o seguinte leva cerca de 6,3 segundos no meu laptop:
Observando os dados no OpenJUMP, notei bastante detalhe nos segmentos das ruas, em relação ao nível de detalhe desejado na saída. Parece que mesmo uma simplificação on-the-fly dessas linhas pode produzir uma grande aceleração no PostGIS:
o que reduz as coisas para 2,3 segundos. Eu pensei que talvez pudesse fazer melhor armazenando a geometria generalizada em uma coluna separada, em vez de calculá-la em tempo real, mas isso realmente não forneceu nenhum benefício adicional.
Dependendo da quantidade de código que você deseja escrever, é quase certo que você pode se sair melhor em Java, se nada mais, porque você pode tirar proveito de vários núcleos. (Pelo que vale a pena, o JTS executa a operação acima em 2,8 segundos). Uma abordagem pode ser estender
CascadedPolygonUnion
para que algumas das operações sindicais ocorram paralelamente. (atualização - aqui está um ParallelCascadedPolygonUnion )Percebi nos dados da amostra que as bordas são armazenadas com referências aos nós iniciais e finais, ou seja, você tem um gráfico pré-construído. Suspeito que você possa gerar esses polígonos muito mais rapidamente se trabalhar com o gráfico em vez de usar operações de geometria genérica. Por exemplo, acho que você poderia fazer algo assim:
fonte
ST_ClusterIntersecting
mas acho que você deseja que qualquer tipo de processamento de gráfico aconteça fora do banco de dados, portanto isso provavelmente não é útil).