Wie können zeitliche Punktcluster in PostGIS identifiziert und vereinfacht werden?

11

Ich habe gerade angefangen, mit räumlichen Datenbanken zu arbeiten, und möchte eine SQL-Abfrage (PostGIS) zur automatischen Verallgemeinerung von rohen GPS-Tracks (mit fester Tracking-Frequenz) schreiben. Das erste, woran ich arbeite, ist eine Abfrage, die Stillstandspunkte in Form einer Abfrage wie "x Punkte in einem Abstand von y Metern" identifiziert, um massive Punktwolken durch repräsentative Punkte zu ersetzen. Ich habe bereits erkannt, dass ich Punkte innerhalb einer bestimmten Entfernung fangen und die gerissenen zählen muss. Im Bild unten sehen Sie eine rohe Beispielspur (kleine schwarze Punkte) und die Zentren der Fangpunkte als farbige Kreise (Größe = Anzahl der Fangpunkte).

Geben Sie hier die Bildbeschreibung ein

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;

Ich wäre mit dieser Lösung genauso zufrieden, aber es gibt das Zeitproblem: Stellen Sie sich die Strecke als Ganztagesstrecke in einer Stadt vor, in der die Person zu bereits zuvor besuchten Orten zurückkehren kann. In meinem Beispiel repräsentiert der dunkelblaue Kreis das Haus der Person, die sie zweimal besucht hat, aber meine Anfrage ignoriert das natürlich.

In diesem Fall sollte die anspruchsvolle Abfrage nur Punkte mit zusammenhängenden Zeitstempeln (oder IDs) sammeln, damit hier zwei repräsentative Punkte erzeugt werden. Meine erste Idee war eine Änderung meiner Abfrage auf eine 3D-Version (Zeit als dritte Dimension), aber es scheint nicht zu funktionieren.

Hat jemand einen Rat für mich? Ich hoffe, dass meine Frage klar ist.


Danke für die Line-Idee. Ich habe festgestellt, dass ich einen Linestring erstellen und vereinfachen muss, wie Sie im folgenden Screenshot sehen können (Punkte sind Originalpunkte). Geben Sie hier die Bildbeschreibung ein Was ich noch brauche, ist die Bestimmung der Ruheplätze (> x Punkte in <x Metern Radius), idealerweise als ein Punkt mit einer Ankunfts- und einer Abfahrtszeit ... irgendwelche anderen Ideen?

Berlin_J
quelle
2
Benötigen Sie die Punkte tatsächlich für andere Zwecke? Andernfalls klingt es so, als würden Sie vielleicht nur Linien aus den Punkten erstellen und dann diese Linien vereinfachen / verallgemeinern, um Ihren Zweck zu erfüllen.
Anthony-GISCOE-
2
Es ist ein faszinierendes Problem. Möglicherweise können Sie einige Ideen aus im Wesentlichen derselben Frage ableiten, die auf der Mathematica- Website unter mathematica.stackexchange.com/questions/2711 gestellt wurde . Nicht alle Antworten nutzen die zeitliche Dimension der Daten aus (meine jedoch :-).
whuber
@ Anthony-GISCOE- das ist ein interessanter Ansatz. Falls Punkt-Features benötigt werden, können neue aus den Eckpunkten der verallgemeinerten Linien oder entlang der Linien wie hier gis.stackexchange.com/questions/27102/… erstellt werden . Ich weiß, das sind immer noch nicht die ursprünglichen Punkte!
Andytilia
@ Anthony: Ich brauche unbedingt die "Repräsentations" -Punkte eines Stillstands und zumindest Start- und Endzeit ...
Berlin_J
1
und es wäre wirklich nützlich, eine Postgis-Lösung zu haben :)
Berlin_J

Antworten:

4

Wenn Sie wirklich alle Punkte für die Visualisierung benötigen, können Sie eine Linie erstellen und st_simplify (dies ist die Implementierung von Douglas Peucker) würde die Arbeit ganz gut erledigen.

In einigen Fällen müssen Sie nicht einmal alle Punkte speichern, sodass Sie vor dem Speichern von Punktdaten filtern können. Wenn sich das Motiv nicht bewegt, speichern Sie es nicht. Sie können DouglasPeucker oder einen anderen Grundfilter anwenden, bevor Sie der DB Punkte hinzufügen. Einige GPS-Anbieter (wie die Android Location API) können die anfängliche Filterung basierend auf Zeit und Mindestentfernung automatisch durchführen. In einigen Fällen behalten Sie doppelte Daten bei: vorgefiltert für schnelle Visualisierungen und vollständiges Protokoll für das Archiv. Einfache Lagerung ist heutzutage ziemlich billig.

JaakL
quelle
3

Inzwischen habe ich eine Lösung für mein Problem gefunden:

Zuerst habe ich für jeden Punkt einen "Entfernungstyp" bestimmt. Wenn der Punkt näher als x Meter am nächsten Punkt liegt, wird er als "Stopp", andernfalls als "Bewegen" bestimmt. Dann habe ich eine Fensterfunktion wie folgt gestartet:

     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;

Die resultierende Tabelle sieht wie folgt aus:

Geben Sie hier die Bildbeschreibung ein

Der einfache nächste Schritt gruppiert die "Stopp" -Punkte, identifiziert den Schwerpunkt dieser Punktgruppen und verwendet minimale und maximale Zeitstempel als Ankunfts- und Abfahrtszeit.

Berlin_J
quelle