Come identificare e semplificare i cluster di punti per quanto riguarda il tempo in PostGIS?


11

Ho appena iniziato a lavorare con database spaziali e voglio scrivere una query SQL (PostGIS) per la generalizzazione automatica di tracce GPS non elaborate (con frequenza di tracciamento fissa). La prima cosa su cui mi sto prendendo in giro è una query che identifica i punti di arresto in forma di query come "punti x entro una distanza di y metri" per sostituire enormi nuvole di punti con punti rappresentativi. Mi sono già reso conto di catturare punti entro una certa distanza e contare quelli scattati. Nell'immagine seguente si può vedere una traccia di esempio grezza (piccoli punti neri) e i centri dei punti spezzati come cerchi colorati (dimensione = numero di punti spezzati).

inserisci qui la descrizione dell'immagine

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;

Sarei abbastanza soddisfatto di questa soluzione, ma c'è il problema del tempo: immaginando la traccia come una traccia di un'intera giornata in una città, la persona può tornare in luoghi già visitati in precedenza. Nel mio esempio, il cerchio blu scuro rappresenta la casa della persona che ha visitato due volte, ma la mia domanda ovviamente lo ignora.

In questo caso, la query sofisticata dovrebbe raccogliere solo punti con timestamp (o ID) contigui, in modo da produrre qui due punti rappresentativi. La mia prima idea è stata una modifica della mia query a una versione 3d (ora come terza dimensione), ma non sembra funzionare.

Qualcuno ha qualche consiglio per me? Spero che la mia domanda sia chiara.


Grazie per l'idea di linea. Mi sono reso conto di creare e semplificare una stringa lineare come puoi vedere nello screenshot qui sotto (i punti sono punti originali). inserisci qui la descrizione dell'immagine Ciò di cui ho ancora bisogno è determinare i luoghi di riposo (> x punti nel raggio di <x metri), idealmente come un punto con un orario di arrivo e un orario di partenza ... altre idee?


2
Hai davvero bisogno dei punti per altri scopi? Altrimenti, sembra che forse semplicemente creare linee dai punti, e quindi semplificare / generalizzare quelle linee servirebbe al tuo scopo.
Anthony -GISCOE-

2
È un problema affascinante. Potresti essere in grado di trarre alcune idee essenzialmente dalla stessa domanda che è stata posta sul sito Mathematica all'indirizzo matematica.stackexchange.com/questions/2711 . Non tutte le risposte sfruttano la dimensione temporale dei dati (ma la mia fa :-).
whuber

@ Anthony-GISCOE- questo è un approccio interessante. Nel caso in cui siano necessarie funzionalità punto, è possibile crearne di nuove dai vertici delle linee generalizzate o lungo le linee come qui gis.stackexchange.com/questions/27102/… . Lo so, quelli non sono ancora i punti originali!
andytilia,

@Antonio: ho assolutamente bisogno dei "punti di rappresentazione" di qualsiasi punto fermo e almeno inizio e fine ...
Berlin_J,

1
e sarebbe davvero utile avere una soluzione
postgis

Risposte:


4

Se hai davvero bisogno di tutti i punti per la visualizzazione, puoi creare una linea e st_simplify (che è l'implementazione di Douglas Peucker) farebbe il lavoro abbastanza bene.

In alcuni casi non è nemmeno necessario memorizzare tutti i punti, quindi è possibile effettuare il filtraggio prima di salvare i dati dei punti, ad esempio quando il soggetto non si sposta, non memorizzarli. È possibile applicare DouglasPeucker o qualche altro filtro di base prima di aggiungere punti al DB. Inoltre, alcuni provider GPS (come l'API Android Location) possono eseguire automaticamente il filtro iniziale in base al tempo e alla distanza minima. In alcuni casi, tieni i dati duplicati: prefiltrati per visualizzazioni veloci e registro completo per l'archivio. L'archiviazione semplice è abbastanza economica al giorno d'oggi.


3

Nel frattempo, ho trovato una soluzione per il mio problema:

Innanzitutto, ho determinato un "tipo di distanza" per ogni punto. Se il punto è più vicino di x metri al punto successivo, viene determinato come "stop", altrimenti come "sposta". Quindi, ho avviato una funzione di finestra come questa:

     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 tabella risultante ha il seguente aspetto:

inserisci qui la descrizione dell'immagine

Il semplice passaggio successivo raggruppa i punti "stop", identifica il centroide di questi gruppi di punti e prende i timestamp minimi e massimi come orario di arrivo e di partenza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.