Capítulo 13. Poses temporales

Tabla de contenidos

Poses estáticas
Entrada y salida
Constructores
Conversión de tipos
Accesores
Transformaciones
Sistema de referencia espacial
Operaciones de distancia
Comparaciones
Poses temporales
Validez de las poses temporales
Entrada y salida
Constructores
Conversión de tipos
Accesores
Transformaciones
Modificaciones
Restricciones
Sistema de referencia espacial
Operaciones de cuadro delimitador
Operaciones de distancia
Relaciones espaciales
Comparaciones
Agregaciones
Indexación
Soporte de OGC GeoPose v1.0
Entrada y salida JSON
Renormalización de cuaterniones
Accesores de ángulos de Euler
Registro de metadatos de marcos
Transformación rígida cuerpo↔mundo
E/S JSON temporal

El tipo pose se utiliza para representar la ubicación y la orientación de objetos geométricos dentro de sistemas de coordenadas anclados a la superficie de la Tierra o dentro de otros sistemas de coordenadas astronómicas. La ubicación se representa mediante un punto 2D o 3D. Para las poses 2D, la orientación se define mediante un ángulo de rotación en (-π, π] expresado en radianes. Para las poses 3D, la orientación se define mediante cuatro valores flotantes W, X, Y, Z, que representan un cuaternión unitario Q = W , X , Y , Z donde Q2 = W2 + X2 + Y2 + Z2 = 1 .

El grupo de trabajo de estándares GeoPose (SWG), que trabaja bajo los auspicios del Open Geospatial Consortium, ha definido un estándar para intercambiar información de poses entre distintos usuarios, dispositivos y plataformas. Se puede encontrar más información sobre el estándar en el repositorio de GitHub del SWG GeoPose.

El tipo pose sirve como tipo base para definir el tipo de pose temporal tpose. El tipo tpose tiene una funcionalidad similar al tipo de punto temporal tgeompoint. Por lo tanto, la mayoría de las funciones y operadores descritos anteriormente para el tipo tgeompoint también son aplicables para el tipo tpose. Además, hay funciones específicas definidas para el tipo tpose.

En este capítulo cubrimos estas funciones.

El tipo tpose se utiliza para definir el tipo trgeometry (es decir, geometría rígida temporal) definido en el siguiente capítulo. La implementación de estos tipos en MobilityDB se ha estudiado en la siguiente tesis doctoral.

Poses estáticas

Una pose 2D es un par de la forma (point2D,radius) donde point2D es un punto geométrico 2D y radius es un valor float que representa un ángulo de rotación en (-π, π] expresado en radianes. Una pose 3D es una tupla de la forma (point3D,W,Y,X,Z) donde point3D es un punto geométrico 3D, y W, X, Y y Z son cuatro floats que representan un cuaternión unitario. Ejemplos de entrada de valores de pose son los siguientes:

SELECT pose 'Pose(Point(1 1), 0.5)';
SELECT pose 'Pose(Point Z(1 1 1), 0.5, 0.5, 0.5, 0.5)';

Se puede especificar un SRID para una pose ya sea al comienzo del literal de pose o antes del literal de punto, como se muestra a continuación.

SELECT pose 'SRID=3812;Pose(Point(1 1), 0.5)';
SELECT pose 'Pose(SRID=5676;Point Z(1 1 1), 0.5, 0.5, 0.5, 0.5)';

Los valores del tipo pose deben satisfacer varias restricciones para que estén bien definidos. Ejemplos de valores incorrectos del tipo pose son los siguientes.

-- Punto vacío
select pose 'Pose(Point empty, 0.5)';
-- Valor de punto incorrecto
SELECT pose 'Pose(Linestring(1 1,2 2), 1.0)';
-- Valor de radio incorrecto
SELECT pose 'Pose(Point(1 1), -10.0)';
-- Punto 3D incorrecto
SELECT pose 'Pose(Point Z(1 1), 1.0)';
-- Orientación 3D incompleta
SELECT pose 'Pose(Point Z(1 1 1), 1.0)';

A continuación damos las funciones y operadores para el tipo pose.

