# Tipos de cuadro delimitador

A continuación presentamos las funciones y operadores para tipos cuadro delimitador. Estas funciones y operadores son polimórficos, es decir, sus argumentos pueden ser de varios tipos y el tipo del resultado puede depender del tipo de los argumentos. Para expresar esto, usamos la siguiente notación:

- `box` representa cualquier tipos cuadro delimitador, es decir `tbox` o `stbox`.

## Entrada y salida

MobilityDB generaliza los formatos de entrada y salida Well-Known Text (WKT) y Well-Known Binary (WKB) del Open Geospatial Consortium para todos los tipos temporales. Presentamos a continuación las funciones de entrada y salida para los tipos de cuadro delimitador.

Un `tbox` se compone de dimensiónes de valor numérico y/o de tiempo. Para cada dimensión, se proporciona un rango, es decir, ya sea un `intspan` o un `floatspan` para la dimensión de valor y un `tstzspan` para la dimensión de tiempo. Ejemplos de entrada de valores `tbox` son los siguientes:

    -- Dimensiones de valor y tiempo
    SELECT tbox 'TBOXINT XT([1,3),[2001-01-01,2001-01-02])';
    SELECT tbox 'TBOXFLOAT XT([1.5,2.5],[2001-01-01,2001-01-02])';
    -- Sólo dimensión de valor
    SELECT tbox 'TBOXINT X([1,3))';
    SELECT tbox 'TBOXFLOAT X((1.5,2.5))';
    -- Sólo dimensión de tiempo
    SELECT tbox 'TBOX T((2001-01-01,2001-01-02))';

Un `stbox` se compone de dimensiónes espacial y/o temporal, donde las coordenadas de la dimensión espacial pueden ser 2D o 3D. Para la dimensión de tiempo se da un `tstzspan`, y para la dimensión espacial se dan los valores mínimos y máximos de las coordenadas, donde estas últimas pueden ser cartesianas (planas) o geodésicas (esféricas). Se puede especificar el SRID de las coordenadas; si no es el caso, se asume un valor de 0 (desconocido) y 4326 (correspondiente a WGS84), respectivamente, para coordenadas planas y geodésicas. Los cuadros geodésicos siempre tienen una dimensión Z para tener en cuenta la curvatura de la esfera o esferoide subyacente. Ejemplos de entrada de valores `stbox` son los siguientes:

    -- Sólo dimensión de valor con coordenadas X e Y
    SELECT stbox 'STBOX X((1.0,2.0),(1.0,2.0))';
    -- Sólo dimensión de valor con coordenadas X, Y y Z
    SELECT stbox 'STBOX Z((1.0,2.0,3.0),(1.0,2.0,3.0))';
    -- Dimensiones de valor (con coordenadas X e Y) y de tiempo
    SELECT stbox 'STBOX XT(((1.0,2.0),(1.0,2.0)),[2001-01-03,2001-01-03])';
    -- Dimensiones de valor (con coordenadas X, Y y Z) y de tiempo
    SELECT stbox 'STBOX ZT(((1.0,2.0,3.0),(1.0,2.0,3.0)),[2001-01-01,2001-01-03])';
    -- Sólo dimensión de tiempo
    SELECT stbox 'STBOX T([2001-01-03,2001-01-03])';
    -- Sólo dimensión de valores con coordenadas geodéticas X, Y y Z
    SELECT stbox 'GEODSTBOX Z((1.0,2.0,3.0),(1.0,2.0,3.0))';
    -- Dimensiones de valor (con coordenadas geodéticas X, Y y Z) y de tiempo
    SELECT stbox 'GEODSTBOX ZT(((1.0,2.0,3.0),(1.0,2.0,3.0)),[2001-01-04,2001-01-04])';
    -- Sólo dimensión temporal para cuadro geodético
    SELECT stbox 'GEODSTBOX T([2001-01-03,2001-01-03])';
    -- Se indica el SRID
    SELECT stbox 'SRID=5676;STBOX XT(((1.0,2.0),(1.0,2.0)),[2001-01-04,2001-01-04])';
    SELECT stbox 'SRID=4326;GEODSTBOX Z((1.0,2.0,3.0),(1.0,2.0,3.0))';

Damos a continuación las funciones de entrada y salida de tipos de cuadro delimitador en formato textual (Well-Known Text o WKT) y binario (Well-Known Binary o WKB).

- Devuelve la representación textual conocida (Well-Known Text o WKT)

  `asText(box,maxdecdigits=15) → text`

  El argumento `maxdecdigits` se puede utilizar para definir el número máximo de decimales para la salida de los valores de coma flotante (por defecto 15).

      SELECT asText(tbox 'TBOXFLOAT XT([1.123456789,2.123456789),[2001-01-01,2001-01-02))', 3);
      -- TBOXFLOAT XT([1.123, 2.123),[2001-01-01 00:00:00+01, 2001-01-02 00:00:00+01))
      SELECT asText(stbox 'STBOX Z((1.55,1.55,1.55),(2.55,2.55,2.55))', 0);
      -- STBOX Z((2,2,2),(3,3,3))

