PostGIS: calcule la distancia progresiva entre puntos en una ruta GPX


8

Estoy tratando de construir un perfil de elevación usando PostGIS-PostgreSQL solamente. He importado datos GPX en mi base de datos PostGis, por lo que ahora tengo una tabla llena de las coordenadas GPS de la pista y la marca de tiempo de cada punto GPS de la pista. Ahora me gustaría construir una segunda tabla que contenga, en una sola fila:

  1. la identificación de la pista
  2. Un conjunto de flotadores que representan la distancia incremental desde el punto de partida
  3. Una matriz de flotadores que representan el tiempo incremental desde el punto de partida

¿Es posible hacerlo en un solo procedimiento almacenado de SQL?

Gracias,

Andrea

Respuestas:


8

Aquí hay un comienzo (realmente no probado ...) Primeros dos supuestos:

  • ¿Supongo que su tabla de pistas es una tabla espacial PostGIS, con una columna geom? (Si no, tendrá que ejecutar SELECT AddGeometryColumn (...) para configurarlo utilizando los valores Lon / Lat)
  • Cuando dices "distancia incremental", ¿supongo que te refieres a la distancia acumulada?

Hice dos tablas de prueba: pistas para los puntos y acumulación para las distancias y tiempos acumulados.

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)

y

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

Ahora, aquí hay un borrador de una función que acumula distancias y tiempos, y pone los valores en matrices en la tabla de acumulación. Esta función se llama con trk_id como parámetro.

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;

Tal vez eso te ayude a comenzar.

Saludos, Micha


¡Eso es! Gracias por la respuesta, esto es exactamente lo que estaba tratando de lograr.
Andrea Cremaschi

1
Al mirar la función por segunda vez, veo que la acumulación de arriba es la distancia cartesiana entre un punto en la pista y el primer punto. Eso no es lo que querías. Más bien necesitas la distancia a lo largo de la pista . Así que agregué un "segmento" variable y cambié el cálculo de acumulo_d para reflejar la distancia acumulada usando cada segmento de pista. Echar un vistazo.
Micha

Sí, de hecho a eso me refería con distancia "progresiva" ... ¡Gracias de nuevo!
Andrea Cremaschi
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.