Las secciones anteriores enuncian lo que un ráster comparte con las demás teselaciones. Las operaciones siguientes son propias del ráster: una celda de ráster lleva un valor donde una celda H3, QUADBIN o S2 lleva solo identidad, de modo que una trayectoria leída contra un ráster responde un tfloat en lugar de una celda temporal.
Un ráster es el mismo valor en todos los motores, y en DuckDB y en Spark se convierte además desde y hacia el ráster del anfitrión, el de la extensión de rásteres de DuckDB y el de Apache Sedona: “Los rásteres de los motores” enuncia lo que conserva cada conversión y cómo la escribe una consulta.
El operador de muestreo de ráster de MobilityDB lee una banda de ráster a lo largo de una trayectoria de punto móvil y devuelve un tfloat. Una posición fuera de la extensión del ráster o sobre un píxel nodata no lleva valor. Los operadores de muestreo son de valor doble sea cual sea el tipo de píxel de la banda, de modo que un tipo de píxel pertenece a la superficie de muestreo cuando todo valor que puede contener es exactamente representable en un número de doble precisión. Eso es lo que permite muestrear una banda de cualquier tipo en un único tfloat, y que una columna con teselas de varios tipos de píxel se lea con una sola consulta. Un tipo de píxel también se acepta con el nombre que le da el ráster de PostGIS, de modo que el tipo de banda que informa una llamada a ST_BandPixelType (8BUI, 16BSI, 32BF, …) se pasa a los constructores de teselas tal cual. El ráster de PostGIS no lleva flotantes de 16 bits ni enteros de 64 bits, así que float16, int64 y uint64 toman la grafía que da su gramática, 16BF, 64BSI y 64BUI. Sus tipos 1BB, 2BUI y 4BUI acotan un píxel a menos de un byte mientras que PostGIS almacena cada uno de ellos a un byte por píxel, de modo que tal banda ya son los bytes de una banda de 8 bits sin signo y los constructores la leen como uint8; la cota es lo único que añade el nombre, y una tesela no la lleva. El nombre que informa una tesela es el que la especificación RaQuet da al tipo.
Los tipos uint64 e int64 contienen valores fuera de ese dominio: una tesela de cualquiera de ellos se almacena y se vuelve a leer exactamente, mientras que muestrear un píxel cuyo valor ningún número de doble precisión nombra genera un error en lugar de responder con un valor vecino. Esto permite consultas como ¿qué perfil de elevación siguió cada vehículo? o ¿qué viajes entraron en una banda de umbral de temperatura?
Una tabla Raquet guarda la celda QUADBIN de una tesela en su columna block como un entero de 64 bits, junto a la fila de metadatos en block = 0, que no contiene ningún índice QUADBIN. Una consulta convierte las celdas de una trayectoria a bigint para leer esa columna, y una celda leída de ella a quadbin, comprobando la conversión que es un índice QUADBIN. El patrón de consulta típico une una trayectoria con una tabla Raquet en dos pasos:
-- Step 1: identify which tiles the trajectory overlaps SELECT getValues(tquadbin(traj, 8)); -- Step 2: sample each matching tile, a 256 x 256 float32 band without nodata SELECT rasterTileValueQuadbin(traj, band_1, 256, 256, block::quadbin, 'float32', 0, false) FROM elevation_raquet WHERE block IN (SELECT unnest(getValues(tquadbin(traj, 8)))::bigint);
Los operadores de restricción y predicado que cierran la sección componen rasterValue con las funciones estándar de restricción temporal y predicado de MobilityDB. Aceptan un argumento opcional band (por defecto 1) e invocan rasterValue exactamente una vez por invocación.
Una función de ráster toma el nombre de su homóloga del ráster de PostGIS sin el prefijo ST_, y los nombres y los valores por defecto de sus argumentos. Una sola signatura responde a cada operación, de modo que una forma de PostGIS que solo fija un argumento de otra se escribe mediante esa otra forma. Un nombre que el estándar SQL reserva toma el tipo como prefijo, de modo que ST_Value es rasterValue, y las funciones de Well-Known Binary toman los nombres que toma todo tipo de MobilityDB.
| Ráster de PostGIS | MobilityDB |
|---|---|
ST_Value | rasterValue |
ST_Clip | clip |
ST_Transform | transform |
ST_Rescale | rescale |
ST_Reclass | reclass |
ST_SummaryStats | summaryStats |
ST_DumpAsPolygons | dumpAsPolygons |
ST_NumBands, ST_Width, ST_Height, ST_SRID | numBands, width, height, SRID |
ST_UpperLeftX, ST_UpperLeftY, ST_ScaleX, ST_ScaleY, ST_SkewX, ST_SkewY | upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY |
ST_BandPixelType, ST_BandNoDataValue | bandPixelType, bandNoDataValue |
ST_MakeEmptyRaster, ST_AddBand, ST_SetValues | makeEmptyRaster, addBand, setValues |
ST_AsBinary, ST_AsHexWKB | asBinary, asHexWKB |
ST_RastFromWKB, ST_RastFromHexWKB | rasterFromBinary, rasterFromHexWKB |
asBinary y asHexWKB toman un orden de bytes donde PostGIS toma outasin, y sin él devuelven los bytes de ST_AsBinary y ST_AsHexWKB.
Lee una banda de ráster a lo largo de una trayectoria
rasterValue(tgeompoint,rast raster,band integer=1,exclude_nodata_value boolean=true, resample text='nearest') → tfloat rasterValue(tgeompoint,path text,band integer=1) → tfloat
Lee la banda band a lo largo de traj, tomando el valor del píxel en el que cae cada posición. Una trayectoria que no afirma nada entre sus instantes se lee en sus instantes y devuelve un tfloat de conjunto de instantes. Una trayectoria que se mueve entre ellos pasa por los píxeles intermedios, por lo que cada segmento se recorre píxel a píxel, y devuelve un tfloat escalonado que mantiene cada valor desde el instante en que el trayecto alcanza el píxel que lo contiene, incluido un píxel del que el trayecto solo corta una esquina. Con un límite superior exclusivo, un píxel que la trayectoria alcanza solo en su final, sin mantenerlo ningún tiempo, no aporta ningún valor al resultado, por lo que las lecturas de una trayectoria cortada en periodos semiabiertos sucesivos se fusionan en la lectura de la trayectoria completa. Una posición fuera del ráster o sobre un píxel sin datos no lleva valor y termina el tramo, por lo que un trayecto que sale y vuelve a entrar en el ráster devuelve una secuencia por visita, y NULL cuando nunca encuentra un píxel con datos. Una banda cuyos píxeles no se pueden leer, como una banda almacenada fuera de la base de datos en un archivo que no se puede abrir, provoca un error en lugar de leerse como una banda sin valores. La forma que recibe path lee un archivo ráster del servidor, en cualquier formato compatible con GDAL, mediante GDAL, allí donde PostGIS permite leer una banda ráster almacenada fuera de la base de datos: postgis.enable_outdb_rasters debe estar activado y postgis.gdal_enabled_drivers debe habilitar el controlador del archivo. Devuelve lo que la forma que recibe un raster devuelve sobre el mismo ráster.
exclude_nodata_value y resample son los de ST_Value de PostGIS: con el primero falso una posición sobre un píxel nodata conserva el valor nodata donde de otro modo se descarta, y el segundo lee el píxel bajo la posición con nearest o bilinear, nombrado sin distinguir mayúsculas de minúsculas. Un valor bilineal varía dentro de un píxel. A lo largo de un segmento de una trayectoria que se desplaza entre sus instantes es, sobre cada cuadrado de medio píxel que el segmento atraviesa, un polinomio de grado dos en el tiempo, de modo que una trayectoria leída con bilinear devuelve un tfloat lineal que contiene el valor en los instantes de la trayectoria, donde cruza los bordes de los píxeles y las líneas que pasan por sus centros, y en el extremo que alcanza cada uno de esos tramos, lineal entre ellos, como el producto de dos flotantes temporales contiene su extremo. Su mínimo y su máximo son los del valor, y es el valor mismo donde la trayectoria se desplaza a lo largo de un eje de la malla, sobre el cual el valor es lineal; en otro caso, entre los instantes que contiene, es la cuerda del valor. El valor salta a través de un borde de píxel donde un píxel leído allí contiene nodata, que toma el valor del píxel en el que cae la posición, y una nueva secuencia comienza entonces en el instante en que la trayectoria cruza el borde.
-- 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)@2001-01-01,
POINT(2.5 2.5)@2001-01-02, POINT(0.5 0.5)@2001-01-03]', r)::text FROM rast;
/* Interp=Step;[10@2001-01-01, 20@2001-01-01 06:00:00, 30@2001-01-01 18:00:00,
50@2001-01-02 06:00:00, 70@2001-01-02 18:00:00, 70@2001-01-03] */
-- A bilinear read reaching its maximum between two pixel centres
WITH rast AS (
SELECT ST_SetValues(ST_AddBand( ST_MakeEmptyRaster(2, 2, 0.0, 2.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], [20.0::float4, 10.0::float4]]) AS r )
SELECT round(rasterValue(tgeompoint 'SRID=4326;[POINT(0.5 1.5)@2001-01-01,
POINT(1.5 1.1)@2001-01-03]', r, 1, true, 'bilinear'), 6)::text FROM rast;
/* [10@2001-01-01, 15@2001-01-02, 16.125@2001-01-02 18:00:00, 16@2001-01-03] */
Aplicado a un conjunto de datos de trayectorias con un ráster de elevación del terreno:
-- 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;
Un ráster cargado como una tabla de teselas, como lo carga raster2pgsql -t, se lee a lo largo de una trayectoria fusionando las lecturas de sus teselas con merge. Una posición se encuentra en un píxel de una sola tesela, de modo que las lecturas de las teselas ocupan tiempos disjuntos, y su fusión responde la lectura del ráster que las teselas cubren, incluido un viaje que pasa de una tesela a la siguiente.
-- A 4x4 raster read along a trip whole, and as its four tiles of 2x2 pixels
WITH r AS (
SELECT ST_SetValues(ST_AddBand(ST_MakeEmptyRaster(4, 4, 0.0, 4.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, 100.0::float4, 110.0::float4, 120.0::float4],
[130.0::float4, 140.0::float4, 150.0::float4, 160.0::float4]]) AS rast ),
t AS (
SELECT tgeompoint 'SRID=4326;[POINT(0.5 3.5)@2001-01-01, POINT(3.5 0.5)@2001-01-02]'
AS trip )
SELECT merge(rasterValue(trip, tile)) = (SELECT rasterValue(trip, rast) FROM t, r)
FROM t, r, ST_Tile(rast, 2, 2) AS tile;
-- true
Devuelve el número de píxeles de una banda de un ráster que contienen cada valor
valueCount(rast raster,nband integer=1,exclude_nodata_value boolean=true, searchvalues float[]=NULL,roundto float=0) → setof (value float,count integer) valueCount(rast raster,nband integer,searchvalues float[],roundto float=0) → setof (value float,count integer) valueCount(rast raster,searchvalues float[],roundto float=0) → setof (value float,count integer) valueCount(rast raster,nband integer,exclude_nodata_value boolean,searchvalue float, roundto float=0) → integer valueCount(rast raster,nband integer,searchvalue float,roundto float=0) → integer valueCount(rast raster,searchvalue float,roundto float=0) → integer
El histograma de ST_ValueCount de PostGIS, con sus argumentos y valores por defecto: una fila por cada valor distinto de la banda, o una por cada valor buscado, que cuenta cero cuando ningún píxel lo contiene, y el número de píxeles que contienen un valor en las formas que toman un único valor buscado. Un valor se redondea al múltiplo más cercano de roundto antes de contarse cuando roundto es positivo. Una banda cuyos píxeles no tienen datos no devuelve ninguna fila cuando se excluyen los píxeles sin datos, y una banda que el ráster no tiene produce un error donde PostGIS devuelve NULL. Las formas de PostGIS que leen una columna ráster de una tabla consultan la base de datos, por lo que siguen siendo de PostGIS.
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, -9999.0::float8), 1, 1, 1,
ARRAY[[1.24, 1.26, -9999], [2, 2, 2], [3, 1.24, 2]]::double precision[][]) AS r )
SELECT round(value::numeric, 2), count
FROM rast, valueCount(r, 1, true, NULL::float[], 0.1) ORDER BY 1;
-- 1.20 | 2
-- 1.30 | 1
-- 2.00 | 4
-- 3.00 | 1
Devuelve la proporción de los píxeles de una banda de un ráster que contienen cada valor
valuePercent(rast raster,nband integer=1,exclude_nodata_value boolean=true, searchvalues float[]=NULL,roundto float=0) → setof (value float,percent float) valuePercent(rast raster,nband integer,searchvalues float[],roundto float=0) → setof (value float,percent float) valuePercent(rast raster,searchvalues float[],roundto float=0) → setof (value float,percent float) valuePercent(rast raster,nband integer,exclude_nodata_value boolean, searchvalue float,roundto float=0) → float valuePercent(rast raster,nband integer,searchvalue float,roundto float=0) → float valuePercent(rast raster,searchvalue float,roundto float=0) → float
La proporción de ST_ValuePercent de PostGIS, entre 0 y 1, de los píxeles que lee valueCount, con los mismos argumentos y formas. Cuando no se lee ningún píxel, la proporción de un valor buscado es cero dividido por cero, NaN, como para PostGIS.
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, -9999.0::float8), 1, 1, 1,
ARRAY[[1.24, 1.26, -9999], [2, 2, 2], [3, 1.24, 2]]::double precision[][]) AS r )
SELECT valuePercent(r, 2::float), valuePercent(r, 3::float) FROM rast;
-- 0.5 | 0.125
Devuelve verdadero si los rásteres están sobre la misma rejilla
sameAlignment(rast1 raster,rast2 raster) → boolean sameAlignment(raster) → boolean sameAlignment(raster) → boolean
La prueba de ST_SameAlignment de PostGIS: dos rásteres están alineados cuando tienen la misma escala y la misma inclinación y una esquina de píxel de uno cae sobre una esquina de píxel del otro, de modo que sus píxeles pueden combinarse uno a uno. El agregado responde si cada ráster de una columna está alineado con el primero, omitiendo un ráster NULL como setUnion omite un conjunto NULL, donde PostGIS responde NULL; sobre ningún ráster responde NULL. Rásteres de SRID distintos producen un error, donde PostGIS responde falso con un aviso.
WITH r AS (SELECT ST_MakeEmptyRaster(3, 3, 0.0, 3.0, 1.0, -1.0, 0.0, 0.0, 4326) AS base, ST_MakeEmptyRaster(3, 3, 1.0, 3.0, 1.0, -1.0, 0.0, 0.0, 4326) AS east1, ST_MakeEmptyRaster(3, 3, 0.5, 3.0, 1.0, -1.0, 0.0, 0.0, 4326) AS easthalf) SELECT sameAlignment(base, east1), sameAlignment(base, easthalf), (SELECT sameAlignment(x) FROM (VALUES (base), (east1), (easthalf)) t(x)) FROM r; -- t | f | f
Devuelve por qué dos rásteres no están sobre la misma rejilla
notSameAlignmentReason(rast1 raster,rast2 raster) → text
La razón de ST_NotSameAlignmentReason de PostGIS, en sus palabras: la primera propiedad en la que difieren las rejillas, o que los rásteres están alineados.
WITH r AS (SELECT ST_MakeEmptyRaster(3, 3, 0.0, 3.0, 1.0, -1.0, 0.0, 0.0, 4326) AS base, ST_MakeEmptyRaster(3, 3, 0.5, 3.0, 1.0, -1.0, 0.0, 0.0, 4326) AS easthalf, ST_MakeEmptyRaster(3, 3, 0.0, 3.0, 2.0, -1.0, 0.0, 0.0, 4326) AS scalex2) SELECT notSameAlignmentReason(base, easthalf), notSameAlignmentReason(base, scalex2) FROM r; -- The rasters (pixel corner coordinates) are not aligned | -- The rasters have different scales on the X axis
Devuelve la unión de los rásteres de una columna
rasterUnion(raster) → raster rasterUnion(raster,nband integer) → raster rasterUnion(raster,uniontype text) → raster rasterUnion(raster,nband integer,uniontype text) → raster
El agregado ST_Union de PostGIS sobre rásteres, nombrado como geoUnion nombra la unión de geometrías, ya que union es una palabra clave de SQL. El resultado cubre la unión de las extensiones de los rásteres, cada píxel la operación de píxeles de los píxeles que tienen un valor allí: LAST, por defecto, FIRST, MIN, MAX, COUNT, SUM, MEAN o RANGE, sin distinguir mayúsculas de minúsculas. Sin nband se unen todas las bandas, y una banda que le falta a un ráster se lee como nodata; con nband solo esa banda, que todo ráster debe tener. El tipo de píxel y el valor nodata son los de la banda leída primero, y un conteo es una banda de enteros sin signo de 32 bits sin valor nodata. Un ráster NULL se omite, y sobre ningún ráster el agregado devuelve NULL. El agregado se ejecuta en paralelo, combinando las uniones de los procesos, mientras que el de PostGIS no tiene función de combinación; LAST y FIRST dependen del orden de los rásteres, que un ORDER BY en el agregado fija. Rásteres con SRID distintos o sobre rejillas distintas producen un error, y también una operación de píxeles distinta de estas, que PostGIS lee como LAST.
WITH tiles AS (
SELECT 1 AS id, ST_AddBand(ST_MakeEmptyRaster(2, 2, 0.0, 2.0, 1.0, -1.0, 0.0, 0.0, 3857),
'32BF'::text, 1.0::float8, -9999.0::float8) AS r
UNION ALL
SELECT 2, ST_AddBand(ST_MakeEmptyRaster(2, 2, 1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 3857),
'32BF'::text, 3.0::float8, -9999.0::float8) )
SELECT ST_DumpValues(rasterUnion(r, 'MEAN' ORDER BY id), 1) FROM tiles;
-- {{1,1,NULL},{1,2,3},{NULL,3,3}}
Devuelve un ráster cuya banda contiene las clases a las que una expresión asigna sus valores
reclass(raster,nband integer,reclassexpr text,pixeltype text,nodataval float=NULL) → raster
La expresión sigue la gramática de ST_Reclass de PostGIS: una lista de asignaciones separadas por comas, cada una un rango de origen y un destino separados por dos puntos, siendo un rango un valor o dos separados por un guion. Un rango escrito sin corchetes incluye su extremo inferior y excluye el superior, mientras que ( excluye el extremo inferior y ] incluye el superior, de modo que 0-50 deja 50 sin asignar mientras que [50-100] lo toma. Un píxel que ningún rango toma contiene el valor nodata de la banda resultante, o cero cuando la banda no declara ninguno. Esa banda tiene el tipo de píxel pixeltype, con el nombre que le da PostGIS raster, como 8BUI, y no declara valor nodata cuando se omite nodataval. El ráster conserva su malla y sus demás bandas, de modo que las clases pueden leerse a lo largo de una trayectoria con rasterValue.
-- 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 ST_DumpValues(reclass(r, 1, '0-50:1, 51-100:2', '8BUI', 0), 1) AS plain,
ST_DumpValues(reclass(r, 1, '0-50:1, [50-100]:2', '8BUI', 0), 1) AS bracket
FROM rast;
-- {{1,1,1},{1,NULL,2},{2,2,2}} | {{1,1,1},{1,2,2},{2,2,2}}
-- Read the classes along a trajectory
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)@2001-01-01,
POINT(1.5 1.5)@2001-01-02, POINT(2.5 0.5)@2001-01-03}',
reclass(r, 1, '0-50:1, [50-100]:2', '8BUI', 0))::text FROM rast;
-- {1@2001-01-01, 2@2001-01-02, 2@2001-01-03}
Adición, resta, multiplicación y división de rásteres, píxel a píxel
{float,raster} {+, -, *, /} {float,raster} → raster
Un ráster tiene los operadores aritméticos de un número temporal, de modo que un ráster derivado se escribe como la expresión que es, como (nir - red) / (nir + red) o depth - 8.5, donde PostGIS lo escribe como la expresión de ST_MapAlgebra. Toda banda del resultado tiene el tipo de píxel 64BF, cualesquiera que sean los tipos de píxel de los operandos, de modo que un píxel contiene la aritmética tal como se calcula: una diferencia negativa de dos bandas sin signo, un producto más allá de su rango y una razón entre cero y uno se conservan en lugar de recortarse o truncarse, y reclass reduce el resultado donde se necesita un tipo de píxel menor. Dos rásteres se operan banda a banda sobre los píxeles que comparten, como dos números temporales sobre el tiempo que comparten: deben tener el mismo sistema de referencia, la misma malla y el mismo número de bandas, y dos rásteres que no comparten ningún píxel no tienen resultado. Un píxel sin datos en cualquiera de los operandos no tiene datos en el resultado, que toma el valor sin datos del primer operando que declara uno y no declara ninguno cuando ninguno lo hace, de modo que un resultado igual a cero es un valor. Una división por cero produce un error, sea el divisor un número o un píxel. Las funciones detrás de los operadores son rasterAdd, rasterSub, rasterMul y rasterDiv.
-- The normalized difference of two unsigned 16-bit bands
WITH bands AS (
SELECT
ST_SetValues(ST_AddBand(ST_MakeEmptyRaster(3, 3, 0.0, 3.0, 1.0, -1.0, 0.0, 0.0,
4326), '16BUI'::text, 0.0::float8, NULL::float8), 1, 1, 1,
ARRAY[[3000, 500, 2000], [4000, 1000, 6000], [100, 0, 65535]]
::double precision[][]) AS nir,
ST_SetValues(ST_AddBand(ST_MakeEmptyRaster(3, 3, 0.0, 3.0, 1.0, -1.0, 0.0, 0.0,
4326), '16BUI'::text, 0.0::float8, NULL::float8), 1, 1, 1,
ARRAY[[1000, 1500, 2000], [1000, 3000, 2000], [300, 1, 0]]
::double precision[][]) AS red )
SELECT ST_BandPixelType((nir - red) / (nir + red), 1),
ST_DumpValues((nir - red) / (nir + red), 1)
FROM bands;
-- 64BF | {{0.5,-0.5,0},{0.6,-0.5,0.5},{-0.5,-1,1}}
-- Read a derived raster along a trajectory: the depth under a vessel of draught 8.5
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 depth )
SELECT rasterValue(tgeompoint 'SRID=4326;[POINT(0.5 2.5)@2001-01-01,
POINT(2.5 2.5)@2001-01-02, POINT(0.5 0.5)@2001-01-03]', depth - 8.5)::text
FROM rast;
-- Interp=Step;[1.5@2001-01-01 00:00:00+00, 11.5@2001-01-01 06:00:00+00,
-- 21.5@2001-01-01 18:00:00+00, 41.5@2001-01-02 06:00:00+00,
-- 61.5@2001-01-02 18:00:00+00, 61.5@2001-01-03 00:00:00+00]
Devuelve la pendiente de una banda de un ráster, píxel a píxel
slope(rast raster,nband integer=1,pixeltype text='32BF',units text='DEGREES', scale float=1.0,interpolate_nodata boolean=false) → raster slope(rast raster,nband integer,customextent raster,pixeltype text='32BF', units text='DEGREES',scale float=1.0,interpolate_nodata boolean=false) → raster
La pendiente de ST_Slope de PostGIS, con sus argumentos y valores por defecto: los gradientes de cada píxel se leen de sus ocho vecinos, tomando un vecino sin datos o fuera del ráster el valor del píxel, y un píxel sin datos sigue sin datos. Las unidades son DEGREES, RADIANS o PERCENT, leídas por sus tres primeras letras sin distinguir mayúsculas, y otras unidades producen un error; PostGIS devuelve los radianes en grados. La escala es la razón entre las unidades verticales y las horizontales, como 111120 para elevaciones en metros sobre una malla en grados. Cuando interpolate_nodata es verdadero, un píxel sin datos toma primero la media de sus vecinos ponderada por el inverso de sus distancias, como la calcula ST_InvDistWeight4ma de PostGIS. El resultado toma la malla de customextent cuando se da.
-- A plane rising by 1 for each pixel to the east
WITH plane 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[[0, 1, 2], [0, 1, 2], [0, 1, 2]]::double precision[][]) AS r )
SELECT ST_Value(slope(r), 2, 2), ST_Value(slope(r, units => 'PERCENT'), 2, 2)
FROM plane;
-- 45 | 100
Devuelve el índice de rugosidad del terreno de una banda de un ráster, píxel a píxel
tri(rast raster,nband integer=1,pixeltype text='32BF',interpolate_nodata boolean=false) → raster tri(rast raster,nband integer,customextent raster,pixeltype text='32BF', interpolate_nodata boolean=false) → raster
El índice de ST_TRI de PostGIS, con sus argumentos y valores por defecto: la media de las diferencias absolutas entre un píxel y sus ocho vecinos, leídos como los lee slope.
WITH dem AS (
SELECT ST_SetValues(ST_AddBand(ST_MakeEmptyRaster(4, 4, 0.0, 4.0, 1.0, -1.0, 0.0, 0.0,
3857), '32BF'::text, 0.0::float8, -9999.0::float8), 1, 1, 1,
ARRAY[[10, 20, 30, 40], [15, 25, -9999, 45], [20, 30, 40, 50],
[25, 35, 45, 55]]::double precision[][]) AS r )
SELECT ST_DumpValues(tri(r), 1) FROM dem;
-- {{3.75,3.75,5,1.875},{5,7.5,NULL,3.75},{5,8.125,8.125,3.125},{2.5,5.625,5.625,3.75}}
Devuelve el índice de posición topográfica de una banda de un ráster, píxel a píxel
tpi(rast raster,nband integer=1,pixeltype text='32BF',interpolate_nodata boolean=false) → raster tpi(rast raster,nband integer,customextent raster,pixeltype text='32BF', interpolate_nodata boolean=false) → raster
El índice de ST_TPI de PostGIS, con sus argumentos y valores por defecto: el valor de un píxel menos la media de sus ocho vecinos, leídos como los lee slope.
WITH dem AS (
SELECT ST_SetValues(ST_AddBand(ST_MakeEmptyRaster(4, 4, 0.0, 4.0, 1.0, -1.0, 0.0, 0.0,
3857), '32BF'::text, 0.0::float8, -9999.0::float8), 1, 1, 1,
ARRAY[[10, 20, 30, 40], [15, 25, -9999, 45], [20, 30, 40, 50],
[25, 35, 45, 55]]::double precision[][]) AS r )
SELECT ST_DumpValues(tpi(r, interpolate_nodata => true), 1) FROM dem;
-- {{-3.75,-1.875,-1.875,1.25},{-3.75,0,0,3.75},{-3.75,0,0,3.75},{-1.25,1.875,1.875,3.75}}
Devuelve una estadística del vecindario de cada píxel de una banda de un ráster
mapAlgebra(rast raster,nband integer,stat text,pixeltype text=NULL, extenttype text='FIRST',customextent raster=NULL,distancex integer=0, distancey integer=0) → raster
Las estadísticas focales de ST_MapAlgebra de PostGIS con las funciones de retorno ST_Min4ma, ST_Max4ma, ST_Sum4ma, ST_Mean4ma, ST_Range4ma y ST_StdDev4ma, con sus argumentos y valores por defecto, la función de retorno nombrada por su estadística: MIN, MAX, SUM, MEAN, RANGE o STDDEV, sin distinguir mayúsculas de minúsculas, como ST_Union nombra sus operaciones. El vecindario de un píxel se extiende distancex píxeles al oeste y al este y distancey píxeles al norte y al sur; sus píxeles sin datos, y los que quedan fuera del ráster, se omiten. La suma de ningún píxel es 0, toda otra estadística de ningún píxel es sin datos, y la desviación estándar es la muestral. Como en PostGIS, un vecindario cuya distancia es cero solo a lo largo de un eje es el píxel solo. Un tipo de píxel dejado en NULL es el de la banda, y el resultado conserva el valor sin datos de la banda, o su valor mínimo cuando no indica ninguno. Todo tipo de extensión salvo CUSTOM es la extensión del ráster, y CUSTOM toma la grilla de customextent. Una estadística o un tipo de extensión fuera de estos produce un error, donde PostGIS lee un tipo de extensión desconocido como INTERSECTION.
WITH dem AS (
SELECT ST_SetValues(ST_AddBand(ST_MakeEmptyRaster(4, 4, 0.0, 4.0, 1.0, -1.0, 0.0, 0.0,
3857), '32BF'::text, 0.0::float8, -9999.0::float8), 1, 1, 1,
ARRAY[[10, 20, 30, 40], [15, 25, -9999, 45], [20, 30, 40, 50],
[25, 35, 45, 55]]::double precision[][]) AS r )
SELECT ST_DumpValues(mapAlgebra(r, 1, 'MEAN', '64BF', distancex => 1, distancey => 1), 1)
FROM dem;
-- {{17.5,20,32,38.333333333333336},{20,23.75,35,41},{25,29.375,40.625,47},
-- {27.5,32.5,42.5,47.5}}
Devuelve un ráster que conserva los píxeles de otro que una geometría cubre
clip(raster,geom geometry,crop boolean=true,touched boolean=false) → raster clip(raster,nband integer[],geom geometry,nodataval float[]=NULL,crop boolean=true, touched boolean=false) → raster
Cada banda se lee contra una máscara en la que se graba la geometría, tal como la lee ST_Clip de PostGIS: un píxel que la geometría no cubre devuelve el valor nodata de su banda, y el menor valor que admite su tipo de píxel cuando la banda no declara ninguno. Con crop el resultado conserva la extensión que comparten el ráster y la geometría, y en caso contrario la extensión del ráster. La geometría está en el sistema de referencia del ráster; una en otro sistema genera un error. Con nband el resultado conserva las bandas nombradas, todas cuando es NULL, nodataval declara el valor nodata de los píxeles que la geometría no cubre, uno para todas las bandas o uno por banda, y con touched se conserva un píxel que la geometría toca donde de otro modo solo se conserva uno cuyo centro cubre.
-- 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, -9999::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 ST_DumpValues(clip(r, geometry 'SRID=4326;POLYGON((0 1,2 1,2 3,0 3,0 1))'), 1)
AS cropped,
ST_DumpValues(clip(r, geometry 'SRID=4326;POLYGON((0 1,2 1,2 3,0 3,0 1))', false), 1)
AS kept_extent
FROM rast;
-- {{10,20},{40,50}} | {{10,20,NULL},{40,50,NULL},{NULL,NULL,NULL}}
Devuelve un ráster expresado en otro sistema de referencia espacial
transform(raster,srid integer,algorithm text='NearestNeighbour',maxerr float=0.125, scalex float=0,scaley float=0) → raster transform(raster,alignto raster,algorithm text='NearestNeighbour', maxerr float=0.125) → raster transformPipeline(raster,pipeline text,srid integer=0,is_forward boolean=true, algorithm text='NearestNeighbour',maxerr float=0.125,scalex float=0, scaley float=0) → raster
Cada banda se lleva al sistema de destino y se remuestrea sobre la malla que implica la reproyección, mediante la misma deformación de GDAL que ST_Transform de PostGIS, de modo que el resultado expresa la misma cobertura leída a través de otro sistema. El algoritmo es uno de NearestNeighbour, Bilinear, Cubic, CubicSpline, Lanczos, Max y Min, nombrado sin distinguir mayúsculas de minúsculas, y maxerr es el error en píxeles de entrada que la deformación puede cometer, 0 para un cálculo exacto. scalex y scaley declaran el tamaño de píxel del resultado, 0 dejando que la deformación lo derive, y alignto toma el sistema de referencia, el tamaño de píxel, el origen de la malla y la inclinación de otro ráster, de modo que el resultado queda sobre su malla.
La función transformPipeline lleva el ráster a través de una operación de coordenadas, expresada como una cadena PROJ, un WKT o un código de autoridad como urn:ogc:def:coordinateOperation:EPSG::16031, en lugar de la que GDAL deriva de los dos sistemas, y la lee como lo hace transformPipeline sobre una geometría: primero la longitud y en grados. El resultado expresa el sistema de referencia dado por srid, 0 por defecto. Por defecto la operación se aplica hacia adelante; poner is_forward a falso aplica su inversa. Los demás argumentos son los de transform, de modo que una operación que GDAL derivaría responde como transform al mismo sistema.
-- 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, -9999::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 SRID(transform(r, 3857)) AS srid, width(transform(r, 3857)) AS width,
height(transform(r, 3857)) AS height
FROM rast;
-- 3857 | 3 | 3
-- 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, -9999::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 SRID(transformPipeline(r, '+proj=utm +zone=31 +ellps=WGS84', 32631)) AS srid,
width(transformPipeline(r, '+proj=utm +zone=31 +ellps=WGS84', 32631)) AS width,
height(transformPipeline(r, '+proj=utm +zone=31 +ellps=WGS84', 32631)) AS height
FROM rast;
-- 32631 | 3 | 3
Devuelve un ráster remuestreado a otro tamaño de píxel
rescale(raster,scalex float,scaley float,algorithm text='NearestNeighbour', maxerr float=0.125) → raster
El resultado conserva el sistema de referencia y la esquina superior izquierda del ráster y expresa su cobertura sobre una malla del tamaño de píxel pedido, mediante la misma deformación de GDAL que ST_Rescale de PostGIS, de modo que una escala más gruesa lee menos píxeles sobre el mismo terreno. Las escalas están en las unidades del sistema de referencia del ráster, y el algoritmo y el error son los de transform.
-- 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, -9999::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 width(rescale(r, 0.5, -0.5)) AS width,
height(rescale(r, 0.5, -0.5)) AS height,
scaleX(rescale(r, 0.5, -0.5)) AS scalex
FROM rast;
-- 6 | 6 | 0.5
Devuelve las estadísticas de los píxeles de una banda de ráster
summaryStats(raster,nband integer=1,exclude_nodata_value boolean=true) → summarystats
La banda se lee una sola vez y devuelve el registro summarystats de PostGIS que devuelve ST_SummaryStats: el número de píxeles contados, y la suma, la media, la desviación estándar, el mínimo y el máximo de sus valores. Se leen todos los píxeles, por lo que la respuesta es exacta y no muestreada; los píxeles que la banda declara como nodata quedan fuera salvo que exclude_nodata_value sea falso, y una banda sin ningún píxel que contar devuelve un recuento de cero y ninguna estadística.
-- 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, -9999::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 (summaryStats(r)).* FROM rast;
-- 9 | 450 | 50 | 25.81988897471611 | 10 | 90
Devuelve las estadísticas de los píxeles de una banda sobre los rásteres de una columna
summaryStatsAgg(raster,nband integer,exclude_nodata_value boolean) → summarystats summaryStatsAgg(raster,exclude_nodata_value boolean) → summarystats
El agregado ST_SummaryStatsAgg de PostGIS, que devuelve el registro summarystats que summaryStats devuelve para un ráster sobre todos los píxeles de la banda de los rásteres, la banda 1 cuando se omite nband. Se leen todos los píxeles, como en summaryStats, por lo que las formas no toman ningún porcentaje de muestreo y la desviación estándar es la de todos los píxeles y no la de una muestra. Un ráster NULL se omite, sobre ningún ráster el agregado devuelve NULL, y unos rásteres sin ningún píxel que contar devuelven un recuento de cero y ninguna estadística. El agregado se ejecuta en paralelo, combinando las estadísticas de los procesos, mientras que el de PostGIS no tiene función de combinación. Una banda que un ráster no tiene genera un error, mientras que PostGIS omite el ráster.
WITH tiles AS (
SELECT ST_AddBand(ST_MakeEmptyRaster(2, 2, 0.0, 2.0, 1.0, -1.0, 0.0, 0.0, 3857),
'32BF'::text, 1.0::float8, -9999.0::float8) AS r
UNION ALL
SELECT ST_AddBand(ST_MakeEmptyRaster(2, 2, 1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 3857),
'32BF'::text, 3.0::float8, -9999.0::float8) )
SELECT (summaryStatsAgg(r, 1, true)).* FROM tiles;
-- 8 | 16 | 2 | 1 | 1 | 3
Devuelve el número de píxeles, la suma, la media, la desviación estándar, el mínimo o el máximo de las estadísticas de una banda de ráster
summarystatsCount(summarystats) → bigint summarystatsSum(summarystats) → float summarystatsMean(summarystats) → float summarystatsStddev(summarystats) → float summarystatsMin(summarystats) → float summarystatsMax(summarystats) → float
Cada función lee un campo del registro summarystats que devuelven summaryStats y summaryStatsAgg, la forma en que todo motor lo lee (Capítulo 18, Escritura de consultas portables), junto a la lectura de un campo por su nombre, (summaryStats(r)).mean, que PostgreSQL conserva. Sobre unas estadísticas que no cuentan ningún píxel el recuento es 0 y las demás funciones devuelven NULL.
-- 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, -9999::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 summarystatsCount(summaryStats(r)), summarystatsMean(summaryStats(r)),
summarystatsStddev(summaryStats(r)) FROM rast;
-- 9 | 50 | 25.81988897471611
Devuelve los polígonos de una banda de ráster, uno por cada grupo de píxeles que comparten un valor
dumpAsPolygons(raster,band integer=1,exclude_nodata_value boolean=true) → {geomval}
Una banda declara un valor por píxel, y esta función declara la misma banda como las regiones que cubren esos valores, devolviendo los registros geomval de PostGIS que devuelve ST_DumpAsPolygons. Cada polígono lleva el sistema de referencia del ráster, donde ST_DumpAsPolygons no declara ninguno, de modo que puede compararse con las trayectorias a lo largo de las cuales se lee la cobertura. Los píxeles que la banda declara como nodata quedan fuera salvo que exclude_nodata_value sea falso, una banda cuyos píxeles son todos nodata no cubre nada y no devuelve ninguna fila, y una banda que el ráster no tiene genera un error.
-- Classify a 3x3 synthetic elevation raster, then read each class as a region
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, -9999::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 val, ST_AsText(geom)
FROM rast, dumpAsPolygons(reclass(r, 1, '0-50:1, [50-100]:2', '8BUI', 0))
ORDER BY val;
-- 1 | POLYGON((0 3,0 1,1 1,1 2,3 2,3 3,0 3))
-- 2 | POLYGON((1 2,1 1,0 1,0 0,3 0,3 2,1 2))
Devuelve los píxeles de una banda de ráster como puntos
pixelAsPoints(rast raster,band integer=1,exclude_nodata_value boolean=true) → setof (geom geometry,val float,x integer,y integer)
Los puntos de ST_PixelAsPoints de PostGIS: para cada píxel, fila por fila, su esquina superior izquierda en el sistema de referencia del ráster, su valor y su columna y su fila, empezando en 1. Los píxeles que la banda declara como nodata quedan fuera salvo que exclude_nodata_value sea falso, en cuyo caso conservan el valor que la banda tiene para ellos, y una banda que no declara valor nodata no deja ninguno fuera. Una banda que el ráster no tiene genera un error, donde PostGIS no devuelve ninguna fila.
WITH rast AS (
SELECT ST_SetValues(ST_AddBand(ST_MakeEmptyRaster(3, 2, 10.0, 20.0, 2.0, -1.0, 0.0, 0.0,
3857), '32BF'::text, 0.0::float8, -9999.0::float8), 1, 1, 1,
ARRAY[[1.5, -9999, 3], [4, 5, 6]]::double precision[][]) AS r )
SELECT ST_AsText(geom), val, x, y FROM rast, pixelAsPoints(r) LIMIT 2;
-- POINT(10 20) | 1.5 | 1 | 1
-- POINT(14 20) | 3 | 3 | 1
Devuelve los valores de las bandas de un ráster como arreglos
dumpValues(rast raster,nband integer[]=NULL,exclude_nodata_value boolean=true) → setof (nband integer,valarray float[]) dumpValues(rast raster,nband integer,exclude_nodata_value boolean=true) → float[]
Los valores de ST_DumpValues de PostGIS: un arreglo por banda, una fila del arreglo por fila del ráster, en el orden de las bandas dadas en nband, todas las bandas cuando es NULL; la forma con una banda devuelve solo su arreglo. Un píxel que la banda declara como nodata es NULL salvo que exclude_nodata_value sea falso, en cuyo caso es el valor que la banda tiene para él. Una banda que el ráster no tiene, o un número de banda NULL, genera un error, donde PostGIS no devuelve ninguna fila o lo omite.
WITH rast AS (
SELECT ST_SetValues(ST_AddBand(ST_MakeEmptyRaster(3, 2, 10.0, 20.0, 2.0, -1.0, 0.0, 0.0,
3857), '32BF'::text, 0.0::float8, -9999.0::float8), 1, 1, 1,
ARRAY[[1.5, -9999, 3], [4, 5, 6]]::double precision[][]) AS r )
SELECT dumpValues(r, 1), dumpValues(r, 1, false) FROM rast;
-- {{1.5,NULL,3},{4,5,6}} | {{1.5,-9999,3},{4,5,6}}
Muestrea una tesela ráster raquet a lo largo de una trayectoria
rasterTileValue(tgeompoint,rast raquet) → tfloat
Lee la tesela a lo largo de traj (SRID 4326) como rasterValue lee un ráster, devolviendo los valores de píxel como un tfloat. Es el equivalente tipado de rasterTileValueQuadbin: las dimensiones, la celda QUADBIN, el tipo de píxel y el tratamiento de nodata se toman del valor raquet en lugar de argumentos separados. Devuelve NULL cuando el trayecto nunca encuentra un píxel de la tesela con datos.
-- Sample pre-packaged raquet tiles along ship trajectories SELECT t.tripid, rasterTileValue(t.trip, r.tile) FROM trips t JOIN elevation_tiles r ON r.quadbin IN (SELECT unnest(getValues(tquadbin(t.trip, 8))));
Muestrea un arreglo de teselas ráster raquet a lo largo de una trayectoria
rasterTileValue(tgeompoint,rast raquet[]) → tfloat
Lee cada tesela de rast a lo largo de traj (SRID 4326) y devuelve los valores de píxel como un único tfloat. Una trayectoria que sale de una tesela queda cubierta por varias, y cada una responde la parte del trayecto que está sobre ella. Las teselas de un mismo nivel de zoom particionan el plano, de modo que responden tiempos disjuntos. Las teselas de niveles de zoom distintos se solapan, y cuando dos de ellas responden el mismo tiempo se conserva el valor de la tesela de mayor zoom, que es la que tiene la resolución más fina. Devuelve NULL cuando el trayecto nunca encuentra un píxel de una tesela con datos.
-- Sample a trajectory across every tile it crosses, in one value SELECT t.tripid, rasterTileValue(t.trip, array_agg(r.tile)) FROM trips t JOIN elevation_tiles r ON r.quadbin IN (SELECT unnest(getValues(tquadbin(t.trip, 8)))) GROUP BY t.tripid, t.trip;
Muestrea un chip ráster de Raquet a lo largo de una trayectoria usando una celda QUADBIN para la georreferenciación
rasterTileValueQuadbin(tgeompoint,pixels bytea,width integer,height integer, quadbin,pixtype text,nodata float,has_nodata boolean) → tfloat
Lee un arreglo de píxeles de banda única en orden de fila mayor a lo largo de traj (SRID 4326), como rasterValue lee un ráster. La georreferenciación de la tesela (rectángulo delimitador, mapeo de píxel a coordenadas) se deriva únicamente de quadbin mediante la transformada de tesela deslizante Web-Mercator. El argumento pixtype debe ser uno de uint8, int8, uint16, int16, uint32, int32, uint64, int64, float16, float32 o float64. Cuando has_nodata es verdadero, un píxel igual a nodata no lleva valor. Devuelve NULL cuando el trayecto nunca encuentra un píxel con datos.
-- Sample the 256 x 256 float32 elevation tiles of a Raquet table, stating no -- nodata value, along every ship trajectory SELECT t.tripid, rasterTileValueQuadbin(t.trip, r.band_1, 256, 256, r.block::quadbin, 'float32', 0, false) FROM trips t JOIN elevation_raquet r ON r.block IN (SELECT unnest(getValues(tquadbin(t.trip, 8)))::bigint); -- Average sea-surface temperature per trajectory SELECT t.tripid, avgValue(rasterTileValueQuadbin(t.trip, r.band_1, 256, 256, r.block::quadbin, 'int16', -9999, true)) AS mean_sst FROM trips t JOIN sst_raquet r ON r.block IN (SELECT unnest(getValues(tquadbin(t.trip, 6)))::bigint);
Devuelve la parte de una trayectoria donde el valor ráster que lee cae dentro de un rango de flotante
atRasterValue(tgeompoint,rast raster,vspan floatspan,band integer=1) → tgeompoint atRasterValue(tgeompoint,path text,vspan floatspan,band integer=1) → tgeompoint
Lee rasterValue a lo largo de traj y devuelve la sub-trayectoria restringida a los tiempos en que el valor del píxel está dentro de vspan. Devuelve NULL cuando ningún tiempo satisface la condición. La forma que recibe path lee un archivo ráster del servidor, como lo hace la forma correspondiente de rasterValue.
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 asText(atRasterValue(tgeompoint 'SRID=4326;
[POINT(0.5 2.5)@2001-01-01, POINT(1.5 1.5)@2001-01-02, POINT(0.5 0.5)@2001-01-03]', r,
floatspan '[40, 90]')) FROM rast;
/* {[POINT(1 2)@2001-01-01 12:00:00, POINT(1.5 1.5)@2001-01-02,
POINT(0.5 0.5)@2001-01-03]} */
Devuelve la parte de una trayectoria donde el valor ráster que lee cae fuera de un rango de flotante
minusRasterValue(tgeompoint,rast raster,vspan floatspan,band integer=1) → tgeompoint minusRasterValue(tgeompoint,path text,vspan floatspan,band integer=1) → tgeompoint
El complemento de atRasterValue: devuelve la sub-trayectoria restringida a los tiempos en que el valor del píxel está fuera de vspan. Devuelve NULL cuando el valor del píxel está dentro de vspan en todo momento. La forma que recibe path lee un archivo ráster del servidor, como lo hace la forma correspondiente de rasterValue.
-- Keep only the instant whose raster value (10) is below 40 SELECT asText(minusRasterValue(traj, elev_raster, floatspan '[40, 9999]')) FROM trips, elevation_raster;
Devuelve verdadero si la trayectoria alguna vez lee un valor de píxel ráster dentro de un rango de flotante
eRasterValue(tgeompoint,rast raster,vspan floatspan,band integer=1) → boolean eRasterValue(tgeompoint,path text,vspan floatspan,band integer=1) → boolean
Devuelve true cuando traj lee alguna vez un valor de píxel dentro de vspan, false en caso contrario. Devuelve NULL únicamente cuando la entrada es NULL. La forma que recibe path lee un archivo ráster del servidor, como lo hace la forma correspondiente de rasterValue.
-- Trips that ever crossed terrain above 200 m SELECT tripid FROM trips, elevation_raster WHERE eRasterValue(trip, elev_raster, floatspan '[200, 9999]');
Devuelve verdadero si cada valor de píxel que la trayectoria lee sobre el ráster está dentro de un rango de flotante
aRasterValue(tgeompoint,rast raster,vspan floatspan,band integer=1) → boolean aRasterValue(tgeompoint,path text,vspan floatspan,band integer=1) → boolean
Devuelve true cuando cada valor de píxel que traj lee sobre el ráster está dentro de vspan, false cuando al menos uno no lo está. Devuelve NULL únicamente cuando la entrada es NULL. La forma que recibe path lee un archivo ráster del servidor, como lo hace la forma correspondiente de rasterValue.
-- Trips that stayed entirely below 100 m elevation SELECT tripid FROM trips, elevation_raster WHERE aRasterValue(trip, elev_raster, floatspan '[0, 100]');
Para usar los operadores descritos aquí, MobilityDB debe ser compilado con -DQUADBIN=ON y -DRASTER=ON, ya que una tesela Raquet se identifica por una celda quadbin. En tal compilación, el archivo mobilitydb.control generado declara requires = 'postgis, postgis_raster', por lo que un único CASCADE crea la pila completa:
CREATE EXTENSION mobilitydb CASCADE; -- NOTICE: installing required extension "postgis" -- NOTICE: installing required extension "postgis_raster"
El ráster de PostGIS forma parte del paquete estándar postgresql- en Debian/Ubuntu; no se requiere ningún paquete adicional. Pase N-postgis-3-DQUADBIN=ON y -DRASTER=ON a CMake:
cmake -DQUADBIN=ON -DRASTER=ON .. make -j$(nproc) sudo make install
Las compilaciones de CI, entre ellas .github/workflows/pgversion.yml, pasan -DALL=ON, que incluye el ráster junto con las demás familias opcionales.