- Devuelve la representación binaria conocida (Well-Known Binary o WKB)

  `asBinary(box,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(tbox 'TBOXFLOAT XT([1,2),[2001-01-01,2001-01-02))');
      -- \x0103270001009c57d3c11c000000fc2ef1d51c00000d0001000000000000f03f0000000000000040
      SELECT asBinary(tbox 'TBOXFLOAT XT([1,2),[2001-01-01,2001-01-02))', 'XDR');
      -- \x000300270100001cc1d3579c0000001cd5f12efc00000d013ff00000000000004000000000000000
      SELECT asBinary(stbox 'STBOX X((1,1),(2,2))');
      -- \x0101000000000000f03f0000000000000040000000000000f03f0000000000000040

- Devuelve la representación hexadecimal binaria conocida (HexWKB) en formato texto

  `asHexWKB(box,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 asHexWKB(tbox 'TBOXFLOAT XT([1,2),[2001-01-01,2001-01-02))');
      -- 0103270001009C57D3C11C000000FC2EF1D51C00000D0001000000000000F03F0000000000000040
      SELECT asHexWKB(tbox 'TBOXFLOAT XT([1,2)[2001-01-01,2001-01-02))', 'XDR');
      -- 000300270100001CC1D3579C0000001CD5F12EFC00000D013FF00000000000004000000000000000
      SELECT asHexWKB(stbox 'STBOX X((1,1),(2,2))');
      -- 0101000000000000F03F0000000000000040000000000000F03F0000000000000040

- Entrar un cuadro delimitador en una representación binaria conocida (WKB)

  `tboxFromBinary(bytea) → tbox`

  `stboxFromBinary(bytea) → stbox`

      SELECT tboxFromBinary(
        '\x0103270001009c57d3c11c000000fc2ef1d51c00000d0001000000000000f03f0000000000000040');
      -- TBOXFLOAT XT([1,2),[2001-01-01,2001-01-02))
      SELECT stboxFromBinary(
        '\x0101000000000000f03f0000000000000040000000000000f03f0000000000000040');
      --  STBOX X((1,1),(2,2))

- Entrar un cuadro delimitador temporal en una representación hexadecimal binaria conocida (HexWKB)

  `tboxFromHexWKB(text) → tbox`

  `stboxFromHexWKB(text) → stbox`

      SELECT tboxFromHexWKB(
        '0103270001009C57D3C11C000000FC2EF1D51C00000D0001000000000000F03F0000000000000040');
      -- TBOXFLOAT XT([1,2),[2001-01-01,2001-01-02)))
      SELECT stboxFromHexWKB(
        '0101000000000000F03F0000000000000040000000000000F03F0000000000000040');
      -- STBOX X((1,1),(2,2))

## Constructores

El tipo `tbox` tienen varias funciones constructoras dependiendo de si se da la extensión de valor y/o de tiempo. La extensión de valor se puede especificar mediante un número o un intervalo, mientras que la extensión de tiempo se puede especificar mediante un tipo de tiempo.

- Constructor para `tbox`

  `tbox({number,numspan}) → tbox`

  `tbox({timestamptz,tstzspan}) → tbox`

  `tbox({number,numspan},{timestamptz,tstzspan}) → tbox`

      -- Dimensiones de valores y de tiempo
      SELECT tbox(1.0, timestamptz '2001-01-01');
      SELECT tbox(floatspan '[1.0,2.0)', tstzspan '[2001-01-01,2001-01-02)');
      -- Sólo dimensión de valores
      SELECT tbox(floatspan '[1.0,2.0)');
      -- Sólo dimensión de tiempo
      SELECT tbox(tstzspan '[2001-01-01,2001-01-02)');

El tipo `stbox` tiene varias funciones constructoras dependiendo de si se da la extensión espacial y/o de tiempo. Las coordenadas de la extension espacial pueden ser 2D o 3D y pueden ser cartesianas o geodésicas. La extensión espacial se puede especificar mediante los valores de coordenadas mínimo y máximo. El SRID se puede especificar en un último argumento opcional. Si no se proporciona, se asume un valor 0 (respectivamente 4326) por defecto para los cuadros planos (respectivamente geodésicos). La extensión espacial también se puede especificar mediante una geometría o una geografía. La extensión temporal se puede especificar mediante un tipo de tiempo.

- Constructor para `stbox`

  `stboxX(float,float,float,float,srid=0) → stbox`

  `stboxZ(float,float,float,float,float,float,srid=0) → stbox`

  `stboxT({timestamptz,tstzspan}) → stbox`

  `stboxXT(float,float,float,float,{timestamptz,tstzspan},srid=0) → stbox`

  `stboxZT(float,float,float,float,float,float,{timestamptz,tstzspan},srid=0) → stbox`

  `geodstboxZ(float,float,float,float,float,float,srid=4326) → stbox`

  `geodstboxT({timestamptz,tstzspan}) → stbox`

  `geodstboxZT(float,float,float,float,float,float,{timestamptz,tstzspan},srid=4326)`

  `→ stbox`

  `stbox(geo) → stbox`

  `stbox(geo,{timestamptz,tstzspan}) → stbox`

      -- Sólo dimensión de valores con coordenadas X e Y
      SELECT stboxX(1.0,2.0,1.0,2.0);
      -- Sólo dimensión de valores con coordenadas X, Y y Z
      SELECT stboxZ(1.0,2.0,3.0,1.0,2.0,3.0);
      -- Sólo dimensión de valores con coordenadas X, Y y Z con SRID
      SELECT stboxZ(1.0,2.0,3.0,1.0,2.0,3.0,5676);
      -- Sólo dimensión de tiempo
      SELECT stboxT(tstzspan '[2001-01-03,2001-01-03]');
      -- Dimensiones de valor (con coordenadas X e Y) y de tiempo
      SELECT stboxXT(1.0,2.0, 1.0,2.0, tstzspan '[2001-01-03,2001-01-03]');
      -- Dimensiones de valor (con coordenadas X, Y y Z) y de tiempo
      SELECT stboxZT(1.0,2.0,3.0, 1.0,2.0,3.0, tstzspan '[2001-01-03,2001-01-03]');
      -- Sólo dimensión de valores con coordenadas geodéticas X, Y y Z
      SELECT geodstboxZ(1.0,2.0,3.0,1.0,2.0,3.0);
      -- Sólo dimensión de tiempo para cuadro geodético
      SELECT geodstboxT(tstzspan '[2001-01-03,2001-01-03]');
      -- Dimensiones de valor (con coordenadas geodéticas X, Y y Z) y de tiempo
      SELECT geodstboxZT(1.0,2.0,3.0, 1.0,2.0,3.0, tstzspan '[2001-01-03,2001-01-04]');
      -- Geometry and time dimensión
      SELECT stbox(geometry 'Linestring(1 1 1,2 2 2)', tstzspan '[2001-01-03, 2001-01-05]');
      -- Geography and time dimensión
      SELECT stbox(geography 'Linestring(1 1 1,2 2 2)', tstzspan '[2001-01-03, 2001-01-05]');

