Table of Contents
The PostGIS raster extension stores gridded coverage data (elevation, temperature, satellite imagery, …) in the raster type. Each raster has one or more bands; a band holds a 2D array of pixel values, a spatial extent, a pixel size, and an optional nodata sentinel value.
MobilityDB's raster sampling operator evaluates a raster band at the instants of a moving-point trajectory and returns a tfloat. Instants whose position falls outside the raster extent or on a nodata pixel are silently dropped. This enables queries such as what elevation profile did each vehicle follow? or which trips entered a temperature threshold band?
To use the operators described here, MobilityDB must be built with -DRASTER=ON. On such a build the generated mobilitydb.control declares requires = 'postgis, postgis_raster', so a single CASCADE creates the full stack:
CREATE EXTENSION mobilitydb CASCADE; -- NOTICE: installing required extension "postgis" -- NOTICE: installing required extension "postgis_raster"
Sample a raster band at each instant of a trajectory
rasterValue(tgeompoint,raster,band integer DEFAULT 1) → tfloat
Evaluates pixel band at every instant of traj using bilinear-nearest sampling (ST_Value with resample=false). Returns an instant-set tfloat whose values are rounded to four decimal places. Returns NULL when no instant intersects the raster.
-- Build a 3x3 synthetic elevation raster (SRID 4326, 1 degree pixels)
WITH rast AS (
SELECT ST_SetValues(ST_AddBand(
ST_MakeEmptyRaster(3, 3, 0.0, 3.0, 1.0, -1.0, 0.0, 0.0, 4326), 32BF'::text,
'0.0::float8, NULL::float8), 1, 1, 1,
ARRAY[[10.0::float4, 20.0::float4, 30.0::float4],
[40.0::float4, 50.0::float4, 60.0::float4],
[70.0::float4, 80.0::float4, 90.0::float4]]) AS r
)
SELECT rasterValue(tgeompoint 'SRID=4326;[POINT(0.5 2.5)@2000-01-01,
POINT(2.5 2.5)@2000-01-02, POINT(0.5 0.5)@2000-01-03]', r)::text
FROM rast;
-- {10@2000-01-01, 30@2000-01-02, 70@2000-01-03}
Applied to a trajectory dataset with a terrain elevation raster:
-- Elevation profile per trip (requires a loaded elevation raster) SELECT tripid, rasterValue(trip, elev) AS elevation FROM trips, elevation_raster; -- Average elevation per trip SELECT tripid, avgValue(rasterValue(trip, elev)) AS mean_elev FROM trips, elevation_raster; -- Trips that crossed terrain above 200 m SELECT tripid FROM trips, elevation_raster WHERE atSpan(rasterValue(trip, elev), floatspan '[200, 9999]') IS NOT NULL;