PostGIS - Hitung jarak progresif antara titik pada jalur GPX

8

Saya mencoba membangun profil elevasi menggunakan PostGIS-PostgreSQL saja. Saya telah mengimpor data GPX dalam database PostGis saya, jadi sekarang saya memiliki tabel yang penuh dengan koordinat GPS trek dan cap waktu setiap titik GPS tunggal trek. Sekarang saya ingin membuat tabel kedua yang berisi, dalam satu baris:

  1. id lagu
  2. array pelampung yang merepresentasikan jarak inkremental dari titik awal
  3. array pelampung yang mewakili waktu tambahan dari titik awal

Apakah mungkin untuk melakukannya dalam satu prosedur tersimpan SQL?

Terima kasih,

Andrea

Andrea Cremaschi
sumber

Jawaban:

8

Inilah awal (tidak benar-benar diuji ...) Dua asumsi pertama:

  • Saya kira tabel trek Anda adalah tabel spasial PostGIS, dengan kolom geom? (Jika tidak, Anda harus menjalankan SELECT AddGeometryColumn (...) untuk mengaturnya menggunakan nilai Lon / Lat)
  • Ketika Anda mengatakan "jarak incremental", saya berasumsi maksud Anda jarak akumulasi

Saya membuat dua tabel uji: trek untuk poin dan akumulasi untuk jarak dan waktu yang terakumulasi

geodata=# \d ms.tracks
                                        Table "ms.tracks"
    Column    |            Type             |                      Modifiers                      
--------------+-----------------------------+-----------------------------------------------------
 pk           | integer                     | not null default nextval('tracks_pk_seq'::regclass)
 trk_id       | integer                     | 
 lon          | double precision            | 
 lat          | double precision            | 
 geom         | geometry                    | 
 gps_timestmp | timestamp without time zone | 
Indexes:
    "tracks_pkey" PRIMARY KEY, btree (pk)
Check constraints:
    "enforce_dims_geom" CHECK (st_ndims(geom) = 2)
    "enforce_geotype_geom" CHECK (geometrytype(geom) = 'POINT'::text OR geom IS NULL)
    "enforce_srid_geom" CHECK (st_srid(geom) = 4326)

dan

geodata=# \d accum
              Table "ms.accum"
   Column   |        Type        | Modifiers 
------------+--------------------+-----------
 trk_id     | integer            | 
 accum_dist | double precision[] | 
 accum_time | double precision[] | 

Sekarang inilah konsep kasar dari fungsi yang mengakumulasi jarak dan waktu, dan menempatkan nilai ke dalam array di tabel akumulasi. Fungsi ini disebut dengan trk_id sebagai parameter.

CREATE OR REPLACE FUNCTION public.calculate_accumulated_track(IN t_id integer) RETURNS void AS
$BODY$
DECLARE
i integer;
-- first date/time in the track
dt1 timestamp;
-- the date/time of following track points
dt2 timestamp;
num_rows integer;
-- first_row will be the primary key of the 
-- first track point for the track id passed into the function
first_row integer := 1;
-- Accumulated distance and time, to be inserted into accum table
segment float :=0;
accum_t float;
accum_d float;

BEGIN
    -- Initialize a row in the accum table
    INSERT INTO accum VALUES (t_id, NULL, NULL);
    -- Get the primary key of the first row for this track id.
    SELECT pk INTO first_row FROM tracks WHERE trk_id=t_id ORDER BY pk LIMIT 1;
    SELECT count(*) INTO num_rows FROM tracks WHERE trk_id=t_id;
    SELECT gps_timestmp INTO dt1 FROM tracks WHERE trk_id=t_id ORDER BY gps_timestmp LIMIT 1;

    FOR i in 1..num_rows LOOP
        SELECT gps_timestmp INTO dt2 FROM tracks WHERE pk=i+first_row;
        accum_t := dt2 - dt1;
        IF pk==1 THEN
accum_d:=0;
ELSE
SELECT ST_Distance(t1.geom, t2.geom) INTO segment 
                FROM tracks t1, tracks t2
                WHERE t1.pk=i+first_row-1 AND t2.pk=i+first_row;
END IF;
accum_t := accum_d+segment;     


    -- Now UPDATE the accum table
     UPDATE accum SET accum_time[i]=accum_t WHERE trk_id=t_id;
     UPDATE accum SET accum_dist[i]=accum_d WHERE trk_id=t_id;
    END LOOP;

END;$BODY$
LANGUAGE plpgsql VOLATILE;
ALTER FUNCTION public.calculate_accumulated_track(IN integer) OWNER TO geodba;

Mungkin itu akan membantu Anda memulai.

Cheers, Micha

Micha
sumber
Itu dia! Terima kasih atas jawabannya, inilah tepatnya yang ingin saya capai.
Andrea Cremaschi
1
Melihat fungsi ini untuk kedua kalinya, saya melihat bahwa diakum di atas adalah jarak kartesian antara titik di trek dan titik pertama. Bukan itu yang Anda inginkan. Sebaliknya Anda membutuhkan jarak di sepanjang trek . Jadi saya menambahkan variabel "segmen" dan mengubah kalkulasi akumulasi_ untuk mencerminkan jarak terakumulasi menggunakan setiap segmen trek. Silahkan lihat.
Micha
Ya, sebenarnya itu yang saya maksud dengan jarak "progresif" .. Terima kasih lagi!
Andrea Cremaschi