## Conversiones de tipo

- Convertir un `tbox` a otro tipo

  `tbox::{intspan,floatspan,tstzspan}`

  `intspan(tbox) → tbox`

  `floatspan(tbox) → tbox`

  `tstzspan(tbox) → tbox`

      SELECT tbox 'TBOXINT XT([1,4),[2001-01-01,2001-01-02))'::intspan;
      -- [1,4)
      SELECT tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02))'::floatspan;
      -- (1, 2)
      SELECT tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02))'::tstzspan;
      -- [2001-01-01, 2001-01-02)

- Convertir otro tipo a un `tbox`

  `{numbers,times,tnumber}::tbox`

  `tbox({numbers,times,tnumber}) → tbox`

      SELECT intset '{1,2}'::tbox;
      -- TBOXINT X([1, 3))
      SELECT intspan '[1,3)'::tbox;
      -- TBOXINT X([1, 3))
      SELECT floatspan '(1.0,2.0)'::tbox;
      -- TBOXFLOAT X((1, 2))
      SELECT tstzspanset '{(2001-01-01,2001-01-02),(2001-01-03,2001-01-04)}'::tbox;
      -- TBOX T((2001-01-01,2001-01-04))

- Convertir un `stbox` a otro tipo

  `stbox::{box2d,box2d,geo,tstzspan}`

  `box2d(stbox) → box2d`

  `box3d(stbox) → box2d`

  `geometry(stbox) → geometry`

  `geography(stbox) → geography`

  `tstzspan(stbox) → tstzspan`

      SELECT stbox 'STBOX XT(((1.0,2.0),(3.0,4.0)),[2001-01-01,2001-01-03])'::box2d;
      -- BOX(1 2,3 4)
      SELECT ST_AsEWKT(stbox 'SRID=4326;STBOX XT(((1,1),(5,5)),[2001-01-01,2001-01-05])'::
        geometry);
      -- SRID=4326;POLYGON((1 1,1 5,5 5,5 1,1 1))
      SELECT ST_AsEWKT(stbox 'STBOX XT(((1,1),(1,5)),[2001-01-01,2001-01-05])'::geometry);
      -- LINESTRING(1 1,1 5)
      SELECT ST_AsEWKT(stbox 'GEODSTBOX XT(((1,1),(1,1)),[2001-01-01,2001-01-05])'::geography);
      -- SRID=4326;POINT(1 1)
      SELECT ST_AsEWKT(stbox 'STBOX ZT(((1,1,1),(5,5,5)),[2001-01-01,2001-01-05])'::
        geometry);
      /* POLYHEDRALSURFACE(((1 1 1,1 5 1,5 5 1,5 1 1,1 1 1)),
         ((1 1 5,5 1 5,5 5 5,1 5 5,1 1 5)),((1 1 1,1 1 5,1 5 5,1 5 1,1 1 1)),
         ((5 1 1,5 5 1,5 5 5,5 1 5,5 1 1)),((1 1 1,5 1 1,5 1 5,1 1 5,1 1 1)),
         ((1 5 1,1 5 5,5 5 5,5 5 1,1 5 1))) */
      SELECT stbox 'STBOX XT(((1.0,2.0),(3.0,4.0)),[2001-01-01,2001-01-03])'::tstzspan;
      -- [2001-01-01, 2001-01-03]

- Convertir otro tipo a un `stbox`

  `{box2d,box3d,geo,times,tpoint}::stbox`

  `stbox({box2d,box3d,geo,times,tpoint}) → stbox`

      SELECT geometry 'Linestring(1 1 1,2 2 2)'::box3d::stbox;
      -- STBOX Z((1,1,1),(2,2,2))
      SELECT geography 'Linestring(1 1,2 2)'::stbox;
      -- SRID=4326;GEODSTBOX X((1,1),(2,2))
      SELECT tstzspanset '{(2001-01-01,2001-01-02),(2001-01-03,2001-01-04)}'::stbox;
      -- STBOX T((2001-01-01,2001-01-04))

## Accesores

- ¿Tiene dimensión X/Z/T?

  `hasX(box) → boolean`

  `hasZ(stbox) → boolean`

  `hasT(box) → boolean`

      SELECT hasX(tbox 'TBOX T([2001-01-01,2001-01-03))');
      -- false
      SELECT hasX(stbox 'STBOX X((1.0,2.0),(3.0,4.0))');
      -- true
      SELECT hasZ(stbox 'STBOX X((1.0,2.0),(3.0,4.0))');
      -- false
      SELECT hasT(tbox 'TBOXFLOAT XT((1.0,3.0),[2001-01-01,2001-01-03])');
      -- true
      SELECT hasT(stbox 'STBOX X((1.0,2.0),(3.0,4.0))');
      -- false

- ¿Es geodética?

  `isGeodetic(stbox) → boolean`

      SELECT isGeodetic(stbox 'GEODSTBOX Z((1.0,1.0,0.0),(3.0,3.0,1.0))');
      -- true
      SELECT isGeodetic(stbox 'STBOX XT(((1.0,2.0),(3.0,4.0)),[2001-01-01,2001-01-02])');
      -- false