Entrada y salida

  • Devuelve la representación de texto conocido (Well-Known Text o WKT) o la representación extendida de texto conocido (Extended Well-Known Text o EWKT)

    asText({pose,pose[]}) → {text,text[]}
    asEWKT({pose,pose[]}) → {text,text[]}
    
    SELECT asText(pose 'SRID=4326;Pose(Point(0 0),1)');
    -- Pose(POINT(0 0),1)
    SELECT asText(ARRAY[pose 'Pose(Point(0 0),1)', 'Pose(Point(1 1),2)']);
    -- {"Pose(POINT(0 0),1)","Pose(POINT(1 1),2)"}
    SELECT asEWKT(pose 'SRID=4326;Pose(Point(0 0),1)');
    -- SRID=4326;Pose(Point(0 0),1)
    SELECT asEWKT(ARRAY[pose 'Pose(SRID=5676;Point(0 0),1)', 'Pose(SRID=5676;Point(1 1),2)']);
    -- {"Pose(SRID=5676;POINT(0 0),1)","Pose(SRID=5676;POINT(1 1),2))"}
    
  • Devuelve la representación binaria conocida (Well-Known Binary o WKB), la representación extendida binaria conocida (Extended Well-Known Binary o EWKB), la representación hexadecimal binaria conocida (Hexadecimal Well-Known Binary o HexWKB), o la representación hexadecimal extendida binaria conocida (Hexadecimal Extended Well-Known Binary o HexEWKB)

    asBinary(pose,endian text='') → bytea
    asEWKB(pose,endian text='') → bytea
    asHexWKB(pose,endian text='') → text
    asHexEWKB(pose,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 la codificación de la máquina.

    SELECT asBinary(pose 'Pose(Point(1 2),1)');
    -- \x0101000000000000f03f0000000000000040000000000000f03f
    SELECT asEWKB(pose 'SRID=7844;Pose(Point(1 2),1)');
    -- \x0141a41e0000000000000000f03f0000000000000040000000000000f03f
    SELECT asHexWKB(pose 'Pose(Point(1 2),1)');
    -- 0101000000000000F03F0000000000000040000000000000F03F
    SELECT asHexEWKB(pose 'SRID=3812;Pose(Point(1 2),1)');
    -- 0141E40E0000000000000000F03F0000000000000040000000000000F03F
    
  • Entrada desde la representación de texto conocido (Well-Known Text o WKT) o desde la representación extendida de texto conocido (Extended Well-Known Text o EWKT)

    poseFromText(text) → pose
    poseFromEWKT(text) → pose
    
    SELECT asEWKT(poseFromText(text 'Pose(Point(1 2),1)'));
    -- Pose(POINT(1 2),1)
    SELECT asEWKT(poseFromEWKT(text 'SRID=3812;Pose(Point(1 2),1)'));
    -- SRID=3812;Pose(Point(1 2),1)
    
  • Entrada desde la representación binaria conocida (Well-Known Binary o WKB), desde la representación extendida binaria conocida (Extended Well-Known Binary o EWKB), o desde la representación hexadecimal extendida binaria conocida (Hexadecimal Extended Well-Known Binary o HexEWKB)

    poseFromBinary(bytea) → pose
    poseFromEWKB(bytea) → pose
    poseFromHexEWKB(text) → pose
    
    SELECT asEWKT(poseFromBinary(
      '\x0101000000000000f03f0000000000000040000000000000f03f'));
    -- Pose(POINT(1 2),1)
    SELECT asEWKT(poseFromEWKB(
      '\x0141a41e0000000000000000f03f0000000000000040000000000000f03f'));
    -- SRID=7844;Pose(Point(1 2),1)
    SELECT asEWKT(poseFromHexEWKB(
      '0141E40E0000000000000000F03F0000000000000040000000000000F03F'));
    -- SRID=3812;Pose(POINT(1 2),1)
    

Constructores

  • Constructor para poses

    pose(geompoint2D,float) → pose
    pose(geompoint3D,float,float,float,float) → pose
    pose(geompoint3D,yaw float,pitch float,roll float) → pose
    

    La forma de tres ángulos toma la orientación en la otra codificación que prescribe el estándar OGC GeoPose v1.0, una terna yaw / pitch / roll en radianes bajo la convención Tait-Bryan intrínseca ZYX, y almacena el cuaternión que denota. Es la inversa de ypr.

    SELECT asText(pose(ST_Point(1,1), radians(45)), 6);
    -- Pose(POINT(1 1),0.785398)
    SELECT asEWKT(pose(ST_Point(1,1,3812), radians(45)), 6);
    -- SRID=3812;Pose(POINT(1 1),0.785398)
    SELECT asText(pose(ST_PointZ(1,1,1), 1, 0, 0, 0));
    -- Pose(POINT Z (1 1 1),1,0,0,0)
    SELECT asText(pose(ST_PointZ(1,1,1), radians(90), 0, 0), 6);
    -- Pose(POINT Z (1 1 1),0.707107,0,0,0.707107)
    

Conversión de tipos

Los valores del tipo pose se pueden convertir al tipo de punto geometry utilizando un CAST explícito o utilizando la notación :: como se muestra a continuación.

  • Convertir una pose y, opcionalmente, una marca de tiempo o un período, en una caja espaciotemporal

    pose::stbox
    stbox(pose) → stbox
    stbox(pose,{timestamptz,tstzspan}) → stbox
    
    SELECT stbox(pose 'SRID=5676;Pose(Point(1 1),0.3)');
    -- SRID=5676;STBOX X((1,1),(1,1))
    SELECT stbox(pose 'Pose(Point(1 1),0.3)', timestamptz '2001-01-01');
    -- STBOX XT(((1,1),(1.3,1.3)),[2001-01-01, 2001-01-01])
    SELECT stbox(pose 'Pose(Point(1 1),0.3)', tstzspan '[2001-01-01,2001-01-02]');
    -- STBOX XT(((1,1),(1.3,1.3)),[2001-01-01, 2001-01-02])
    
  • Convertir una pose en un punto geométrico

    pose::geompoint
    
    SELECT ST_AsText(pose(ST_Point(1, 1), 1)::geometry);
    -- Point(1 1)
    SELECT ST_AsEWKT(pose(ST_PointZ(1, 1, 1, 5676), 1, 0, 0, 0)::geometry);
    -- SRID=5676;POINT(1 1 1)
    

Accesores

  • Devuelve el punto

    point(pose) → geompoint
    
    SELECT ST_AsText(point(pose 'Pose(Point(1 1), 0.3)'));
    -- Point(1 1)
    
  • Devuelve el cuaternión de orientación de una pose

    quaternion(pose) → quaternion
    

    Las componentes se devuelven en el orden W, X, Y, Z, la convención de Hamilton en la que una pose 3D las almacena. Esta es una de las dos codificaciones de orientación que prescribe el estándar OGC GeoPose v1.0; la otra, yaw / pitch / roll, la proporciona ypr. Ambas están definidas para las dos dimensiones: la orientación de una pose 2D es un giro alrededor de la vertical local por su ángulo almacenado, de modo que coloca la mitad de ese ángulo en W y Z y deja X e Y en cero. Este es el cuaternión que un documento GeoPose Basic-Quaternion lleva para una pose plana.

    SELECT quaternion(pose 'Pose(Point Z(1 1 1), 0, 0, 0, 1)');
    -- (0,0,0,1)
    SELECT quaternion(pose 'Pose(Point(1 1), 0)');
    -- (1,0,0,0)
    

Transformaciones

  • Redondear el punto y la orientación de la pose al número de posiciones decimales

    round(pose,integer=0) → pose
    
    SELECT asText(round(pose(ST_Point(1.123456789,1.123456789), 0.123456789), 6));
    -- Pose(POINT(1.123457 1.123457),0.123457)
    

Sistema de referencia espacial

  • Devuelve o establece el identificador de referencia espacial

    SRID(pose) → integer
    setSRID(pose) → pose
    
    SELECT SRID(pose 'Pose(SRID=5676;Point(1 1), 0.3)');
    -- 5676
    SELECT asEWKT(setSRID(pose 'Pose(Point(0 0),1)', 4326));
    -- SRID=4326;Pose(POINT(0 0),1)
    
  • Transformar a un identificador de referencia espacial

    transform(pose,integer) → pose
    transformPipeline(pose,pipeline text,to_srid integer,is_forward boolean=true) → pose
    

    La función transform especifica la transformación con un SRID de destino. Se genera un error cuando la pose de entrada tiene un SRID desconocido (representado por 0).

    En una pose 3D, la orientación se reexpresa en la base del marco de destino en el punto de la pose. La corrección está definida para el par canónico de OGC GeoPose, WGS-84 geográfico (EPSG:4326) ↔ WGS-84 ECEF (EPSG:4978), y toma la base estándar Este-Norte-Arriba en el punto geográfico como pivote de rotación. Para cualquier otro par de SRID, transform emite un NOTICE y deja pasar la orientación sin cambios. En una pose 2D, el ángulo es intrínseco a la proyección de origen y se deja pasar sin cambios.

    La función transformPipeline especifica la transformación con una canalización de transformación de coordenadas definida representada con el siguiente formato de cadena:

    urn:ogc:def:coordinateOperation:AUTHORITY::CODE

    El SRID de la pose de entrada se ignora y el SRID de la pose de salida se establecerá en cero a menos que se proporcione un valor a través del parámetro opcional to_srid. Como se indica en el último parámetro, la canalización se ejecuta de forma predeterminada en dirección hacia adelante; al establecer el parámetro en falso, la canalización se ejecuta en la dirección inversa.

    SELECT asEWKT(transform(pose 'SRID=4326;Pose(Point(4.35 50.85),1)', 3812), 6);
    -- SRID=3812;Pose(POINT(648679.018035 671067.055638),1)
    
    -- Un viaje de ida y vuelta de una pose 3D por ECEF aterriza en la pose de entrada
    SELECT asEWKT(round(
      transform(transform(pose 'SRID=4326;Pose(Point(8 47 0), 1, 0, 0, 0)', 4978),
                4326), 6));
    -- SRID=4326;Pose(POINT Z (8 47 0),1,0,0,0)
    
    -- En el cruce del ecuador y el meridiano (lat=lon=0), el cuaternión identidad
    -- del cuerpo en la base ECEF es la rotación canónica Este-Norte-Arriba a ECEF
    SELECT asEWKT(round(
      transform(pose 'SRID=4326;Pose(Point(0 0 0), 1, 0, 0, 0)', 4978), 6));
    -- SRID=4978;Pose(POINT Z (6378137 0 0),0.5,0.5,0.5,0.5)
    
    WITH test(pose, pipeline) AS (
      SELECT pose 'Pose(SRID=4326;Point(4.3525 50.846667),1)',
        text 'urn:ogc:def:coordinateOperation:EPSG::16031' )
    SELECT asEWKT(transformPipeline(transformPipeline(pose, pipeline, 4326), pipeline,
      4326, false), 6)
    FROM test;
    -- SRID=4326;Pose(POINT(4.3525 50.846667),1)
    

Operaciones de distancia

  • Devuelve la distancia

    distance({geo,stbox,pose},pose) → float
    distance(pose,{geo,stbox,pose}) → float
    {geo,stbox,pose} <-> pose → float
    

    Solo se tiene en cuenta el componente de punto de la pose, la orientación se ignora. La distancia se calcula en dos dimensiones, incluso cuando los argumentos son tridimensionales. El resultado es NULL cuando la geometría está vacía.

    SELECT round(distance(geometry 'Point(1 0)', pose 'Pose(Point(4 0),0)'), 6);
    -- 3
    SELECT round(distance(stbox 'STBOX X((1,-1),(3,1))', pose 'Pose(Point(4 0),0)'), 6);
    -- 1
    SELECT round(pose 'Pose(Point(0 0),0)' <-> pose 'Pose(Point(3 4),0)', 6);
    -- 5
    SELECT round(pose 'Pose(Point(0 0 0), 1, 0, 0, 0)' <->
      pose 'Pose(Point(3 4 12), 1, 0, 0, 0)', 6);
    -- 5
    SELECT round(geometry 'Point empty' <-> pose 'Pose(Point(4 0),0)', 6);
    -- NULL
    

Comparaciones

Los operadores de comparación (=, < y así sucesivamente) están disponibles para poses. 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 poses.

  • Comparaciones tradicionales

    pose {=, <>, <, >, <=, >=} pose
    
    SELECT pose 'Pose(Point(3 3), 0.5)' = pose 'Pose(Point(3 3), 0.5)';
    -- true
    SELECT pose 'Pose(Point(3 3), 0.5)' <> pose 'Pose(Point(3 3), 0.6)';
    -- true
    SELECT pose 'Pose(Point(3 3), 0.5)' < pose 'Pose(Point(3 3), 0.6)';
    -- true
    SELECT pose 'Pose(Point(3 3), 0.6)' > pose 'Pose(Point(2 2), 0.6)';
    -- true
    SELECT pose 'Pose(Point Z(1 1 1), 0.5, 0.5, 0.5, 0.5)' <= pose 'Pose(Point Z(2 2 2), 0.5,
      0.5, 0.5, 0.5)';
    -- true
    SELECT pose 'Pose(Point(1 1), 0.6)' >= pose 'Pose(Point(1 1), 0.5)';
    -- true
    
  • ¿Son las poses aproximadamente iguales con respecto a un valor épsilon?

    pose ~= pose → boolean
    
    SELECT pose 'Pose(SRID=5676;Point(1 1), 0.3)' ~= 
      pose 'Pose(SRID=5676;Point(1 1.0000001), 0.30000001)';
    -- true