PostGIS - Calcule a distância progressiva entre pontos em um caminho GPX

8

Estou tentando criar um perfil de elevação usando apenas o PostGIS-PostgreSQL. Importei dados GPX no meu banco de dados PostGis, então agora tenho uma tabela cheia das coordenadas GPS da pista e o registro de data e hora de cada ponto GPS da pista. Agora eu gostaria de criar uma segunda tabela que contém, em uma única linha:

  1. o ID da faixa
  2. uma matriz de flutuadores representando a distância incremental do ponto inicial
  3. uma matriz de flutuadores representando o tempo incremental a partir do ponto de partida

É possível fazer isso em um único procedimento armazenado SQL?

Obrigado,

Andrea

Andrea Cremaschi
fonte

Respostas:

8

Aqui está um começo (não realmente testado ...) Primeiras duas suposições:

  • Eu acho que sua tabela de faixas é uma tabela espacial PostGIS, com uma coluna geom? (Caso contrário, você precisará executar SELECT AddGeometryColumn (...) para configurá-lo usando os valores Lon / Lat)
  • Quando você diz "distância incremental", suponho que você queira dizer distância acumulada?

Fiz duas tabelas de teste: trilhas para os pontos e acumulações para distâncias e tempos 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)

e

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

Agora, aqui está um rascunho aproximado de uma função que acumula distâncias e tempos e coloca os valores em matrizes na tabela de acumulação. Essa função é chamada com o 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;

Talvez isso ajude você a começar.

Cheers, Micha

Micha
fonte
É isso aí! Obrigado pela resposta, é exatamente isso que eu estava tentando realizar.
Andrea Cremaschi
1
Examinando a função uma segunda vez, vejo que o acum_d acima é a distância cartesiana entre um ponto na pista e o primeiro ponto. Não era isso que você queria. Você precisa da distância ao longo da pista . Então, adicionei uma variável "segmento" e alterei o cálculo de acum_d para refletir a distância acumulada usando cada segmento de faixa. Dar uma olhada.
Micha
Sim, na verdade foi isso que eu quis dizer com a distância "progressiva" .. Obrigado novamente!
Andrea Cremaschi