- Devuelve el valor mínimo de X/Y/Z/T

  `xMin(box) → float`

  `yMin(stbox) → float`

  `zMin(stbox) → float`

  `tMin(box) → timestamptz`

      SELECT xMin(tbox 'TBOXFLOAT XT((1.0,3.0),[2001-01-01,2001-01-03))');
      -- 1
      SELECT yMin(stbox 'STBOX X((1.0,2.0),(3.0,4.0))');
      -- 2
      SELECT zMin(stbox 'STBOX Z((1.0,2.0,3.0),(4.0,5.0,6.0))');
      -- 3
      SELECT tMin(stbox 'GEODSTBOX T([2001-01-01,2001-01-03))');
      -- 2001-01-01

- Devuelve el valor máximo de X/Y/Z/T

  `xMax(box) → float`

  `yMax(stbox) → float`

  `zMax(stbox) → float`

  `tMax(box) → timestamptz`

      SELECT xMax(stbox 'STBOX X((1.0,2.0),(3.0,4.0))');
      -- 3
      SELECT yMax(stbox 'STBOX X((1.0,2.0),(3.0,4.0))');
      -- 4
      SELECT zMax(stbox 'STBOX Z((1.0,2.0,3.0),(4.0,5.0,6.0))');
      -- 6
      SELECT tMax(stbox 'GEODSTBOX T([2001-01-01,2001-01-03))');
      -- 2001-01-03

- Es el mínimo valor X/T inclusivo?

  `xMinInc(tbox) → bool`

  `tMinInc(box) → bool`

      SELECT xMinInc(tbox 'TBOXFLOAT XT((1.0,3.0),[2001-01-01,2001-01-03))');
      -- false
      SELECT tMinInc(stbox 'GEODSTBOX T([2001-01-01,2001-01-03))');
      -- true

- Es el máximo valor X/T inclusivo?

  `xMaxInc(tbox) → bool`

  `tMaxInc(box) → bool`

      SELECT xMaxInc(tbox 'TBOXFLOAT XT((1.0,3.0),[2001-01-01,2001-01-03))');
      -- false
      SELECT tMaxInc(stbox 'GEODSTBOX T([2001-01-01,2001-01-03))');
      -- true

- Área, volumen, perímetro

  `area(stbox, spheroid bool=true) → float`

  `volume(stbox) → float`

  `perimeter(stbox, spheroid bool=true) → float`

  Para cuadros geodésicos, el cálculo se realiza en el esferoide WGS 84 por defecto. Si el último argumento es falso, se utiliza un cálculo esférico más rápido. La función `volume` no acepta cuadros geodésicos.

      SELECT area(stbox 'STBOX XT(((1,1),(3,3)),[2001-01-01,2001-01-03))');
      -- 4
      SELECT volume(stbox 'STBOX ZT(((1,1,1),(3,3,3)),[2001-01-01,2001-01-03))');
      -- 8
      SELECT perimeter(stbox 'STBOX XT(((1,1),(3,3)),[2001-01-01,2001-01-03))');
      -- 8
      SELECT area(stbox 'GEODSTBOX XT(((1,1),(3,3)),[2001-01-01,2001-01-03))');
      -- 49209676328.36632
      SELECT perimeter(stbox 'GEODSTBOX XT(((1,1),(3,3)),[2001-01-01,2001-01-03))', false);
      -- 889221.9544681838

## Transformaciones

- Desplazar el rango de valores o el período del cuadro delimitador con un valor o intervalo

  `shiftValue(tbox,{integer,float}) → tbox`

  `shiftTime(box,interval) → box`

      SELECT shiftValue(tbox 'TBOXFLOAT XT([1.5, 2.5],[2001-01-01,2001-01-02])', 1.0);
      -- TBOXFLOAT XT([2.5, 3.5],[2001-01-01, 2001-01-02])
      SELECT shiftTime(tbox 'TBOXFLOAT XT([1.5, 2.5],[2001-01-01,2001-01-02])',
        interval '1 day');
      -- TBOXFLOAT XT([1.5, 2.5],[2001-01-02, 2001-01-03])
      SELECT shiftTime(stbox 'STBOX T([2001-01-01,2001-01-02])', interval '-1 day');
      -- STBOX T([2001-12-31, 2001-01-01])
      SELECT shiftTime(stbox 'STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01,2001-01-02])',
        interval '1 day');
      -- STBOX ZT(((1,1,1),(2,2,2)),[2001-01-02, 2001-01-03])

- Escalar el rango de valores o el período del cuadro delimitador a un valor o intervalo. Si el ancho o el lapso de tiempo del valor de tiempo es cero (es decir, los límites inferior y superior son iguales), el resultado es el cuadro delimitador. El valor o intervalo dado debe ser estrictamente mayor que cero.

  `scaleValue(tbox,{integer,float}) → tbox`

  `scaleTime(box,interval) → box`

      SELECT scaleValue(tbox 'TBOXFLOAT XT([1.5, 2.5],[2001-01-01,2001-01-02])', 2.0);
      -- TBOXFLOAT XT([1.5, 3.5],[2001-01-01, 2001-01-02])
      SELECT scaleTime(tbox 'TBOXFLOAT XT([1.5, 2.5],[2001-01-01,2001-01-02])',
        interval '2 days');
      -- TBOXFLOAT XT([1.5, 2.5],[2001-01-01, 2001-01-03])
      SELECT scaleTime(stbox 'STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01,2001-01-02])',
        interval '1 hour');
      -- STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01 00:00:00, 2001-01-01 01:00:00])
      SELECT scaleTime(stbox 'STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01,2001-01-02])',
        interval '-1 day');
      -- ERROR:  The interval must be positive: -1 days

