Como identificar e simplificar clusters de pontos em relação ao tempo no PostGIS?

11

Comecei a trabalhar com bancos de dados espaciais e quero escrever uma consulta SQL (PostGIS) para generalização automática de trilhas GPS brutas (com frequência de rastreamento fixa). A primeira coisa em que estou trabalhando é uma consulta que identifica pontos de parada na forma de consulta como "x pontos a uma distância de y metros" para substituir nuvens de pontos maciças por pontos representativos. Eu já percebi encaixar pontos a uma certa distância e contar os encaixados. Na figura abaixo, é possível ver uma trilha de exemplo bruto (pequenos pontos pretos) e o centro dos pontos quebrados como círculos coloridos (tamanho = número de pontos quebrados).

insira a descrição da imagem aqui

CREATE table simplified AS 
 SELECT count(raw.geom)::integer AS count, st_centroid(st_collect(raw.geom)) AS center
   FROM raw
  GROUP BY st_snaptogrid(raw.geom, 500, 0.5)
  ORDER BY count(raw.geom) DESC;

Eu ficaria muito satisfeito com esta solução, mas existe o problema do tempo: imaginar a pista como uma pista de dia inteiro em uma cidade em que a pessoa pode retornar a lugares já visitados anteriormente. No meu exemplo, o círculo azul escuro representa a casa da pessoa que ele visitou duas vezes, mas é claro que minha pergunta ignora isso.

Nesse caso, a consulta sofisticada deve coletar apenas pontos com registros de data e hora contíguos (ou IDs), para que produza aqui dois pontos representativos. Minha primeira ideia foi uma modificação da minha consulta para uma versão 3d (tempo como terceira dimensão), mas parece não funcionar.

Alguém tem algum conselho para mim? Espero que minha pergunta seja clara.


Obrigado pela ideia da linha. Eu percebi fazer e simplificar uma cadeia de linhas, como você pode ver na captura de tela abaixo (pontos são pontos originais). insira a descrição da imagem aqui O que eu ainda preciso é determinar os locais de descanso (> x pontos em <x metros de raio), idealmente como um ponto com um horário de chegada e um horário de saída ... outras idéias?

Berlin_J
fonte
2
Você realmente precisa dos pontos para outros fins? Caso contrário, parece que apenas criar linhas a partir dos pontos e simplificar / generalizar essas linhas serviriam ao seu propósito.
Anthony -GISCOE- #:
2
É um problema fascinante. Você pode coletar algumas idéias essencialmente da mesma pergunta que foi feita no site do Mathematica em mathematica.stackexchange.com/questions/2711 . Nem todas as respostas exploram a dimensão temporal dos dados (mas a minha sim :-).
whuber
@ Anthony-GISCOE- essa é uma abordagem interessante. Caso sejam necessários recursos de pontos, novos poderão ser criados a partir dos vértices das linhas generalizadas ou ao longo das linhas como aqui gis.stackexchange.com/questions/27102/… . Eu sei, esses ainda não são os pontos originais!
22712 Andytilia
@ Anthony: Eu absolutamente preciso dos pontos de "representação" de qualquer ponto morto e, pelo menos, do começo e do fim ...
Berlin_J 23/10/12
1
e que seria muito útil ter um postgis-solução :)
Berlin_J

Respostas:

4

Se você realmente precisar de todos os pontos de visualização, poderá criar uma linha e o st_simplify (que é a implementação de Douglas Peucker) faria o trabalho muito bem.

Em alguns casos, você nem precisa armazenar todos os pontos; portanto, você pode filtrar antes de salvar os dados dos pontos; por exemplo, quando o assunto não se mover, não os armazene. Você pode aplicar o DouglasPeucker ou algum outro filtro básico antes de adicionar pontos ao DB. Além disso, alguns provedores de GPS (como a API do Android Location) podem fazer a filtragem inicial com base no tempo e na distância mínima automaticamente. Em alguns casos, você mantém dados duplicados: pré-filtrados para visualizações rápidas e log completo para arquivamento. Atualmente, o armazenamento simples é bastante barato.

JaakL
fonte
3

Enquanto isso, encontrei uma solução para o meu problema:

Primeiro, eu determinei um "tipo de distância" para cada ponto. Se o ponto estiver mais próximo de x metros do próximo ponto, será determinado como "parar", caso contrário, como "mover". Então, iniciei uma função de janela como esta:

     SELECT t1.id, t1.dist_type, t1."time", t1.the_geom, t1.group_flag, sum(t1.group_flag) OVER (ORDER BY t1.id) AS group_nr
FROM ( SELECT distances.id, distances.the_geom, distances."time", distances.dist_type, 
                CASE
                    WHEN lag(distances.dist_type) OVER (ORDER BY distances.id) = distances.dist_type THEN NULL::integer
                    ELSE 1
                END AS group_flag
           FROM distances) t1;

A tabela resultante tem a seguinte aparência:

insira a descrição da imagem aqui

A próxima etapa simples agrupa os pontos de "parada", identifica o centróide desses grupos de pontos e assume os carimbos de data e hora mínimos e máximos como hora de chegada e saída.

Berlin_J
fonte