Capítulo 11. Puntos de red temporales

Tabla de contenidos

Tipos de red estáticos
Constructores
Transformaciones
Accesores
Operaciones espaciales
Comparaciones
Puntos de red temporales
Validez de los puntos de red temporal
Constructores
Conversión de tipos
Operaciones para los tipos de puntos de red
Agregacions
Indexación

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

Tipos de red estáticos

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.

Constructores

  • Constructor de puntos de red

    npoint(bigint,double precision) → npoint

    SELECT npoint(76, 0.3);
    
  • Constructor de segmentos de red

    nsegment(bigint,double precision,double precision) → nsegment

    SELECT nsegment(76, 0.3, 0.5);
    

Transformaciones

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

Accesores

  • 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
    

Operaciones espaciales

  • Obtener el identificador de referencia espacial

    SRID({npoint,nsegment}) → integer

    SELECT SRID(npoint 'Npoint(76, 0.3)');
    -- 5676
    SELECT SRID(nsegment 'Nsegment(76, 0.3, 0.5)');
    -- 5676
    

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
    

Comparaciones

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