- Desplazar y escalar el rango de valores o el período del cuadro delimitador con los valores o intervalos

  `shiftScaleValue(tbox,{integer,float},{integer,float}) → tbox`

  `shiftScaleTime(box,interval,interval) → box`

  Estas funciones combinan las funciones `shiftValue` y `scaleValue` o `shiftTime` y `scaleTime`

      SELECT shiftScaleValue(tbox 'TBOXFLOAT XT([1.5, 2.5],[2001-01-01,2001-01-02])', 2.0, 3.0);
      -- TBOXFLOAT XT([3.5, 6.5],[2001-01-01, 2001-01-02])
      SELECT shiftScaleTime(tbox 'TBOXFLOAT XT([1.5, 2.5],[2001-01-01,2001-01-02])',
        interval '1 day', interval '3 days');
      -- TBOXFLOAT XT([1.5, 2.5],[2001-01-02, 2001-01-05])
      SELECT shiftScaleTime(stbox 'STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01,2001-01-02])',
        interval '1 hour', interval '3 hours');
      -- STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01 01:00:00, 2001-01-01 04:00:00])

- Devuelve la dimensión espacial del cuadro delimitador, eliminando la dimensión temporal, si existe

  `getSpace(stbox) → stbox`

      SELECT getSpace(stbox 'STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01,2001-01-03])');
      -- STBOX Z((1,1,1),(2,2,2))

Las funciones dadas a continuación expanden los cuadros delimitadores en la dimensión de valor y de tiempo o establecen la precisión de la dimensión de valor. Estas funciones generan un error si la dimensión correspondiente no está presente.

- Extender la dimensión numérica del cuadro delimitador con un valor flotante

  `expandValue(tbox,{integer,float}) → tbox`

      SELECT expandValue(tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-03])', 1.0);
      -- TBOXFLOAT XT((0,3),[2001-01-01, 2001-01-03])
      SELECT expandValue(tbox 'TBOX T([2001-01-01,2001-01-03))', 1);
      -- The box must have value dimension

- Extender la dimensión espacial del cuadro delimitador con un valor flotante

  `expandSpace(stbox,float) → stbox`

      SELECT expandSpace(stbox 'STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01,2001-01-03])', 1);
      -- STBOX ZT(((0,0,0),(3,3,3)),[2001-01-01, 2001-01-03])
      SELECT expandSpace(stbox 'STBOX T([2001-01-01,2001-01-03))', 1);
      -- The box must have space dimension

- Extender la dimensión temporal del cuadro delimitador con un intervalo de tiempo

  `expandTime(box,interval) → box`

      SELECT expandTime(tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-03])', interval '1 day');
      -- TBOXFLOAT XT((1,2),[2011-12-31, 2001-01-04])
      SELECT expandTime(stbox 'STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01,2001-01-03])',
        interval '1 day');
      -- STBOX ZT(((1,1,1),(2,2,2)),[2011-12-31, 2001-01-04])

- Redondear el valor o las coordenadas del cuadro delimitador a un número de decimales

  `round(box,integer=0) → box`

      SELECT round(tbox 'TBOXFLOAT XT((1.12345,2.12345),[2001-01-01,2001-01-02])', 2);
      -- TBOXFLOAT XT((1.12, 2.12),[2001-01-01,2001-01-02])
      SELECT round(stbox 'STBOX XT(((1.12345,1.12345),(2.12345,2.12345)),
        [2001-01-01,2001-01-02])', 2);
      -- STBOX XT(((1.12,1.12),(2.12,2.12)),[2001-01-01,2001-01-02])

## Sistema de referencia espacial

- Devuelve el identificador de referencia espacial

  `SRID(stbox) → integer`

      SELECT SRID(stbox 'STBOX ZT(((1.0,2.0,3.0),(4.0,5.0,6.0)),[2001-01-01,2001-01-02])');
      -- 0
      SELECT SRID(stbox 'SRID=5676;STBOX XT(((1.0,2.0),(4.0,5.0)),[2001-01-01,2001-01-02])');
      -- 5676
      SELECT SRID(stbox 'GEODSTBOX T([2001-01-01,2001-01-02))');
      -- ERROR:  The box must have space dimension

- Especificar el identificador de referencia espacial

  `setSRID(stbox) → stbox`

      SELECT setSRID(stbox 'STBOX ZT(((1.0,2.0,3.0),(4.0,5.0,6.0)),
        [2001-01-01,2001-01-02])', 5676);
      -- SRID=5676;STBOX ZT(((1,2,3),(4,5,6)),[2001-01-01,2001-01-02])

- Transformar a una referencia espacial diferente

  `transform(stbox,to_srid integer) → stbox`

  `transform(stbox,pipeline text,to_srid integer,is_forward bool=true) → stbox`

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

  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 del cuadro de entrada se ignora y el SRID del cuadro 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 round(transform(stbox 'SRID=4326;STBOX XT(((2.340088, 49.400250),
        (6.575317, 51.553167)),[2001-01-01,2001-01-02])', 3812), 6);
      /* SRID=3812;STBOX XT(((502773.429981,511805.120402),(803028.908265,751590.742629)),
        [2001-01-01, 2001-01-02]) */

      WITH test(box, pipeline) AS (
        SELECT stbox 'SRID=4326;GEODSTBOX Z((-0.1275,50.846667,100),(4.3525,51.507222,100))',
          text 'urn:ogc:def:coordinateOperation:EPSG::16031' )
      SELECT asEWKT(transformPipeline(transformPipeline(box, pipeline, 4326),
        pipeline, 4326, false), 6)
      FROM test;
      -- SRID=4326;GEODSTBOX Z((-0.1275,50.846667,100),(4.3525,51.507222,100))

## Funciones de división

