Punkte zu Linien zusammenfassen

Hallo Forum,

ich verwalte GPS Daten in eine PostGIS Datenbank. Mein GPS Empfänger kennt Waypoints und Trackpoints (Geometry POINT 2D) die einen Track zugeordnet sind. Die Zuordnung der Trackpoints zu Tracks geschieht über zwei weitere Tabellen.

Mir geht es bei der Frage um die Trackpoints. Ich möchte einen View erstellen, der mir pro Track eine Linie (Geometry LINE) aus den zugehörigen Trackpoints erstellt.

Folgende SQL Anweisung erstellt mir einen VIEW mit der nach Track und Position im Track sortierte Aufstellung der Trackpoints

CREATE OR REPLACE VIEW v_gps_track (trkid, trk_name, trk_desc, trkpt_id, trkpt_geom, trkpt_ele, trkpt_time ) AS 
SELECT track.fid as trk_fid, track.name as name, track.description as description, trackpoint.fid as trkpt_fid, trackpoint.geometry_trackpoint as trkpt_geom, trackpoint.ele as trkpt_ele, trackpoint.time as trkpt_time
FROM track, trackpoint, track_trackpoint
WHERE track.fid=track_trackpoint.ref_fid_track
AND trackpoint.fid=track_trackpoint.ref_fid_trackpoint
ORDER BY track.fid, track_trackpoint.trackposition

Wie kann ich jetzt die einzelnen Trackpoints eines Track zu einer Geometry LINIE zusammenführen?

Es müsste doch irgendwie mit “LineFromMultipoint(Collect(trkpt_geom))” gehen. Ich habe bis jetzt noch nicht hinbekommen, dass der Linienzug sich an die Position der Trackpoints im Track hält.

Vielleicht könnt ihr mir helfen!

Gruß, Torsten

Hallo Forum,

nach weiteren Experimenten bin ich zum folgenden SQL Statement zum anlegen des Views gekommen:

CREATE OR REPLACE VIEW v_gps_track (id, geometry )AS 
SELECT track.fid as id, MakeLine(track.geometry_trackpoint) as geometry
FROM ( SELECT track.fid, trackpoint.geometry_trackpoint
FROM track, trackpoint, track_trackpoint
where track.fid=track_trackpoint.ref_fid_track
AND trackpoint.fid=track_trackpoint.ref_fid_trackpoint
ORDER BY track.fid, track_trackpoint.trackposition ) track
GROUP BY track.fid

Die Sache hat leider einen Haken, wenn ich in den VIEW weitere Spalten wie z.B. Trackname und Trackbeschreibung einfügen möchte, muss ich die jeweiligen Spalten auch immer in der GROUP BY Klausel angeben. Dies führt zu “wilden” Verbindungen der Trackpunkte untereinander. (Bedingt durch die angegebenen Gruppierungen) Wie kann ich weitere Spalten in den View eintragen ohne eine Erweiterung der GROUP BY Klausel?

Gruß, Torsten

Du kannst auch Collect verwenden um die Punkte zusammenzufassen. Das funktioniert wie eine Aggregatfunktion. Um da Grop By wirst du aben wohl nicht rumkommen. Höchstens über subselects, aber ob das einfacher ist, sei mal dahin gestellt.
Ich hab grad leider keine Möglichkeit die Syntax nachzuschlagen, da müsstest du dich bis morgen gedulden :wink:

Gruß Uwe

Hallo Gisman,

in den “sauren Apfel” des Subselects werde ich wohl beisen müssen. Die Group By Klausel darf nicht um die zusätzlichen Spalten erweitert werden. Sonst gibt es wirre Verbindungen der Punkte im Linienzug (durch die weiteren Gruppierungen).
Gibt es einen Performance Unterschied zwischen deinen Vorschlag (Collect) und der MakeLine Methode? Oder sonstige Gründe eine Methode zu bevorzugen?

Gruß, Torsten

Hallo Forum,

ich habe das Problem gelöst, hier die SQL Statements für die beiden Lösungsansätze.

  1. Ansatz MakeLine(…)
CREATE OR REPLACE VIEW v_gps_track (id, geometry, name, description) AS 
  SELECT track.fid as id, 
         -- Geometrie Line (GPS Track) aus den Punkten zum aktuelle Track erzeugen
         MakeLine(track.geometry_trackpoint) as geometry,
         -- SubSelect 1: Name des GPS Tracks
        ( SELECT sub_track.name
          FROM track sub_track
          WHERE track.fid=sub_track.fid ) as name,
         -- SubSelect 2: Beschreibung des GPS Tracks
        ( SELECT sub_track.description
          FROM track sub_track
          WHERE track.fid=sub_track.fid ) as description
  FROM 
  ( -- Einzelne Points (Streckenmesspunkte) nach GPS Track und 
    -- Position im GPS Track sortiert zusammenstellen
    SELECT track.fid, trackpoint.geometry_trackpoint
      FROM track, trackpoint, track_trackpoint
      WHERE track.fid=track_trackpoint.ref_fid_track
       AND trackpoint.fid=track_trackpoint.ref_fid_trackpoint
       ORDER BY track.fid, track_trackpoint.trackposition ) track
    -- Gruppierung nach Tracks -> Voraussetzung für MakeLine(...)   
  GROUP BY track.fid
  1. Ansatz Collect(…)
CREATE OR REPLACE VIEW v_gps_track (id, geometry, name, description) AS 
  SELECT track.fid as id, 
         -- Geometrie Line (GPS Track) aus den Punkten zum aktuelle Track erzeugen
         COLLECT(track.geometry_trackpoint) as geometry,
         -- SubSelect 1: Name des GPS Tracks
        ( SELECT sub_track.name
          FROM track sub_track
          WHERE track.fid=sub_track.fid ) as name,
         -- SubSelect 2: Beschreibung des GPS Tracks
        ( SELECT sub_track.description
          FROM track sub_track
          WHERE track.fid=sub_track.fid ) as description
  FROM 
  ( -- Einzelne Points (Streckenmesspunkte) nach GPS Track und 
    -- Position im GPS Track sortiert zusammenstellen
    SELECT track.fid, trackpoint.geometry_trackpoint
      FROM track, trackpoint, track_trackpoint
      WHERE track.fid=track_trackpoint.ref_fid_track
       AND trackpoint.fid=track_trackpoint.ref_fid_trackpoint
       ORDER BY track.fid, track_trackpoint.trackposition ) track
    -- Gruppierung nach Tracks -> Voraussetzung für Collect(...)   
  GROUP BY track.fid

Um die Performancefrage zu klären habe ich den View nacheinander mit den beiden SQL Statements erzeugt und jeweils dreimal ein

SELECT * FROM v_gps_track

aufgerufen.

Collect: 1708ms, 1705ms und 1803ms
MakeLine: 1506ms, 1602ms, 1601ms

Die Unterschiede sind also gering.

Gruß, Torsten