¿Cómo identificar y simplificar los grupos de puntos con respecto al tiempo en PostGIS?

11

Recién comencé a trabajar con bases de datos espaciales y quiero escribir una consulta SQL (PostGIS) para la generalización automática de pistas GPS sin procesar (con frecuencia de seguimiento fija). Lo primero en lo que estoy trabajando es una consulta que identifica puntos de parada en forma de consulta como "puntos x dentro de una distancia de y metros" para reemplazar las nubes de puntos masivas por puntos representativos. Ya me di cuenta de tomar puntos dentro de una cierta distancia y contarlos. En la siguiente imagen, se puede ver una pista de ejemplo sin formato (pequeños puntos negros) y los centros de los puntos ajustados como círculos de colores (tamaño = número de puntos ajustados).

ingrese la descripción de la imagen aquí

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;

Estaría bastante satisfecho con esta solución, pero existe el problema del tiempo: imaginando la pista como una pista de día completo en una ciudad, la persona puede regresar a lugares ya visitados anteriormente. En mi ejemplo, el círculo azul oscuro representa el hogar de la persona que visitó dos veces, pero mi consulta, por supuesto, lo ignora.

En este caso, la consulta sofisticada solo debe recopilar puntos con marcas de tiempo contiguas (o id), para que produzca dos puntos representativos aquí. Mi primera idea fue una modificación de mi consulta a una versión 3D (tiempo como tercera dimensión), pero no parece funcionar.

¿Alguien tiene algún consejo para mí? Espero que mi pregunta sea clara.


Gracias por la idea de línea. Me di cuenta de hacer y simplificar una cadena lineal como se puede ver en la captura de pantalla a continuación (los puntos son puntos originales). ingrese la descripción de la imagen aquí Lo que aún necesito es determinar los lugares de descanso (> x puntos en <x metros de radio), idealmente como un punto con una hora de llegada y una hora de salida ... ¿alguna otra idea?

Berlin_J
fuente
2
¿Realmente necesitas los puntos para otros fines? De lo contrario, parece que tal vez solo crear líneas a partir de los puntos, y luego simplificar / generalizar esas líneas serviría para su propósito.
Anthony -GISCOE-
2
Es un problema fascinante. Es posible que pueda obtener algunas ideas esencialmente de la misma pregunta que se hizo en el sitio de Mathematica en Mathica.stackexchange.com/questions/2711 . No todas las respuestas explotan la dimensión temporal de los datos (pero la mía sí :-).
whuber
@ Anthony-GISCOE: es un enfoque interesante. En caso de que se necesiten entidades de puntos, se podrían crear nuevas a partir de los vértices de las líneas generalizadas, o a lo largo de las líneas como aquí gis.stackexchange.com/questions/27102/… . Lo sé, ¡esos todavía no son los puntos originales!
andytilia
@ Anthony: Necesito absolutamente los puntos de "representación" de cualquier punto muerto y, al menos, el inicio y el final ...
Berlin_J
1
y sería realmente útil tener una solución
postgis

Respuestas:

4

Si realmente necesita todos los puntos para la visualización, puede crear una línea y st_simplify (que es la implementación de Douglas Peucker) haría el trabajo bastante bien.

En algunos casos, ni siquiera necesita almacenar todos los puntos, por lo que puede filtrar antes de guardar los datos de los puntos, por ejemplo, cuando el sujeto no se mueve, no lo almacene. Puede aplicar DouglasPeucker o algún otro filtro básico antes de agregar puntos a la base de datos. Además, algunos proveedores de GPS (como la API de ubicación de Android) pueden realizar automáticamente el filtrado inicial en función del tiempo y la distancia mínima. En algunos casos, debe mantener datos duplicados: prefiltrados para visualizaciones rápidas y registro completo para el archivo. El almacenamiento simple es bastante barato hoy en día.

JaakL
fuente
3

Mientras tanto, encontré una solución para mi problema:

Primero, determiné un "tipo de distancia" para cada punto. Si el punto está más cerca como x metros del siguiente punto, se determina como "detener", de lo contrario, como "mover". Entonces, comencé una función de ventana 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;

La tabla resultante tiene el siguiente aspecto:

ingrese la descripción de la imagen aquí

El siguiente paso simple agrupa los puntos de "detención", identifica el centroide de estos grupos de puntos y toma las marcas de tiempo mínimas y máximas como hora de llegada y salida.

Berlin_J
fuente