Comment identifier et simplifier les clusters de points en fonction du temps dans PostGIS?

11

Je viens de commencer à travailler avec des bases de données spatiales et je veux écrire une requête SQL (PostGIS) pour la généralisation automatique des traces GPS brutes (avec une fréquence de suivi fixe). La première chose sur laquelle je travaille est une requête qui identifie les points d'arrêt sous forme de requête comme "x points à une distance de y mètres" pour remplacer les nuages ​​de points massifs par des points représentatifs. Je me suis déjà rendu compte de prendre des points à une certaine distance et de compter les points cassés. Dans l'image ci-dessous, on peut voir un exemple de piste brute (petits points noirs) et les centres des points cassés sous forme de cercles colorés (taille = nombre de points cassés).

entrez la description de l'image ici

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;

Je serais tout aussi satisfait de cette solution, mais il y a le problème de temps: en imaginant la piste comme une piste d'une journée dans une ville, la personne peut retourner dans des endroits déjà visités auparavant. Dans mon exemple, le cercle bleu foncé représente le domicile de la personne qu'il a visité deux fois, mais ma requête l'ignore bien sûr.

Dans ce cas, la requête sophistiquée ne doit collecter que des points avec des horodatages (ou id) contigus, afin de produire ici deux points représentatifs. Ma première idée a été de modifier ma requête en version 3D (le temps comme troisième dimension), mais cela ne semble pas fonctionner.

Quelqu'un a-t-il des conseils pour moi? J'espère que ma question est claire.


Merci pour l'idée de ligne. J'ai réalisé pour faire et simplifier une chaîne de lignes comme vous pouvez le voir dans la capture d'écran ci-dessous (les points sont des points originaux). entrez la description de l'image ici Il me reste à déterminer les lieux de repos (> x points dans <x mètres de rayon), idéalement comme un point avec une heure d'arrivée et une heure de départ ... d'autres idées?

Berlin_J
la source
2
Avez-vous réellement besoin des points à d'autres fins? Sinon, cela ressemble peut-être à la simple création de lignes à partir des points, puis la simplification / généralisation de ces lignes servirait votre objectif.
Anthony -GISCOE-
2
C'est un problème fascinant. Vous pourrez peut-être glaner des idées provenant essentiellement de la même question que celle posée sur le site de Mathematica à l' adresse mathica.stackexchange.com/questions/2711 . Toutes les réponses n'exploitent pas la dimension temporelle des données (mais la mienne le fait :-).
whuber
@ Anthony-GISCOE- c'est une approche intéressante. Si des entités ponctuelles sont nécessaires, de nouvelles peuvent être créées à partir des sommets des lignes généralisées ou le long des lignes comme ici gis.stackexchange.com/questions/27102/… . Je sais, ce ne sont toujours pas les points d'origine!
andytilia
@ Anthony: J'ai absolument besoin des points de "représentation" de toute immobilité et au moins des heures de début et de fin ...
Berlin_J
1
et il serait vraiment utile d'avoir une solution
postgis

Réponses:

4

Si vous avez vraiment besoin de tous les points pour la visualisation, vous pouvez créer une ligne et st_simplify (qui est l'implémentation Douglas Peucker) ferait très bien le travail.

Dans certains cas, vous n'avez même pas besoin de stocker tous les points, vous pouvez donc effectuer un filtrage avant d'enregistrer les données de points, par exemple lorsque le sujet ne bouge pas, ne les stockez pas. Vous pouvez appliquer DouglasPeucker ou un autre filtre de base avant d'ajouter des points à DB. Certains fournisseurs de GPS (comme Android Location API) peuvent également effectuer automatiquement le filtrage initial en fonction du temps et de la distance minimale. Dans certains cas, vous faites garder des données en double: préfiltrées pour des visualisations rapides et journal complet pour l'archivage. Le stockage ordinaire est assez bon marché de nos jours.

JaakL
la source
3

Pendant ce temps, j'ai trouvé une solution à mon problème:

Tout d'abord, j'ai déterminé un "type de distance" pour chaque point. Si le point est plus proche de x mètres du point suivant, il est déterminé comme "stop", sinon comme "move". Ensuite, j'ai commencé une fonction de fenêtre comme celle-ci:

     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;

Le tableau résultant se présente comme suit:

entrez la description de l'image ici

L'étape suivante simple regroupe les points "d'arrêt", identifie le centre de gravité de ces groupes de points et prend les horodatages minimum et maximum comme heure d'arrivée et de départ.

Berlin_J
la source