A continuación, especificamos con el símbolo
que la función admite puntos 3D y con el símbolo
que la función está disponible para geografías.
Obtener la representación de texto conocido (Well-Known Text o WKT)
asText({tpoint,tpoint[],geo[]}): {text,text[]}
SELECT asText(tgeompoint 'SRID=4326;[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-02)'); -- "[POINT Z (0 0 0)@2012-01-01 00:00:00+00, POINT Z (1 1 1)@2012-01-02 00:00:00+00)" SELECT asText(ARRAY[geometry 'Point(0 0)', 'Point(1 1)']); -- "{"POINT(0 0)","POINT(1 1)"}"
Obtener la representación extendida de texto conocido (Extended Well-Known Text o EWKT)
asEWKT({tpoint,tpoint[],geo[]}): {text,text[]}
SELECT asEWKT(tgeompoint 'SRID=4326;[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-02)'); -- "SRID=4326;[POINT Z (0 0 0)@2012-01-01 00:00:00+00, POINT Z (1 1 1)@2012-01-02 00:00:00+00)" SELECT asEWKT(ARRAY[geometry 'SRID=5676;Point(0 0)', 'SRID=5676;Point(1 1)']); -- "{"SRID=5676;POINT(0 0)","SRID=5676;POINT(1 1)"}"
Obtener la representación JSON de característica móviles (Moving Features)
asMFJSON(tpoint,maxdecdigits integer=15,options integer=0): bytea
El último argumento options
puede usarse para agregar BBOX y/o CRS en la salida MFJSON:
0: significa que no hay opción (valor por defecto)
1: MFJSON BBOX
2: MFJSON Short CRS (e.g EPSG:4326)
4: MFJSON Long CRS (e.g urn:ogc:def:crs:EPSG::4326)
SELECT asMFJSON(tgeompoint 'Point(1 2)@2019-01-01 18:00:00.15+02'); -- "{"type":"MovingPoint","coordinates":[1,2],"datetimes":"2019-01-01T17:00:00.15+01", "interpolations":["Discrete"]}" SELECT asMFJSON(tgeompoint 'SRID=4326; Point(50.813810 4.384260)@2019-01-01 18:00:00.15+02', 2, 3); -- "{"type":"MovingPoint","crs":{"type":"name","properties":{"name":"EPSG:4326"}}, "stBoundedBy":{"bbox":[50.81,4.38,50.81,4.38], "period":{"begin":"2019-01-01 17:00:00.15+01","end":"2019-01-01 17:00:00.15+01"}}, "coordinates":[50.81,4.38],"datetimes":"2019-01-01T17:00:00.15+01", "interpolations":["Discrete"]}"
Obtener la representación binaria conocida (Well-Known Binary o WKB)
asBinary(tpoint): bytea
asBinary(tpoint,endian text): bytea
El resultado se codifica utilizando la codificación little-endian (NDR) o big-endian (XDR). Si no se especifica ninguna codificación, se utiliza la codificación de la máquina.
SELECT asBinary(tgeompoint 'Point(1 2 3)@2012-01-01'); -- "\x0191000000000000f03f0000000000000040000000000000084000fce0136a580100"
Obtener la representación extendida binaria conocida (Extended Well-Known Binary o EWKB)
asEWKB(tpoint): bytea
asEWKB(tpoint,endian text): bytea
El resultado se codifica utilizando la codificación little-endian (NDR) o big-endian (XDR). Si no se especifica ninguna codificación, se utiliza la codificación de la máquina.
SELECT asEWKB(tgeogpoint 'SRID=7844;Point(1 2 3)@2012-01-01'); -- "\x01f1a41e0000000000000000f03f0000000000000040000000000000084000fce0136a580100"
Obtener la representación hexadecimal extendida binaria conocida (Extended Well-Known Binary o EWKB) en formato texto
asHexEWKB(tpoint): text
asHexEWKB(tpoint,endian text): text
El resultado se codifica utilizando la codificación little-endian (NDR) o big-endian (XDR). Si no se especifica ninguna codificación, se utiliza NDR.
SELECT asHexEWKB(tgeompoint 'SRID=3812;Point(1 2 3)@2012-01-01'); -- "01D1E40E0000000000000000F03F0000000000000040000000000000084000FCE0136A580100"
Entrar un punto temporal geométrico en una representación de texto conocido (Well-Known Text o WKT)
tgeompointFromText(text): tgeompoint
SELECT asEWKT(tgeompointFromText(text '[POINT(1 2)@2000-01-01, POINT(3 4)@2000-01-02]')); -- "[POINT(1 2)@2000-01-01, POINT(3 4)@2000-01-02]"
Entrar un punto temporal geográfico en una representación de texto conocido (Well-Known Text o WKT)
tgeogpointFromText(text): tgeogpoint
SELECT asEWKT(tgeogpointFromText(text '[POINT(1 2)@2000-01-01, POINT(3 4)@2000-01-02]')); -- "SRID=4326;[POINT(1 2)@2000-01-01, POINT(3 4)@2000-01-02]"
Entrar un punto temporal geométrico en una representación extendida de texto conocido (Extended Well-Known Text o EWKT)
tgeompointFromEWKT(text): tgeompoint
SELECT asEWKT(tgeompointFromEWKT(text 'SRID=3812;[POINT(1 2)@2000-01-01, POINT(3 4)@2000-01-02]')); -- "SRID=3812;[POINT(1 2)@2000-01-01 00:00:00+01, POINT(3 4)@2000-01-02 00:00:00+01]"
Entrar un punto temporal geográfico en una representación extendida de texto conocido (Extended Well-Known Text o EWKT)
tgeogpointFromEWKT(text): tgeogpoint
SELECT asEWKT(tgeogpointFromEWKT(text 'SRID=7844;[POINT(1 2)@2000-01-01, POINT(3 4)@2000-01-02]')); -- "SRID=7844;[POINT(1 2)@2000-01-01, POINT(3 4)@2000-01-02]"
Entrar un punto temporal geométrico en una representación JSON de características móviles (Moving Features)
tgeompointFromMFJSON(text): tgeompoint
SELECT asEWKT(tgeompointFromMFJSON(text '{"type":"MovingPoint","crs":{"type":"name", "properties":{"name":"EPSG:4326"}},"coordinates":[50.81,4.38], "datetimes":"2019-01-01T17:00:00.15+01","interpolations":["Discrete"]}')); -- "SRID=4326;POINT(50.81 4.38)@2019-01-01 17:00:00.15+01"
Entrar un punto temporal geográfico en una representación JSON de características móviles (Moving Features)
tgeogpointFromMFJSON(text): tgeogpoint
SELECT asEWKT(tgeogpointFromMFJSON(text '{"type":"MovingPoint","crs":{"type":"name", "properties":{"name":"EPSG:4326"}},"coordinates":[50.81,4.38], "datetimes":"2019-01-01T17:00:00.15+01","interpolations":["Discrete"]}')); -- "SRID=4326;POINT(50.81 4.38)@2019-01-01 17:00:00.15+01"
Entrar un punto temporal geométrico en una representación binaria conocida (WKB)
tgeompointFromBinary(bytea): tgeompoint
SELECT asEWKT(tgeompointFromBinary( '\x0181000000000000f03f0000000000000040005c6c29ffffffff')); -- "POINT(1 2)@2000-01-01"
Entrar un punto temporal geográfico en una representación binaria conocida (WKB)
tgeogpointFromBinary(bytea): tgeogpoint
SELECT asEWKT(tgeompointFromBinary( '\x01b1000000000000f03f000000000000f03f000000000000f03f005c6c29ffffffff')); -- "SRID=4326;POINT Z (1 1 1)@2000-01-01"
Entrar un punto temporal geométrico en una representación extendida binaria conocida (EWKB)
tgeompointFromEWKB(bytea): tgeompoint
SELECT asEWKT(tgeompointFromEWKB( '\x01c1e40e0000000000000000f03f0000000000000040005c6c29ffffffff')); -- "SRID=3812;POINT(1 2)@2000-01-01"
Entrar un punto temporal geográfico en una representación extendida binaria conocida (EWKB)
tgeogpointFromEWKB(bytea): tgeogpoint
SELECT asEWKT(tgeogpointFromEWKB( '\x01f1a41e0000000000000000f03f000000000000f03f000000000000f03f005c6c29ffffffff')); -- "SRID=7844;POINT Z (1 1 1)@2000-01-01"
Entrar un punto temporal geométrico en una representación hexadecimal extendida binaria conocida (HexEWKB)
tgeompointFromHexEWKB(text): tgeompoint
SELECT asEWKT(tgeompointFromHexEWKB( '01C1E40E0000000000000000F03F0000000000000040005C6C29FFFFFFFF')); -- "SRID=3812;POINT(1 2)@2000-01-01"
Entrar un punto temporal geográfico en una representación hexadecimal extendida binaria conocida (HexEWKB)
tgeogpointFromHexEWKB(text): tgeogpoint
SELECT asEWKT(tgeogpointFromHexEWKB( '01F1A41E0000000000000000F03F000000000000F03F000000000000F03F005C6C29FFFFFFFF')); -- "SRID=7844;POINT Z (1 1 1)@2000-01-01"
Obtener el identificador de referencia espacial
SRID(tpoint): integer
SELECT SRID(tgeompoint 'Point(0 0)@2012-01-01'); -- 0
Establecer el identificador de referencia espacial
setSRID(tpoint): tpoint
SELECT asEWKT(setSRID(tgeompoint '[Point(0 0)@2012-01-01, Point(1 1)@2012-01-02)', 4326)); -- "SRID=4326;[POINT(0 0)@2012-01-01 00:00:00+00, POINT(1 1)@2012-01-02 00:00:00+00)"
Transformar a una referencia espacial diferente
transform(tpoint,integer): tpoint
SELECT asEWKT(transform(tgeompoint 'SRID=4326;Point(4.35 50.85)@2012-01-01', 3812)); -- "SRID=3812;POINT(648679.018035303 671067.055638114)@2012-01-01 00:00:00+00"
Obtener los valores de las coordenadas X como un número flotante temporal
getX(tpoint): tfloat
SELECT getX(tgeompoint '{Point(1 2)@2000-01-01, Point(3 4)@2000-01-02, Point(5 6)@2000-01-03}'); -- "{1@2000-01-01, 3@2000-01-02, 5@2000-01-03}" SELECT getX(tgeogpoint 'Interp=Stepwise;[Point(1 2 3)@2000-01-01, Point(4 5 6)@2000-01-02, Point(7 8 9)@2000-01-03]'); -- "Interp=Stepwise;[1@2000-01-01, 4@2000-01-02, 7@2000-01-03]"
Obtener los valores de las coordenadas Y como un número flotante temporal
getY(tpoint): tfloat
SELECT getY(tgeompoint '{Point(1 2)@2000-01-01, Point(3 4)@2000-01-02, Point(5 6)@2000-01-03}'); -- "{2@2000-01-01, 4@2000-01-02, 6@2000-01-03}" SELECT getY(tgeogpoint 'Interp=Stepwise;[Point(1 2 3)@2000-01-01, Point(4 5 6)@2000-01-02, Point(7 8 9)@2000-01-03]'); -- "Interp=Stepwise;[2@2000-01-01, 5@2000-01-02, 8@2000-01-03]"
Obtener los valores de las coordenadas Z como un número flotante temporal
getZ(tpoint): tfloat
SELECT getZ(tgeompoint '{Point(1 2)@2000-01-01, Point(3 4)@2000-01-02, Point(5 6)@2000-01-03}'); -- The temporal point do not have Z dimension SELECT getZ(tgeogpoint 'Interp=Stepwise;[Point(1 2 3)@2000-01-01, Point(4 5 6)@2000-01-02, Point(7 8 9)@2000-01-03]'); -- "Interp=Stepwise;[3@2000-01-01, 6@2000-01-02, 9@2000-01-03]"
Devuelve verdadero si el punto temporal no se auto-intersecta espacialmente
isSimple(tpoint): boolean
Nótese que un punto temporal de conjunto de secuencias es simple si cada una de las secuencias que lo componen es simple.
SELECT isSimple(tgeompoint '[Point(0 0)@2000-01-01, Point(1 1)@2000-01-02, Point(0 0)@2000-01-03]'); -- false SELECT isSimple(tgeompoint '[Point(0 0 0)@2000-01-01, Point(1 1 1)@2000-01-02, Point(2 0 2)@2000-01-03, Point(0 0 0)@2000-01-04]'); -- true SELECT isSimple(tgeompoint '{[Point(0 0 0)@2000-01-01, Point(1 1 1)@2000-01-02], [Point(1 1 1)@2000-01-03, Point(0 0 0)@2000-01-04]}'); -- true
Obtener la longitud atravesada por el punto temporal
length(tpoint): float
SELECT length(tgeompoint '[Point(0 0 0)@2000-01-01, Point(1 1 1)@2000-01-02]'); -- 1.73205080756888 SELECT length(tgeompoint '[Point(0 0 0)@2000-01-01, Point(1 1 1)@2000-01-02, Point(0 0 0)@2000-01-03]'); -- 3.46410161513775 SELECT length(tgeompoint 'Interp=Stepwise;[Point(0 0 0)@2000-01-01, Point(1 1 1)@2000-01-02, Point(0 0 0)@2000-01-03]'); -- 0
Obtener la longitud acumulada atravesada por el punto temporal
cumulativeLength(tpoint): tfloat_seq
SELECT round(cumulativeLength(tgeompoint '{[Point(0 0)@2000-01-01, Point(1 1)@2000-01-02, Point(1 0)@2000-01-03], [Point(1 0)@2000-01-04, Point(0 0)@2000-01-05]}'), 6); -- {[0@2000-01-01, 1.414214@2000-01-02, 2.414214@2000-01-03], [2.414214@2000-01-04, 3.414214@2000-01-05]} SELECT cumulativeLength(tgeompoint 'Interp=Stepwise;[Point(0 0 0)@2000-01-01, Point(1 1 1)@2000-01-02, Point(0 0 0)@2000-01-03]'); -- Interp=Stepwise;[0@2000-01-01, 0@2000-01-03]
Obtener la velocidad del punto temporal en unidades por segundo
speed(tpoint): tfloat_seqset
El punto temporal debe tener interpolación linear
SELECT speed(tgeompoint '{[Point(0 0)@2000-01-01, Point(1 1)@2000-01-02, Point(1 0)@2000-01-03], [Point(1 0)@2000-01-04, Point(0 0)@2000-01-05]}') * 3600 * 24; -- "Interp=Stepwise;{[1.4142135623731@2000-01-01, 1@2000-01-02, 1@2000-01-03], [1@2000-01-04, 1@2000-01-05]}" SELECT speed(tgeompoint 'Interp=Stepwise;[Point(0 0)@2000-01-01, Point(1 1)@2000-01-02, Point(1 0)@2000-01-03]'); -- ERROR: The temporal value must have linear interpolation
Obtener el centroide ponderado en el tiempo
twCentroid(tgeompoint): point
SELECT ST_AsText(twCentroid(tgeompoint '{[Point(0 0 0)@2012-01-01, Point(0 1 1)@2012-01-02, Point(0 1 1)@2012-01-03, Point(0 0 0)@2012-01-04)}')); -- "POINT Z (0 0.666666666666667 0.666666666666667)"
Obtener el acimut temporal
azimuth(tpoint): tfloat
SELECT degrees(azimuth(tgeompoint '[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-02, Point(1 1 1)@2012-01-03, Point(0 0 0)@2012-01-04)')); -- "Interp=Stepwise;{[45@2012-01-01, 45@2012-01-02], [225@2012-01-03, 225@2012-01-04)}"
Obtener el rumbo temporal
bearing({tpoint, point}, {tpoint, point}): tfloat
SELECT degrees(bearing(tgeompoint '[Point(1 1)@2012-01-01, Point(3 3)@2012-01-03]', geometry 'Point(2 2)')); -- [45@2012-01-01, 0@2012-01-02, 225@2012-01-03] SELECT round(degrees(bearing(tgeompoint '[Point(0 0)@2012-01-01, Point(2 0)@2012-01-03]', tgeompoint '[Point(2 1)@2012-01-01, Point(0 1)@2012-01-03]')), 3); -- [63.435@2012-01-01, 0@2012-01-02, 296.565@2012-01-03] SELECT round(degrees(bearing(tgeompoint '[Point(2 1)@2012-01-01, Point(0 1)@2012-01-03]', tgeompoint '[Point(0 0)@2012-01-01, Point(2 0)@2012-01-03]')), 3); -- [243.435@2012-01-01, 116.565@2012-01-03]
Tenga en cuenta que esta función actualmente no acepta dos puntos geográficos temporales.
Redondear los valores de las coordenadas a un número de decimales
setPrecision(tpoint,integer): tpoint
SELECT asText(setPrecision(tgeompoint '{Point(1.12345 1.12345 1.12345)@2000-01-01, Point(2 2 2)@2000-01-02, Point(1.12345 1.12345 1.12345)@2000-01-03}', 2)); -- "{POINT Z (1.12 1.12 1.12)@2000-01-01, POINT Z (2 2 2)@2000-01-02, POINT Z (1.12 1.12 1.12)@2000-01-03}" SELECT asText(setPrecision(tgeogpoint 'Point(1.12345 1.12345)@2000-01-01', 2)); -- "POINT(1.12 1.12)@2000-01-01"
Devuelve una matriz de fragmentos del punto temporal que son simples
makeSimple(tpoint): tgeompoint[]
SELECT asText(makeSimple(tgeompoint '[Point(0 0)@2000-01-01, Point(1 1)@2000-01-02, Point(0 0)@2000-01-03]')); -- {"[POINT(0 0)@2000-01-01, POINT(1 1)@2000-01-02)", "[POINT(1 1)@2000-01-02, POINT(0 0)@2000-01-03]"} SELECT asText(makeSimple(tgeompoint '[Point(0 0 0)@2000-01-01, Point(1 1 1)@2000-01-02, Point(2 0 2)@2000-01-03, Point(0 0 0)@2000-01-04]')); -- {"[POINT Z (0 0 0)@2000-01-01, POINT Z (1 1 1)@2000-01-02, POINT Z (2 0 2)@2000-01-03, POINT Z (0 0 0)@2000-01-04]"} SELECT asText(makeSimple(tgeompoint '[Point(0 0)@2000-01-01, Point(1 1)@2000-01-02, Point(0 1)@2000-01-03, Point(1 0)@2000-01-04]')); -- {"[POINT(0 0)@2000-01-01, POINT(1 1)@2000-01-02, POINT(0 1)@2000-01-03)", "[POINT(0 1)@2000-01-03, POINT(1 0)@2000-01-04]"} SELECT asText(makeSimple(tgeompoint '{[Point(0 0 0)@2000-01-01, Point(1 1 1)@2000-01-02], [Point(1 1 1)@2000-01-03, Point(0 0 0)@2000-01-04]}')); -- {"{[POINT Z (0 0 0)@2000-01-01, POINT Z (1 1 1)@2000-01-02], [POINT Z (1 1 1)@2000-01-03, POINT Z (0 0 0)@2000-01-04]}"}
Simplificar un punto temporal usando una generalización del algoritmo de Douglas-Peucker
simplify(tpoint,distance float): tpoint
simplify(tpoint,distance float,speed float): tpoint
La primera versión elimina los puntos cuya distancia es menor que la distancia pasada como segundo argumento, que se especifica en las unidades del sistema de coordenadas. La segunda versión elimina los puntos cuya distancia es menor que la distancia pasada como segundo argumento siempre que la diferencia de velocidad entre el punto y el punto correspondiente en la versión simplificada sea menor que la velocidad pasada como tercer argumento, que se especifica en unidades por segundo. Observe que la simplificación se aplica sólo a secuencias temporales o conjuntos de secuencias con interpolación lineal. En todos los demás casos, se devuelve una copia del punto temporal dado.
-- Solo distancia especificada SELECT ST_AsText(trajectory(simplify(tgeompoint '[Point(0 4)@2000-01-01, Point(1 1)@2000-01-02, Point(2 3)@2000-01-03, Point(3 1)@2000-01-04, Point(4 3)@2000-01-05, Point(5 0)@2000-01-06, Point(6 4)@2000-01-07]', 1.5))); -- "LINESTRING(0 4,1 1,4 3,5 0,6 4)" SELECT ST_AsText(trajectory(simplify(tgeompoint '[Point(0 4)@2000-01-01, Point(1 1)@2000-01-02, Point(2 3)@2000-01-03, Point(3 1)@2000-01-04, Point(4 3)@2000-01-05, Point(5 0)@2000-01-06, Point(6 4)@2000-01-07]', 2))); -- "LINESTRING(0 4,5 0,6 4)" SELECT ST_AsText(trajectory(simplify(tgeompoint '[Point(0 4)@2000-01-01, Point(1 1)@2000-01-02, Point(2 3)@2000-01-03, Point(3 1)@2000-01-04, Point(4 3)@2000-01-05, Point(5 0)@2000-01-06, Point(6 4)@2000-01-07]', 4))); -- "LINESTRING(0 4,6 4)" -- Solo diferencia de velocidad especificada SELECT round(speed(tgeompoint '[Point(0 4)@2000-01-01, Point(1 1)@2000-01-02, Point(2 3)@2000-01-03, Point(3 1)@2000-01-04, Point(4 3)@2000-01-05, Point(5 0)@2000-01-06, Point(6 4)@2000-01-07]') * 1e5, 2); -- "Interp=Stepwise;[3.66@2000-01-01, 2.59@2000-01-02, 3.66@2000-01-05, 4.77@2000-01-06, 4.77@2000-01-07]" -- Se especifican tanto la distancia como la diferencia de velocidad SELECT ST_AsText(trajectory(simplify(tgeompoint '[Point(0 4)@2000-01-01, Point(1 1)@2000-01-02, Point(2 3)@2000-01-03, Point(3 1)@2000-01-04, Point(4 3)@2000-01-05, Point(5 0)@2000-01-06, Point(6 4)@2000-01-07]', 4, 1 / 1e5))); -- "LINESTRING(0 4,1 1,2 3,3 1,4 3,5 0,6 4)" SELECT ST_AsText(trajectory(simplify(tgeompoint '[Point(0 4)@2000-01-01, Point(1 1)@2000-01-02, Point(2 3)@2000-01-03, Point(3 1)@2000-01-04, Point(4 3)@2000-01-05, Point(5 0)@2000-01-06, Point(6 4)@2000-01-07]', 4, 2 / 1e5))); -- "LINESTRING(0 4,1 1,5 0,6 4)" SELECT ST_AsText(trajectory(simplify(tgeompoint '[Point(0 4)@2000-01-01, Point(1 1)@2000-01-02, Point(2 3)@2000-01-03, Point(3 1)@2000-01-04, Point(4 3)@2000-01-05, Point(5 0)@2000-01-06, Point(6 4)@2000-01-07]', 4, 3 / 1e5))); -- "LINESTRING(0 4,6 4)"
Un uso típico de la función simplify
es reducir el tamaño de un conjunto de datos, en particular con fines de visualización.
Construir una geometría/geografía con medida M a partir de un punto temporal y un número flotante temporal
geoMeasure(tpoint,tfloat,segmentize=false): geo
El último argumento segmentize
establece si el valor resultado ya sea es un Linestring M
o un MultiLinestring M
donde cada componente es un segmento de dos puntos.
SELECT st_astext(geoMeasure(tgeompoint '{Point(1 1 1)@2000-01-01, Point(2 2 2)@2000-01-02}', '{5@2000-01-01, 5@2000-01-02}')); -- "MULTIPOINT ZM (1 1 1 5,2 2 2 5)" SELECT st_astext(geoMeasure(tgeogpoint '{[Point(1 1)@2000-01-01, Point(2 2)@2000-01-02], [Point(1 1)@2000-01-03, Point(1 1)@2000-01-04]}', '{[5@2000-01-01, 5@2000-01-02],[7@2000-01-03, 7@2000-01-04]}')); -- "GEOMETRYCOLLECTION M (LINESTRING M (1 1 5,2 2 5),POINT M (1 1 7))" SELECT st_astext(geoMeasure(tgeompoint '[Point(1 1)@2000-01-01, Point(2 2)@2000-01-02, Point(1 1)@2000-01-03]', '[5@2000-01-01, 7@2000-01-02, 5@2000-01-03]', true)); -- "MULTILINESTRING M ((1 1 5,2 2 5),(2 2 7,1 1 7))"
Una visualización típica de los datos de movilidad es mostrar en un mapa la trayectoria del objeto móvil utilizando diferentes colores según la velocidad. La Figura 5.1 muestra el resultado de la consulta a continuación usando una rampa de color en QGIS.
WITH Temp(t) AS ( SELECT tgeompoint '[Point(0 0)@2012-01-01, Point(1 1)@2012-01-05, Point(2 0)@2012-01-08, Point(3 1)@2012-01-10, Point(4 0)@2012-01-11]' ) SELECT ST_AsText(geoMeasure(t, round(speed(t) * 3600 * 24, 2), true)) FROM Temp; -- "MULTILINESTRING M ((0 0 0.35,1 1 0.35),(1 1 0.47,2 0 0.47),(2 0 0.71,3 1 0.71), (3 1 1.41,4 0 1.41))"
La siguiente expresión se usa en QGIS para lograr esto. La función scale_linear
transforma el valor M de cada segmento componente al rango [0, 1]. Este valor luego se pasa a la función ramp_color
.
ramp_color( 'RdYlBu', scale_linear( m(start_point(geometry_n($geometry,@geometry_part_num))), 0, 2, 0, 1) )
Transformar un punto geométrico temporal en el espacio de coordenadas de un Mapbox Vector Tile. El resultado es un par compuesto de un valor geometry
y una matriz de valores de marca de tiempo asociados codificados como época de Unix
asMVTGeom(tpoint,bounds,extent=4096,buffer=256,clip=TRUE): geom_times
Los parámetros son los siguientes:
tpoint
es el punto temporal para transformar
bounds
es un stbox
que define los límites geométricos del contenido del mosaico sin búfer
extent
es la extensión del mosaico en el espacio de coordenadas del mosaico
buffer
es la distancia del búfer en el espacio de coordenadas de mosaico
clip
es un booleano que determina si las geometrías resultantes y las marcas de tiempo deben recortarse o no
SELECT ST_AsText((mvt).geom), (mvt).times FROM (SELECT asMVTGeom(tgeompoint '[Point(0 0)@2000-01-01, Point(100 100)@2000-01-02]', stbox 'STBOX((40,40),(60,60))') AS mvt ) AS t; -- LINESTRING(-256 4352,4352 -256) | {946714680,946734120} SELECT ST_AsText((mvt).geom), (mvt).times FROM (SELECT asMVTGeom(tgeompoint '[Point(0 0)@2000-01-01, Point(100 100)@2000-01-02]', stbox 'STBOX((40,40),(60,60))', clip:=false) AS mvt ) AS t; -- LINESTRING(-8192 12288,12288 -8192) | {946681200,946767600}
Obtener la distancia más pequeña que haya existido
{geo,tpoint} |=| {geo,tpoint}: float
SELECT tgeompoint '[Point(0 0)@2012-01-02, Point(1 1)@2012-01-04, Point(0 0)@2012-01-06)' |=| geometry 'Linestring(2 2,2 1,3 1)'; -- 1 SELECT tgeompoint '[Point(0 0)@2012-01-01, Point(1 1)@2012-01-03, Point(0 0)@2012-01-05)' |=| tgeompoint '[Point(2 0)@2012-01-02, Point(1 1)@2012-01-04, Point(2 2)@2012-01-06)'; -- 0.5 SELECT tgeompoint '[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-03, Point(0 0 0)@2012-01-05)' |=| tgeompoint '[Point(2 0 0)@2012-01-02, Point(1 1 1)@2012-01-04, Point(2 2 2)@2012-01-06)'; -- 0.5 SELECT tgeompoint 'Interp=Stepwise;(Point(1 1)@2000-01-01, Point(3 1)@2000-01-03]' |=| geometry 'Linestring(1 3,2 2,3 3)'; -- 1.4142135623731
El operador |=|
se puede utilizar para realizar una búsqueda de vecino más cercano utilizando un índice GiST (ver la Sección 5.7). Esta función corresponde a la función ST_DistanceCPA
proporcionada por PostGIS, aunque este última requiere que ambos argumentos sean una trayectoria.
SELECT ST_DistanceCPA( tgeompoint '[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-03, Point(0 0 0)@2012-01-05)'::geometry, tgeompoint '[Point(2 0 0)@2012-01-02, Point(1 1 1)@2012-01-04, Point(2 2 2)@2012-01-06)'::geometry); -- 0.5
Obtener el instante del primer punto temporal en el que los dos argumentos están a la distancia más cercana
nearestApproachInstant({geo,tpoint},{geo,tpoint}): tpoint
La función sólo devuelve el primer instante que encuentre si hay más de uno. El instante resultante puede tener un límite exclusivo.
SELECT asText(NearestApproachInstant(tgeompoint '(Point(1 1)@2000-01-01, Point(3 1)@2000-01-03]', geometry 'Linestring(1 3,2 2,3 3)')); -- "POINT(2 1)@2000-01-02" SELECT asText(NearestApproachInstant(tgeompoint 'Interp=Stepwise;(Point(1 1)@2000-01-01, Point(3 1)@2000-01-03]', geometry 'Linestring(1 3,2 2,3 3)')); -- "POINT(1 1)@2000-01-01" SELECT asText(NearestApproachInstant(tgeompoint '(Point(1 1)@2000-01-01, Point(2 2)@2000-01-03]', tgeompoint '(Point(1 1)@2000-01-01, Point(4 1)@2000-01-03]')); -- "POINT(1 1)@2000-01-01" SELECT asText(nearestApproachInstant(tgeompoint '[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-03, Point(0 0 0)@2012-01-05)', tgeompoint '[Point(2 0 0)@2012-01-02, Point(1 1 1)@2012-01-04, Point(2 2 2)@2012-01-06)')); -- "POINT Z (0.75 0.75 0.75)@2012-01-03 12:00:00+00"
La función nearestApproachInstant
generaliza the la función PostGIS ST_ClosestPointOfApproach
. Primero, la última función requiere que ambos argumentos sean trayectorias. Segundo, la función nearestApproachInstant
devuelve tanto el punto como la marca de tiempo del punto de aproximación más cercano, mientras que la función PostGIS sólo proporciona la marca de tiempo como se muestra a continuación.
SELECT to_timestamp(ST_ClosestPointOfApproach( tgeompoint '[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-03, Point(0 0 0)@2012-01-05)'::geometry, tgeompoint '[Point(2 0 0)@2012-01-02, Point(1 1 1)@2012-01-04, Point(2 2 2)@2012-01-06)'::geometry)); -- "2012-01-03 12:00:00+00"
Obtener la línea que conecta el punto de aproximación más cercano
shortestLine({geo,tpoint},{geo,tpoint}): geo
La función sólo devolverá la primera línea que encuentre si hay más de una.
SELECT ST_AsText(shortestLine(tgeompoint '(Point(1 1)@2000-01-01, Point(3 1)@2000-01-03]', geometry 'Linestring(1 3,2 2,3 3)')); -- "LINESTRING(2 1,2 2)" SELECT ST_AsText(shortestLine(tgeompoint 'Interp=Stepwise;(Point(1 1)@2000-01-01, Point(3 1)@2000-01-03]', geometry 'Linestring(1 3,2 2,3 3)')); -- "LINESTRING(1 1,2 2)" SELECT ST_AsText(shortestLine( tgeompoint '[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-03, Point(0 0 0)@2012-01-05)', tgeompoint '[Point(2 0 0)@2012-01-02, Point(1 1 1)@2012-01-04, Point(2 2 2)@2012-01-06)')); -- "LINESTRING Z (0.75 0.75 0.75,1.25 0.75 0.75)"
La función shortestLine
se puede utilizar para obtener el resultado proporcionado por la función PostGIS ST_CPAWithin
cuando ambos argumentos son trayectorias como se muestra a continuación.
SELECT ST_Length(shortestLine( tgeompoint '[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-03, Point(0 0 0)@2012-01-05)', tgeompoint '[Point(2 0 0)@2012-01-02, Point(1 1 1)@2012-01-04, Point(2 2 2)@2012-01-06)')) <= 0.5; -- true SELECT ST_CPAWithin( tgeompoint '[Point(0 0 0)@2012-01-01, Point(1 1 1)@2012-01-03, Point(0 0 0)@2012-01-05)'::geometry, tgeompoint '[Point(2 0 0)@2012-01-02, Point(1 1 1)@2012-01-04, Point(2 2 2)@2012-01-06)'::geometry, 0.5); -- true
El operador de distancia temporal, denotado <->
, calcula la distancia en cada instante de la intersección de las extensiones temporales de sus argumentos y da como resultado un número flotante temporal. Calcular la distancia temporal es útil en muchas aplicaciones de movilidad. Por ejemplo, un grupo en movimiento (también conocido como convoy o bandada) se define como un conjunto de objetos que se mueven cerca unos de otros durante un intervalo de tiempo prolongado. Esto requiere calcular la distancia temporal entre dos objetos en movimiento.
El operador de distancia temporal acepta una geometría/geografía restringida a un punto o un punto temporal como argumentos. Observe que los tipos temporales sólo consideran la interpolación lineal entre valores, mientras que la distancia es una raíz de una función cuadrática. Por lo tanto, el operador de distancia temporal proporciona una aproximación lineal del valor de distancia real para los puntos de secuencia temporal. En este caso, los argumentos se sincronizan en la dimensión de tiempo y para cada uno de los segmentos de línea que componen los argumentos, se calcula la distancia espacial entre el punto inicial, el punto final y el punto de aproximación más cercano, como se muestra en los ejemplos a continuación.
Obtener la distancia temporal
{point,tpoint} <-> {point,tpoint}: tfloat
SELECT tgeompoint '[Point(0 0)@2012-01-01, Point(1 1)@2012-01-03)' <-> geometry 'Point(0 1)'; -- "[1@2012-01-01, 0.707106781186548@2012-01-02, 1@2012-01-03)" SELECT tgeompoint '[Point(0 0)@2012-01-01, Point(1 1)@2012-01-03)' <-> tgeompoint '[Point(0 1)@2012-01-01, Point(1 0)@2012-01-03)'; -- "[1@2012-01-01, 0@2012-01-02, 1@2012-01-03)" SELECT tgeompoint '[Point(0 1)@2012-01-01, Point(0 0)@2012-01-03)' <-> tgeompoint '[Point(0 0)@2012-01-01, Point(1 0)@2012-01-03)'; -- "[1@2012-01-01, 0.707106781186548@2012-01-02, 1@2012-01-03)" SELECT tgeompoint '[Point(0 0)@2012-01-01, Point(1 1)@2012-01-02)' <-> tgeompoint '[Point(0 1)@2012-01-01, Point(1 2)@2012-01-02)'; -- "[1@2012-01-01,1@2012-01-02)"
Las relaciones topológicas como ST_Intersects
y las relaciones de distancia como ST_DWithin
pueden ser generalizadas a los puntos temporales. Los argumentos de estas funciones generalizadas son un punto temporal y un tipo base (es decir, un geometry
o un geography
) o dos puntos temporales. Además, ambos argumentos deben ser del mismo tipo base, es decir, estas funciones no permiten merzclar un punto de geometría temporal (o una geometría) y un punto de geografía temporal (o una geografía).
Hay dos versiones de las relaciones espaciales:
Las relaciones possibles aplican la función topológica o de distancia tradicional a la unión de todos los valores tomados por el punto temporal (que es un geometry
o geography
) y resulta en un boolean
. Ejemplos son las funciones intersects
y dwithin
.
Las relaciones temporales se definen con la semántica temporal, es decir, la función topológica o de distancia tradicional se calcula en cada instante y da como resultado un tbool
. Ejemplos son las funciones tintersects
y tdwithin
.
La semántica de las relaciones posibles varía según la relación y el tipo de argumentos. Por ejemplo, la siguiente consulta
SELECT intersects(geometry 'Polygon((0 0,0 1,1 1,1 0,0 0))', tgeompoint '[Point(0 1)@2012-01-01, Point(1 1)@2012-01-03)');
comprueba si el punto temporal se cruzó alguna vez con la geometría, ya que la consulta es conceptualmente equivalente a la siguiente
SELECT ST_Intersects(geometry 'Polygon((0 0,0 1,1 1,1 0,0 0))', geometry 'Linestring(0 1,1 1)');
donde la segunda geometría se obtiene aplicando la función trajectory
al punto temporal. Por otro lado, la consulta
SELECT contains(geometry 'Polygon((0 0,0 1,1 1,1 0,0 0))', tgeompoint '[Point(0 1)@2012-01-01, Point(1 1)@2012-01-03)');
comprueba si la geometría siempre contiene el punto temporal. Finalmente, la siguiente consulta
SELECT intersects(tgeompoint '[Point(0 1)@2012-01-01, Point(1 0)@2012-01-03)', tgeompoint '[Point(0 0)@2012-01-01, Point(1 1)@2012-01-03)');
comprueba si los puntos temporales pueden cruzarse en el espacio independientemente del tiempo, ya que la consulta anterior es conceptualmente equivalente a la siguiente
SELECT ST_Intersects('Linestring(0 1,1 0)', 'Linestring(0 0,1 1)');
Las relaciones posibles se utilizan normalmente en combinación con un índice espacio-temporal al calcular las relaciones temporales. Por ejemplo, la siguiente consulta
SELECT T.TripId, R.RegionId, tintersects(T.Trip, R.Geom) FROM Trips T, Regions R WHERE intersects(T.Trip, R.Geom)
que verifica si un viaje T
(que es un punto temporal) se cruza con una región R
(que es una geometría) beneficiará de un índice espacio-temporal en la columna T.Trip
dado que la función intersects
realiza automáticamente la comparación del cuadro delimitador T.Trip && R.Geom
. Esto se explica más adelante en este documento.
No todas las relaciones espaciales disponibles en PostGIS tienen una generalización significativa para los puntos temporales. Se define una versión generalizada de las siguientes relaciones para los puntos geométricos temporales: intersects
, disjoint
, dwithin
, contains
, y touches
, mientras que para los puntos geográficos temporales solo se definen las tres primeras. Además, no todas las combinaciones de parámetros son significativas para una función generalizada dada. Por ejemplo, mientras que tcontains(geometry,tpoint)
es significativo, tcontains(tpoint,geometry)
es significativo solo cuando la geometría es un solo punto, y tcontains(tpoint,tpoint)
es equivalente a tintersects(tpoint, geometry)
. Por esta razón, solo se define la primera combinación de parámetros para contains
y tcontains
.
Finalmente, cabe destacar que las relaciónes temporales permiten mezclar geometrías 2D/3D pero en ese caso, el cálculo sólo se realiza en 2D.
Puede contener
contains({geo,tgeompoint},{geo,tgeompoint}): boolean
SELECT contains(geometry 'Polygon((0 0,0 1,1 1,1 0,0 0))', tgeompoint '[Point(0 0)@2012-01-01, Point(1 1)@2012-01-03)'); -- true
Puede ser disjunto
disjoint({geo,tgeompoint},{geo,tgeompoint}): boolean
SELECT disjoint(geometry 'Polygon((0 0,0 1,1 1,1 0,0 0))', tgeompoint '[Point(0 0)@2012-01-01, Point(1 1)@2012-01-03)'); -- false
Puede estar a distancia de
dwithin({geo,tpoint},{geo,tpoint},float): boolean
SELECT dwithin(geometry 'Polygon((0 0 0,0 1 1,1 1 1,1 0 0,0 0 0))', tgeompoint 'Point(0 2 1)@2000-01-01,Point(2 2 1)@2000-01-02', 1) -- true SELECT dwithin(geometry 'Polygon((0 0 0,0 1 1,1 1 1,1 0 0,0 0 0))', tgeompoint 'Point(0 2 2)@2000-01-01,Point(2 2 2)@2000-01-02', 1) -- false
Puede cruzarse
intersects({geo,tpoint},{geo,tpoint}): boolean
SELECT intersects(geometry 'Polygon((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0))', tgeompoint '[Point(0 0 1)@2012-01-01, Point(1 1 1)@2012-01-03)'); -- false SELECT intersects(geometry 'Polygon((0 0 0,0 1 1,1 1 1,1 0 0,0 0 0))', tgeompoint '[Point(0 0 1)@2012-01-01, Point(1 1 1)@2012-01-03)'); -- true
Puede tocar
touches({geo,tgeompoint},{geo,tgeompoint}): boolean
SELECT touches(geometry 'Polygon((0 0,0 1,1 1,1 0,0 0))', tgeompoint '[Point(0 0)@2012-01-01, Point(0 1)@2012-01-03)'); -- true
Contiene temporal
tcontains({geo,tgeompoint},{geo,tgeompoint}): tbool
SELECT tcontains(geometry 'Polygon((1 1,1 2,2 2,2 1,1 1))', tgeompoint '[Point(0 0)@2012-01-01, Point(3 3)@2012-01-04)'); -- "{[f@2012-01-01, f@2012-01-02], (t@2012-01-02, f@2012-01-03, f@2012-01-04)}"
Disjunto temporal
tdisjoint({geo,tgeompoint},{geo,tgeompoint}): tbool
SELECT tdisjoint(geometry 'Polygon((1 1,1 2,2 2,2 1,1 1))', tgeompoint '[Point(0 0)@2012-01-01, Point(3 3)@2012-01-04)'); -- "{[t@2012-01-01, f@2012-01-02, f@2012-01-03], (t@2012-01-03, t@2012-01-04]}" SELECT tdisjoint(tgeompoint '[Point(0 3)@2012-01-01, Point(3 0)@2012-01-05)', tgeompoint '[Point(0 0)@2012-01-01, Point(3 3)@2012-01-05)'); -- "{[t@2012-01-01, f@2012-01-03], (t@2012-01-03, t@2012-01-05)}"
Estar a distancia de temporal
tdwithin({geo,tpoint},{geo,tpoint},float): tbool
SELECT tdwithin(geometry 'Polygon((1 1,1 2,2 2,2 1,1 1))', tgeompoint '[Point(0 0)@2012-01-01, Point(3 0)@2012-01-04)', 1); -- "{[f@2012-01-01, t@2012-01-02, t@2012-01-03], (f@2012-01-03, f@2012-01-04)}" SELECT tdwithin(tgeompoint '[Point(1 0)@2000-01-01, Point(1 4)@2000-01-05]', tgeompoint 'Interp=Stepwise;[Point(1 2)@2000-01-01, Point(1 3)@2000-01-05]', 1); -- "{[f@2000-01-01, t@2000-01-02, t@2000-01-04], (f@2000-01-04, t@2000-01-05]}"
Intersección temporal
tintersects({geo,tpoint},{geo,tpoint}): tbool
SELECT tintersects(geometry 'MultiPoint(1 1,2 2)', tgeompoint '[Point(0 0)@2012-01-01, Point(3 3)@2012-01-04)'); -- "{[f@2012-01-01, t@2012-01-02], (f@2012-01-02, t@2012-01-03], (f@2012-01-03, f@2012-01-04]}" SELECT tintersects(tgeompoint '[Point(0 3)@2012-01-01, Point(3 0)@2012-01-05)', tgeompoint '[Point(0 0)@2012-01-01, Point(3 3)@2012-01-05)'); -- "{[f@2012-01-01, t@2012-01-03], (f@2012-01-03, f@2012-01-05)}"
Toca temporal
ttouches({geo,tgeompoint},{geo,tgeompoint}): tbool
SELECT ttouches(geometry 'Polygon((1 0,1 2,2 2,2 0,1 0))', tgeompoint '[Point(0 0)@2012-01-01, Point(3 0)@2012-01-04)'); -- "{[f@2012-01-01, t@2012-01-02, t@2012-01-03], (f@2012-01-03, f@2012-01-04]}"