- Dividir el cuadro delimitador en cuadrantes u octantes &SRF;

  `quadSplit(stbox) → {stbox}`

  Como lo indica el símbolo &SRF;, esta función es una función de retorno de conjuntos (también conocida como función de tabla) ya que normalmente devuelve más de un valor.

      SELECT quadSplit(stbox 'STBOX XT(((0,0),(4,4)),[2001-01-01,2001-01-05])');
      /* {"STBOX XT(((0,0),(2,2)),[2001-01-01, 2001-01-05])",
         "STBOX XT(((2,0),(4,2)),[2001-01-01, 2001-01-05])",
         "STBOX XT(((0,2),(2,4)),[2001-01-01, 2001-01-05])",
         "STBOX XT(((2,2),(4,4)),[2001-01-01, 2001-01-05])"} */
      SELECT quadSplit(stbox 'STBOX Z((0,0,0),(4,4,4))');
      /* {"STBOX Z((0,0,0),(2,2,2))","STBOX Z((2,0,0),(4,2,2))","STBOX Z((0,2,0),(2,4,2))",
         "STBOX Z((2,2,0),(4,4,2))","STBOX Z((0,0,2),(2,2,4))","STBOX Z((2,0,2),(4,2,4))",
         "STBOX Z((0,2,2),(2,4,4))","STBOX Z((2,2,2),(4,4,4))"} */

Tenga en cuenta que la función anterior es una función de retorno de conjuntos (también conocida como función de tabla) ya que normalmente devuelve más de un valor. Por lo tanto, la función está marcada con el símbolo &SRF;. Esta función se usa normalmente para cuadrículas de resolución múltiple, donde el espacio se divide en celdas de modo que las celdas tengan un número máximo de elementos. berlinmod_grid muestra un ejemplo del resultado de usar esta función usando trayectorias sintéticas en Bruselas.

### Grilla multiresolución sobre datos de Bruselas obtenidos mediante el generador BerlinMOD. Cada celda contiene como máximo 10.000 (izquierda) y 1.000 (derecha) instantes durante todo el período de simulación (cuatro días en este caso). A la izquierda, podemos ver la alta densidad de tráfico en el anillo alrededor de Bruselas, mientras que a la derecha podemos ver otros ejes principales de la ciudad.

## Operaciones de conjuntos

Los operadores de conjuntos para los tipos de cuadro delimitador son la unión (`+`) y la intersección (`*`). En el caso de la unión, los operandos deben tener exactamente las mismas dimensiónes, de lo contrario se genera un error. Además, si los operandos no se superponen en todas las dimensiónes se genera un error, ya que esto daría como resultado una caja con valores disjuntos, que no se puede representar. El operador calcula la unión en todas las dimensiónes que están presentes en ambos argumentos. En el caso de intersección, los operandos deben tener al menos una dimensión común, de lo contrario se genera un error. El operador calcula la intersección en todas las dimensiónes que están presentes en ambos argumentos.

- Unión de los cuadros delimitadores

  `box + box → box`

      SELECT tbox 'TBOXINT XT([1,3),[2001-01-01,2001-01-03])' +
        tbox 'TBOXINT XT([2,4),[2001-01-02,2001-01-04])';
      -- TBOXINT XT([1,4),[2001-01-01, 2001-01-04])
      SELECT stbox 'STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01,2001-01-02])' +
        stbox 'STBOX XT(((2,2),(3,3)),[2001-01-01,2001-01-03])';
      -- ERROR:  The arguments must be of the same dimensionality
      SELECT tbox 'TBOXFLOAT XT((1,3),[2001-01-01,2001-01-02])' +
        tbox 'TBOXFLOAT XT((3,4),[2001-01-03,2001-01-04])';
      -- ERROR:  Result of box union would not be contiguous

- Intersección de los cuadros delimitadores

  `box * box → box`

      SELECT tbox 'TBOXINT XT([1,3),[2001-01-01,2001-01-03])' *
        tbox 'TBOX T([2001-01-02,2001-01-04))';
      -- TBOX T([2001-01-02,2001-01-03))
      SELECT stbox 'STBOX ZT(((1,1,1),(3,3,3)),[2001-01-01,2001-01-02])' *
        stbox 'STBOX X((2,2),(4,4))';
      -- STBOX X((2,2),(3,3))

## Operaciones de cuadro delimitador

### Operaciones topológicas

Hay cinco operadores topológicos: superposición (`&&`), contiene (`@>`), es contenido (`<@`), mismo (`~=`) y adyacente (`-|-`). Los operadores verifican la relación topológica entre los cuadros delimitadores teniendo en cuenta la dimensión de valor y/o de tiempo para todas las dimensiónes que estén presentes en ambos argumentos.

- ¿Se superponen los cuadros delimitadores?

  `box && box → boolean`

      SELECT tbox 'TBOXFLOAT XT((1,3),[2001-01-01,2001-01-03])' &&
        tbox 'TBOXFLOAT XT((2,4),[2001-01-02,2001-01-04])';
      -- true
      SELECT stbox 'STBOX XT(((1,1),(2,2)),[2001-01-01,2001-01-02])' &&
        stbox 'STBOX XT([2001-01-02,2001-01-02])';
      -- true

- ¿Contiene el primer cuadro delimitador el segundo?

  `box @> box → boolean`

      SELECT tbox 'TBOXFLOAT XT((1,4),[2001-01-01,2001-01-04])' @>
        tbox 'TBOXFLOAT XT((2,3),[2001-01-01,2001-01-02])';
      -- true
      SELECT stbox 'STBOX Z((1,1,1),(3,3,3))' @>
        stbox 'STBOX XT(((1,1),(2,2)),[2001-01-01,2001-01-02])';
      -- true

- ¿Está el primer cuadro delimitador contenido en el segundo?

  `box <@ box → boolean`

      SELECT tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02])' <@
        tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02])';
      -- true
      SELECT stbox 'STBOX XT(((1,1),(2,2)),[2001-01-01,2001-01-02)' <@
        stbox 'STBOX ZT(((1,1,1),(2,2,2)),[2001-01-01,2001-01-02])';
      -- true

