Tabla de contenidos
Los puntos temporales que hemos considerado hasta ahora representan el movimiento de objetos que pueden moverse libremente en el espacio ya que se supone que pueden cambiar su posición de un lugar a otro sin ninguna restricción de movimiento. Este es el caso de los animales y de los objetos voladores como aviones o drones. Sin embargo, en muchos casos, los objetos no se mueven libremente en el espacio sino dentro de redes integradas espacialmente, como rutas o ferrocarriles. En este caso, es necesario tener en cuenta de las redes integradas al describir los movimientos de estos objetos en movimiento. Los puntos de red temporales tienen en cuenta estos requisitos.
En comparación con los puntos temporales de espacio libre, los puntos basados en red tienen las siguientes ventajas:
Los puntos de red temporales proporcionan restricciones que reflejan los movimientos reales de los objetos en movimiento.
La información geométrica no se almacena con el punto móvil, sino de una vez por todas en las redes fijas. De esta forma, las representaciones e interpolaciones de la ubicación son más precisas.
Los puntos de red temporales son más eficientes en términos de almacenamiento de datos, actualización de ubicación, formulación de consultas e indexación. Estos aspectos se tratan más adelante en este documento.
Los puntos de red temporales se basan en pgRouting, una extensión de PostgreSQL para desarrollar aplicaciones de enrutamiento de red y realizar análisis de gráficos. Por lo tanto, los puntos de red temporal asumen que la red subyacente está definida en una tabla llamada ways
, que tiene al menos tres columnas: gid
que contiene el identificador de ruta único, length
que contiene la longitud de la ruta y the_geom
que contiene la geometría de la ruta.
Hay dos tipos de red estáticos, npoint
(abreviatura de network point) y nsegment
(abreviatura de network segment), que representan, respectivamente, un punto y un segmento de una ruta. Un valor npoint
se compone de un identificador de ruta y un número flotante en el rango [0,1] que determina una posición relativa de la ruta, donde 0 corresponde al comienzo de la ruta y 1 al final de la ruta. Un valor de nsegment
se compone de un identificador de ruta y dos números flotantes en el rango [0,1] que determinan las posiciones relativas de inicio y finalización. Un valor de nsegment
cuyas posiciones inicial y final son iguales corresponde a un valor de npoint
.
El tipo npoint
sirve como tipo base para definir el tipo punto de red temporal tnpoint
. El tipo tnpoint
tiene una funcionalidad similar al tipo de punto temporal tgeompoint
con la excepción de que solo considera dos dimensiones. Por lo tanto, todas las funciones y operadores descritos anteriormente para el tipo tgeompoint
también son aplicables para el tipo tnpoint
. Además, hay funciones específicas definidas para el tipo tnpoint
.
Un valor npoint
es un par de la forma (rid, position)
donde rid
es un valor bigint
que representa un identificador de ruta y position
es un valor float
en el rango [0,1] que indica su posición relativa. Los valores 0 y 1 de position
denotan, respectivamente, la posición inicial y final de la ruta. La distancia de la ruta entre un valor de npoint
y la posición inicial de la ruta con el identificador rid
se calcula multiplicando position
por length
, donde este último es la longitud de la ruta. Ejemplos de entrada de valores de puntos de red son los siguientes:
SELECT npoint 'Npoint(76, 0.3)'; SELECT npoint 'Npoint(64, 1.0)';
La función de constructor para puntos de red tiene un argumento para el identificador de ruta y un argumento para la posición relativa. Un ejemplo de un valor de punto de red definido con la función constructora es el siguiente:
SELECT npoint(76, 0.3);
Un valor nsegment
es un triple de la forma (rid, startPosition, endPosition)
donde rid
es un valor bigint
que representa un identificador de ruta y startPosition
y endPosition
son valores de float
en el rango [0,1] tal que startPosition ≤ endPosition
. Semánticamente, un segmento de red representa un conjunto de puntos de red (rid, position)
con startPosition ≤ position ≤ endPosition
. Si startPosition = 0
y endPosition = 1
, el segmento de red es equivalente a la ruta completa. Si startPosition = endPosition
, el segmento de red representa un único punto de red. Ejemplos de entrada de valores de puntos de red son los siguientes:
SELECT nsegment 'Nsegment(76, 0.3, 0.5)'; SELECT nsegment 'Nsegment(64, 0.5, 0.5)'; SELECT nsegment 'Nsegment(64, 0.0, 1.0)'; SELECT nsegment 'Nsegment(64, 1.0, 0.0)'; -- convertido a nsegment 'Nsegment(64, 0.0, 1.0)';
Como se puede ver en el último ejemplo, los valores startPosition
y endPosition
se invertirán para asegurar que la condición startPosition ≤ endPosition
siempre se satisface. La función de constructor para segmentos de red tiene un argumento para el identificador de ruta y dos argumentos opcionales para las posiciones inicial y final. Los ejemplos de valores de segmento de red definidos con la función constructora son los siguientes:
SELECT nsegment(76, 0.3, 0.3); SELECT nsegment(76); -- se asume que las posiciones inicial y final son 0 y 1 SELECT nsegment(76, 0.5); -- se asume que la posición final es 1
Los valores del tipo npoint
se pueden convertir al tipo nsegment
usando un CAST
explícito o usando la notación ::
como se muestra a continuación.
SELECT npoint(76, 0.33)::nsegment;
Los valores de los tipos de red estáticos deben satisfacer varias restricciones para que estén bien definidos. Estas restricciones se dan a continuación.
El identificador de ruta rid
debe encontrarse en la columna gid
de la tabla ways
.
Los valores de position
, startPosition
y endPosition
deben estar en el rango [0,1]. Se genera un error cuando no se cumple una de estas restricciones.
Ejemplos de valores de tipo de red estática incorrectos son los siguientes.
-- Valor rid incorrecto SELECT npoint 'Npoint(87.5, 1.0)'; -- Valor de posición incorrecto SELECT npoint 'Npoint(87, 2.0)'; -- Valor rid inexistente en la table ways SELECT npoint 'Npoint(99999999, 1.0)';
Damos a continuación las funciones y operadores para los tipos de redes estáticas.
Redondear la(s) posición(es) del punto de red or el segmento de red en el número de posiciones decimales
round({npoint,nsegment},integer=0) → {npoint,nsegment}
SELECT round(npoint(76, 0.123456789), 6); -- NPoint(76,0.123457) SELECT round(nsegment(76, 0.123456789, 0.223456789), 6); -- NSegment(76,0.123457,0.223457)
Obtener el identificador de ruta
route({npoint,nsegment}) → bigint
SELECT route(npoint 'Npoint(63, 0.3)'); -- 63 SELECT route(nsegment 'Nsegment(76, 0.3, 0.3)'); -- 76
Obtener la posición
getPosition(npoint) → float
SELECT getPosition(npoint 'Npoint(63, 0.3)'); -- 0.3
Obtener la posición inicial/final
startPosition(nsegment) → float
endPosition(nsegment) → float
SELECT startPosition(nsegment 'Nsegment(76, 0.3, 0.5)'); -- 0.3 SELECT endPosition(nsegment 'Nsegment(76, 0.3, 0.5)'); -- 0.5
Los valores de los tipos npoint
y nsegment
se pueden convertir al tipo geometry
usando un CAST
explícito o usando la notación ::
como se muestra a continuación.
Convertir un punto de red en una geometría
{npoint,nsegment}::geometry
SELECT ST_AsText(npoint(76, 0.33)::geometry); -- POINT(21.6338731332283 50.0545869554067) SELECT ST_AsText(nsegment(76, 0.33, 0.66)::geometry); -- LINESTRING(21.6338731332283 50.0545869554067,30.7475989651999 53.9185062927473) SELECT ST_AsText(nsegment(76, 0.33, 0.33)::geometry); -- POINT(21.6338731332283 50.0545869554067)
De manera similar, los valores de tipo geometry
de subtipo point
o linestring
(restringidos a dos puntos) se pueden convertir, respectivamente, en valores npoint
y nsegment
usando un CAST
explícito o usando la notación ::
. Para ello se debe encontrar la ruta que interseca los puntos dados, donde se asume una tolerancia de 0.00001 unidades (dependiendo del sistema de coordenadas) por lo que se considera que un punto y una ruta que están cerca se cruzan. Si no se encuentra dicha ruta, se devuelve un valor nulo.
Convertir una geometría en un punto de red
geometry::{npoint,nsegment}
SELECT geometry 'Point(279.269156511873 811.497076880187)'::npoint; -- NPoint(3,0.781413) SELECT geometry 'LINESTRING(406.729536784738 702.58583437902, 383.570801314823 845.137059419277)'::nsegment; -- NSegment(3,0.6,0.9) SELECT geometry 'Point(279.3 811.5)'::npoint; -- NULL SELECT geometry 'LINESTRING(406.7 702.6,383.6 845.1)'::nsegment; -- NULL
Dos valores npoint
pueden tener diferentes identificadores de ruta pero pueden representar el mismo punto espacial en la intersección de las dos rutas. La función equals
se utiliza para verificar la igualdad espacial de los puntos de la red.
Igualdad espacial para puntos de red
equals(npoint, npoint)::Boolean
WITH inter(geom) AS ( SELECT st_intersection(t1.the_geom, t2.the_geom) FROM ways t1, ways t2 WHERE t1.gid = 1 AND t2.gid = 2), fractions(f1, f2) AS ( SELECT ST_LineLocatePoint(t1.the_geom, i.geom), ST_LineLocatePoint(t2.the_geom, i.geom) FROM ways t1, ways t2, inter i WHERE t1.gid = 1 AND t2.gid = 2) SELECT equals(npoint(1, f1), npoint(2, f2)) FROM fractions; -- true
Los operadores de comparación (=, < y así sucesivamente) para tipos de red estáticos requieren que los argumentos izquierdo y derecho sean del mismo tipo. Excepto la igualdad y la desigualdad, los otros operadores de comparación no son útiles en el mundo real pero permiten que los índices de árbol B se construyan en tipos de red estáticos.
¿Son iguales los valores?
{npoint,nsegment} = {npoint,nsegment}
SELECT npoint 'Npoint(3, 0.5)' = npoint 'Npoint(3, 0.5)'; -- true SELECT nsegment 'Nsegment(3, 0.5, 0.5)' = nsegment 'Nsegment(3, 0.5, 0.6)'; -- false
¿Son diferentes los valores?
{npoint,nsegment} <> {npoint,nsegment}
SELECT npoint 'Npoint(3, 0.5)' <> npoint 'Npoint(3, 0.6)'; -- true SELECT nsegment 'Nsegment(3, 0.5, 0.5)' <> nsegment 'Nsegment(3, 0.5, 0.5)'; -- false
¿El primer valor es menor que el segundo?
{npoint,nsegment} < {npoint,nsegment}
SELECT nsegment 'Nsegment(3, 0.5, 0.5)' < nsegment 'Nsegment(3, 0.5, 0.6)'; -- true
¿El primer valor es mayor que el segundo?
{npoint,nsegment} > {npoint,nsegment}
SELECT nsegment 'Nsegment(3, 0.5, 0.5)' > nsegment 'Nsegment(2, 0.5, 0.5)'; -- true
¿El primer valor es menor o igual que el segundo?
{npoint,nsegment} <= {npoint,nsegment}
SELECT npoint 'Npoint(1, 0.5)' <= npoint 'Npoint(2, 0.5)'; -- true
¿El primer valor es mayor o igual que el segundo?
{npoint,nsegment} >= {npoint,nsegment}
SELECT npoint 'Npoint(1, 0.6)' >= npoint 'Npoint(1, 0.5)'; -- true