5.12. Funciones y operadores espaciales

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.

5.12.1. Funciones de entrada/salida

  • 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"
    	

5.12.2. Funciones de sistema de referencia espacial

  • 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"
    	

5.12.3. Funciones de accessor

  • 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.

5.12.4. Funciones de manipulación

  • 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)
    	)
    	
    Visualización de la velocidad de un objeto móvil usando una rampa de color en QGIS.

    Figura 5.1. Visualización de la velocidad de un objeto móvil usando una rampa de color en QGIS.


  • 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}
    	

5.12.5. Funciones y operadores de distancia

  • 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)"
    

5.12.6. Relaciones espaciales

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.

5.12.7. Relaciones topológicas posibles

  • 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
    

5.12.8. Relaciones topológicas temporales

  • 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]}"