- ¿Son los cuadros delimitadores iguales en sus dimensiónes comunes?

  `box ~= box → boolean`

      SELECT tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02])' ~=
        tbox 'TBOXFLOAT XT([2001-01-01,2001-01-02])';
      -- true
      SELECT stbox 'STBOX XT(((1,1),(3,3)),[2001-01-01,2001-01-03])' ~=
        stbox 'STBOX Z((1,1,1),(3,3,3))';
      -- true

- ¿Son los cuadros delimitadores adyacentes?

  `box -|- box → boolean`

  Dos cuadros delimitadores son adyacentes si comparten n dimensiónes y si su intersección tiene como máximo n-1 dimensiónes.

      SELECT tbox 'TBOXINT XT([1,2),[2001-01-01,2001-01-02])' -|-
        tbox 'TBOXINT XT([2,3),[2001-01-02,2001-01-03])';
      -- true
      SELECT tbox 'TBOXFLOAT XT((1,2)[2001-01-01,2001-01-02])' -|-
        tbox 'TBOX T([2001-01-02,2001-01-03])';
      -- true
      SELECT stbox 'STBOX XT(((1,1),(3,3)),[2001-01-01,2001-01-03])' -|-
        stbox 'STBOX XT(((2,2),(4,4)),[2001-01-03,2001-01-04])';
      -- true

### Operaciones de posición

Los operadores de posición consideran la posición relativa de los cuadros delimitadores. Los operadores `<<`, `>>`, `&<` y `&>` consideran el valor X para el tipo `tbox` y las coordenadas X para el tipo `stbox`, los operadores `<<|`, `|>>`, `&<|` y `|&>` consideran las coordenadas Y para el tipo `stbox`, los operadores `<</`, `/>>`, `&</` y `/&>` consideran las coordenadas Z para el tipo `stbox` y los operadores `<<#`, `#>>`, `#&<` y `#&>` consideran la dimensión de tiempo para los tipos `tbox` y `stbox`. Los operadores generan un error si ambos cuadros delimitadores no tienen la dimensión requerida.

Los operadores para la dimensión numérica del tipo `tbox` se dan a continuación.

- ¿Son los valores X/Y/Z/T del primer cuadro delimitador estrictamente menores que los del segundo?

  `box << box → boolean`

  `stbox <<| stbox → boolean`

  `stbox <</ stbox → boolean`

  `box <<# box → boolean`

      SELECT tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02])' <<
        tbox 'TBOXFLOAT XT((3,4),[2001-01-03,2001-01-04])';
      -- true
      SELECT tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02])' <<
        tbox 'TBOXFLOAT XT([2001-01-03,2001-01-04])';
      -- ERROR:  The box must have value dimension
      SELECT stbox 'STBOX Z((1,1,1),(2,2,2))' << stbox 'STBOX Z((3,3,3),(4,4,4))';
      -- true
      SELECT stbox 'STBOX Z((1,1,1),(2,2,2))' <<| stbox 'STBOX Z((3,3,3),(4,4,4))';
      -- true
      SELECT stbox 'STBOX Z((1,1,1),(2,2,2))' <</ stbox 'STBOX Z((3,3,3),(4,4,4))';
      -- true
      SELECT tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02])' <<#
        tbox 'TBOXFLOAT XT((3,4),[2001-01-03,2001-01-04])';
      -- true

- ¿Son los valores X/Y/Z/T del primer cuadro delimitador estrictamente mayores que los del segundo?

  `box >> box → boolean`

  `stbox |>> stbox → boolean`

  `stbox />> stbox → boolean`

  `box #>> box → boolean`

      SELECT tbox 'TBOXFLOAT XT((3,4),[2001-01-03,2001-01-04])' >>
        tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02])';
      -- true
      SELECT stbox 'STBOX Z((3,3,3),(4,4,4))' >> stbox 'STBOX Z((1,1,1),(2,2,2))';
      -- true
      SELECT stbox 'STBOX Z((3,3,3),(4,4,4))' |>> stbox 'STBOX Z((1,1,1),(2,2,2))';
      -- true
      SELECT stbox 'STBOX Z((3,3,3),(4,4,4))' />> stbox 'STBOX Z((1,1,1),(2,2,2))';
      -- true
      SELECT stbox 'STBOX XT((4,4),[2001-01-03,2001-01-04],((3,3)))'  #>>
        stbox 'STBOX XT(((1,1),(2,2)),[2001-01-01,2001-01-02])';
      -- true

- ¿No son los valores X/Y/Z/T del primer cuadro delimitador mayores que los del segundo?

  `box &< box → boolean`

  `stbox &<| stbox → boolean`

  `stbox &</ stbox → boolean`

  `box &<# box → boolean`

      SELECT tbox 'TBOXFLOAT XT((1,4),[2001-01-01,2001-01-04])' &<
        tbox 'TBOXFLOAT XT((3,4),[2001-01-03,2001-01-04])';
      -- true
      SELECT stbox 'STBOX Z((1,1,1),(4,4,4))' &< stbox 'STBOX Z((3,3,3),(4,4,4))';
      -- true
      SELECT stbox 'STBOX Z((1,1,1),(4,4,4))' &<| stbox 'STBOX Z((3,3,3),(4,4,4))';
      -- true
      SELECT stbox 'STBOX Z((1,1,1),(4,4,4))' &</ stbox 'STBOX Z((3,3,3),(4,4,4))';
      -- true
      SELECT tbox 'TBOXFLOAT XT((1,4),[2001-01-01,2001-01-04])' &<#
        tbox 'TBOXFLOAT XT((3,4),[2001-01-03,2001-01-04])';
      -- true

- ¿No son los valores X/Y/Z/T del primer cuadro delimitador menores que los del segundo?

  `box &> box → boolean`

  `stbox |&> stbox → boolean`

  `stbox /&> stbox → boolean`

  `box #&> box → boolean`

      SELECT tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-02])' &>
        tbox 'TBOXFLOAT XT((1,4),[2001-01-01,2001-01-04])';
      -- true
      SELECT stbox 'STBOX Z((3,3,3),(4,4,4))' &> stbox 'STBOX Z((1,1,1),(2,2,2))';
      -- true
      SELECT stbox 'STBOX Z((3,3,3),(4,4,4))' |&> stbox 'STBOX Z((1,1,1),(2,2,2))';
      -- false
      SELECT stbox 'STBOX Z((3,3,3),(4,4,4))' /&> stbox 'STBOX Z((1,1,1),(2,2,2))';
      -- true
      SELECT stbox 'STBOX XT(((1,1),(2,2)),[2001-01-01,2001-01-02])' #&>
        stbox 'STBOX XT(((1,1),(4,4)),[2001-01-01,2001-01-04])';
      -- true

## Comparaciones

Los operadores de comparación tradicionales (`=`, `<`, etc.) se pueden aplicar a tipos de cuadro delimitador. Exceptuando la igualdad y la no igualdad, los otros operadores de comparación no son útiles en el mundo real pero permiten construir índices de árbol B en tipos de cuadro delimitador. Estos operadores comparan primero los valores de tiempo y, si son iguales, comparan los valores.

- ¿Son iguales los cuadros delimitadores?

  `box = box → boolean`

      SELECT tbox 'TBOXINT XT([1,1],[2001-01-01,2001-01-04])' =
        tbox 'TBOXINT XT([2,2],[2001-01-03,2001-01-05])';
      -- false

- ¿Son diferentes los cuadros delimitadores?

  `box <> box → boolean`

      SELECT tbox 'TBOXFLOAT XT([1,1],[2001-01-01,2001-01-04])' <>
        tbox 'TBOXFLOAT XT([2,2],[2001-01-03,2001-01-05])';
      -- true

- ¿Es el primer cuadro delimitador menor que el segundo?

  `box < box → boolean`

      SELECT tbox 'TBOXINT XT([1,1],[2001-01-01,2001-01-04])' <
        tbox 'TBOXINT XT([1,2],[2001-01-03,2001-01-05])';
      -- true

- ¿Es el primer cuadro delimitador mayor que el segundo?

  `box > box → boolean`

      SELECT tbox 'TBOXFLOAT XT([1,1],[2001-01-03,2001-01-04])' >
        tbox 'TBOXFLOAT XT((1,2),[2001-01-01,2001-01-05])';
      -- true

- ¿Es el primer cuadro delimitador menor o igual que el segundo?

  `box <= box → boolean`

      SELECT tbox 'TBOXINT XT([1,1],[2001-01-01,2001-01-04])' <=
        tbox 'TBOXINT XT([2,2],[2001-01-03,2001-01-05])';
      -- true

- ¿Es el primer cuadro delimitador mayor o igual que el segundo?

  `box >= box → boolean`

      SELECT tbox 'TBOXFLOAT XT([1,1],[2001-01-01,2001-01-04])' >=
        tbox 'TBOXFLOAT XT([2,2],[2001-01-03,2001-01-05])';
      -- false

## Aggregaciones

- Extensión del cuadro delimitador

  `extent(box) → box`

      WITH boxes(b) AS (
        SELECT tbox 'TBOXFLOAT XT((1,3),[2001-01-01,2001-01-03])' UNION
        SELECT tbox 'TBOXFLOAT XT((5,7),[2001-01-05,2001-01-07])' UNION
        SELECT tbox 'TBOXFLOAT XT((6,8),[2001-01-06,2001-01-08])'
      )
      SELECT extent(b) FROM boxes;
      -- TBOXFLOAT XT((1,8),[2001-01-01,2001-01-08])
      WITH boxes(b) AS (
        SELECT stbox 'STBOX Z((1,1,1),(3,3,3))' UNION
        SELECT stbox 'STBOX Z((5,5,5),(7,7,7))' UNION
        SELECT stbox 'STBOX Z((6,6,6),(8,8,8))'
      )
      SELECT extent(b) FROM boxes;
      -- STBOX Z((1,1,1),(8,8,8))

## Indexación

Se pueden crear índices GiST y SP-GiST para columnas de tablas de los tipos `tbox` y `stbox`. El índice GiST implementa un árbol R, mientras que el índice SP-GiST implementa un árbol cuádruple n-dimensiónal. Un ejemplo de creación de un índice GiST en una columna `Box` de tipo `stbox` en una tabla `Trips` es el siguiente:

    CREATE TABLE Trips(TripID integer PRIMARY KEY, Trip tgeompoint, Box stbox);
    CREATE INDEX Trips_Box_Idx ON Trips USING GIST(Box);

Un índice GiST o SP-GiST puede acelerar las consultas que involucran a los siguientes operadores: `&&`, `<@`, `@>`, `~=`, `-|-`, `<<`, `>>`, `&<`, `&>`, `<<|`, `|>>`, `&<|`, `|&>`, `<</`, `/>>`, `&</`, `/&>`, `<<#`, `#>>`, `&<#` y `#&>`.

Además, se pueden crear índices de árbol B para columnas de tablas de un tipo cuadro delimitador. Para estos tipos de índices, básicamente la única operación útil es la igualdad. Hay un orden de clasificación de árbol B definido para valores de tipos cuadro delimitador con los correspondientes operadores `<` y `>`, pero el orden es bastante arbitrario y no suele ser útil en el mundo real. El soporte de árbol B está destinado principalmente a permitir la clasificación interna en las consultas, en lugar de la creación de índices reales.