Parches de nube de puntos temporales

Un tpcpatch es la elevación temporal de pcpatch. Es el espejo de tpcpoint en todos los aspectos, mismos subtipos, mismas funciones de acceso, mismas conversiones y operadores, excepto que cada instante contiene un lote comprimido completo de puntos en lugar de un único punto. La caja delimitadora es de nuevo un tpcbox, calculada en O(1) por instante a partir del PCBOUNDS embebido en el parche.

Las operaciones sobre un tpcpatch se realizan a dos granularidades, porque los puntos de un parche residen en una carga comprimida que la capa de caja delimitadora no puede inspeccionar. A nivel de parche el parche de cada instante se conserva o se descarta como un todo, leyendo únicamente su cabecera PCBOUNDS de cuatro valores double (xmin / xmax / ymin / ymax) y la marca de tiempo del instante: esta es la granularidad de atTpcbox / minusTpcbox, de los operadores de caja delimitadora y del agregado extent, no descomprime ninguna carga y cuesta O(número de instantes). Como PCBOUNDS es 2D, la dimensión Z de un argumento tpcbox se ignora a esa granularidad, incluso cuando el esquema tiene una.

A nivel de punto se recorre en C cada punto de cada instante. points emite una fila por cada marca de tiempo de instante y punto, mientras que atTpcboxFine / minusTpcboxFine, atGeometry / minusGeometry y eIntersects(tpcpatch,geometry) aplican su predicado a las coordenadas reales y reconstruyen cada instante superviviente con los puntos que lo superaron, descartando los instantes que no conservan ninguno. Pode primero a nivel de parche, con atTpcbox o un escaneo de índice GiST / SP-GiST, y refine los supervivientes cuando se necesite fidelidad a nivel de punto.

Entrada y salida

  • Devuelve la representación textual de un tpcpatch, o de un arreglo de ellos, con o sin su SRID, y convertir un tpcpatch a texto

    asText(tpcpatch) → text
    asText(tpcpatch[]) → text[]
    asEWKT(tpcpatch) → text
    asEWKT(tpcpatch[]) → text[]
    tpcpatch::text → text
    

    Como para un tpcpoint, asEWKT antepone el SRID que declara el esquema del pcid, y escribe solo la forma textual bajo un esquema que no declara ninguno.

    -- The pcpatch payload renders as hex-encoded WKB.
    SELECT left(asText(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz)), 24);
    -- EC0100000100000000000000
    SELECT left(asEWKT(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz)), 24);
    -- EC0100000100000000000000
    
  • Devuelve la representación binaria o binaria bien conocida hexadecimal de un tpcpatch, con o sin su SRID

    asBinary(tpcpatch,endian text='') → bytea
    asEWKB(tpcpatch,endian text='') → bytea
    asHexWKB(tpcpatch,endian text='') → text
    asHexEWKB(tpcpatch,endian text='') → text
    
    SELECT tpcpatchFromHexEWKB(asHexEWKB(t)) = t
    FROM (SELECT tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)),
      '2001-01-01'::timestamptz) AS t) s;
    -- t
    
  • Devuelve un tpcpatch a partir de su representación textual, binaria o binaria bien conocida hexadecimal, con o sin su SRID

    tpcpatchFromText(text) → tpcpatch
    tpcpatchFromEWKT(text) → tpcpatch
    tpcpatchFromBinary(bytea) → tpcpatch
    tpcpatchFromEWKB(bytea) → tpcpatch
    tpcpatchFromHexWKB(text) → tpcpatch
    tpcpatchFromHexEWKB(text) → tpcpatch
    

    El pcid que lleva cada parche nombra su esquema, por lo que la forma textual se lee de vuelta como la binaria, y un SRID indicado por la entrada debe ser el que declara ese esquema.

    SELECT tpcpatchFromText(asText(t)) = t
    FROM (SELECT tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)),
      '2001-01-01'::timestamptz) AS t) s;
    -- t
    SELECT tpcpatchFromEWKT('SRID=4326;' || asText(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz)));
    -- ERROR:  The SRID of a pcpatch is the one its schema declares and cannot be set
    
  • Devuelve la representación JSON de características móviles (MF-JSON)

    asMFJSON(tpcpatch,options int=0,flags int=0,maxdecimaldigits int=15) → text
    

    Un tpcpatch se emite bajo la etiqueta de tipo "MovingPCPatch", y cada instante indica el objeto {"pcid":N, "npoints":N, "bounds":[xmin,xmax,ymin,ymax]}; la carga de puntos comprimida queda fuera del JSON, por lo que un ida y vuelta sin pérdida pasa por asBinary o asHexWKB.

    SELECT asMFJSON(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz));
    /* {"type":"MovingPCPatch","values":[{"pcid":1,"npoints":2,"bounds":[1,2,1,2]}],
       "datetimes":["2001-01-01T00:00:00"],"interpolation":"None"} */
    

Como para un tpcpoint, asText no toma un argumento maxdecimaldigits. MF-JSON es solo de salida, y su resumen por instante descarta la carga por punto.

Constructores

  • Construye un pcpatch temporal de subtipo instante

    tpcpatch(pcpatch,timestamptz) → tpcpatch
    
    SELECT tempSubtype(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz));
    -- Instant
    
  • Construye un pcpatch temporal de subtipo secuencia

    tpcpatchSeq(tpcpatch[]) → tpcpatch
    tpcpatchSeq(tpcpatch[],text) → tpcpatch
    
    SELECT numInstants(tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)])), interp(tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)]));
    -- 2 | Step
    
  • Construye un pcpatch temporal de subtipo conjunto de secuencias

    tpcpatchSeqSet(tpcpatch[]) → tpcpatch
    
    SELECT numSequences(tpcpatchSeqSet(ARRAY[tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3),
      pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz)])]));
    -- 1
    

Conversiones

  • Convierte un parche temporal en la geometría temporal de los multipuntos que ocupan sus parches

    tgeometry(tpcpatch) → tgeometry
    

    El parche de cada instante se convierte en el multipunto de las posiciones que ocupan sus puntos, leídas a través del esquema que nombra su pcid

    SELECT asText(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz)::tgeometry);
    -- MULTIPOINT Z ((1 1 1),(2 2 2))@2001-01-01
    

Accesores

  • Devuelve el número de puntos del parche contenido en el primer o último instante

    startNumPoints(tpcpatch) → integer
    endNumPoints(tpcpatch) → integer
    
    SELECT startNumPoints(tpcpatch(pcpatch(pcpoint(1, 10.0, 20.0, 30.0)),
      '2024-02-01'::timestamptz));
    -- 1
    
  • Devuelve el número total de puntos de todos los parches de todos los instantes

    numPoints(tpcpatch) → bigint
    

    Se lee directamente de la cabecera de cada parche, sin descompresión.

    SELECT numPoints(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1.0, 1.0, 1.0),
      pcpoint(1, 2.0, 2.0, 2.0)), '2024-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3.0, 3.0, 3.0)), '2024-01-02'::timestamptz)]));
    -- 3
    
  • Emite una fila por cada marca de tiempo de instante y punto del parche

    points(tpcpatch) → setof (t timestamptz,point pcpoint)
    

    Recorre el parche de cada instante y lo descompone mediante la API C en memoria de pgPointCloud. Útil para combinar una columna tpcpatch con predicados por punto que los operadores de nivel de caja delimitadora no pueden expresar. El coste es O(total de puntos), una descompresión por instante más una emisión de fila por punto.

    SELECT t,
      point FROM points(tpcpatch(pcpatch(pcpoint(1, 1.0, 1.0, 1.0),
      pcpoint(1, 2.0, 2.0, 2.0)), '2024-01-01'::timestamptz));
    -- ('2024-01-01',
    -- '01:0000000000000000000000F03F0000000000000000F03F00000000000000F03F'::pcpoint)
    -- ('2024-01-01',
    -- '01:0000000000000000000000004000000000000000400000000000000040'::pcpoint)
    

Transformaciones

  • Transforma un tpcpatch en otro subtipo

    tpcpatchInst(tpcpatch) → tpcpatch
    tpcpatchSeq(tpcpatch,interp text='step') → tpcpatch
    tpcpatchSeqSet(tpcpatch) → tpcpatch
    
    SELECT tempSubtype(tpcpatchSeq(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz)));
    -- Sequence
    
  • Transforma un tpcpatch a otra interpolación

    setInterp(tpcpatch,interp) → tpcpatch
    
    SELECT interp(setInterp(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz)],
      'discrete'), 'step'));
    -- Step
    

Modificaciones

  • Inserta un tpcpatch en otro, o actualizar otro con él

    insert(tpcpatch,tpcpatch,connect boolean=true) → tpcpatch
    update(tpcpatch,tpcpatch,connect boolean=true) → tpcpatch
    
    SELECT numInstants(insert(tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)]), tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 5, 5, 5)), '2001-01-03'::timestamptz)])));
    -- 3
    
  • Elimina un selector de tiempo (marca de tiempo, conjunto, período o conjunto de spans) de un tpcpatch

    deleteTime(tpcpatch,time,connect boolean=true) → tpcpatch
    
    -- Deleting the middle instant splits the sequence into {[2001-01-01, 2001-01-02),
    -- (2001-01-02, 2001-01-03]}; each half stores its bound at the deleted timestamp, giving
    -- four instants.
    SELECT numInstants(deleteTime(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 5, 5, 5)), '2001-01-03'::timestamptz)]),
      timestamptz '2001-01-02'));
    -- 4
    
  • Añade un instante o una secuencia a un tpcpatch

    appendInstant(tpcpatch,tpcpatch) → tpcpatch
    appendSequence(tpcpatch,tpcpatch) → tpcpatch
    
    SELECT numInstants(appendInstant(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3),
      pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz)]),
      tpcpatch(pcpatch(pcpoint(1, 5, 5, 5)), '2001-01-03'::timestamptz)));
    -- 3
    

Restricciones

  • Restringe un tpcpatch a (al complemento de) un valor pcpatch o un conjunto de valores pcpatch

    atValue(tpcpatch,pcpatch) → tpcpatch
    minusValue(tpcpatch,pcpatch) → tpcpatch
    atValues(tpcpatch,pcpatchset) → tpcpatch
    minusValues(tpcpatch,pcpatchset) → tpcpatch
    
    -- The matching value is held up to the next instant; the closing bound is stored as a
    -- second instant.
    SELECT numInstants(atValue(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)]), pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2))));
    -- 2
    SELECT numInstants(minusValue(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)]), pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2))));
    -- 1
    
  • Restringe un tpcpatch a los instantes cuyo parche supera una prueba de superposición aproximada de PCBOUNDS frente al tpcbox, o eliminarlos

    atTpcbox(tpcpatch,tpcbox,border_inc boolean=true) → tpcpatch
    minusTpcbox(tpcpatch,tpcbox,border_inc boolean=true) → tpcpatch
    

    La granularidad es a nivel de parche: cada instante superviviente conserva su payload pcpatch textualmente, sin descompresión por punto. Como el PCBOUNDS de pgPointCloud es 2D, la dimensión Z de la caja se ignora a esta granularidad. Devuelve NULL cuando el pcid del tpcbox no coincide.

    SELECT numInstants(atTpcbox(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3),
      pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz)]),
      tpcboxXT(0, 0, 2, 2, tstzspan '[2001-01-01, 2001-01-03]', 1)));
    -- 1
    -- The dropped patch stays present on the open interval before its instant,
    -- so the complement keeps two instants.
    SELECT numInstants(minusTpcbox(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3),
      pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz)]),
      tpcboxXT(0, 0, 2, 2, tstzspan '[2001-01-01, 2001-01-03]', 1)));
    -- 2
    
  • Restringe un tpcpatch a los puntos de cada instante que contiene el tpcbox, o los elimina

    atTpcboxFine(tpcpatch,tpcbox,border_inc boolean=true) → tpcpatch
    minusTpcboxFine(tpcpatch,tpcbox,border_inc boolean=true) → tpcpatch
    

    Cada instante superviviente contiene un pcpatch recién construido que incluye solo los puntos dentro, o fuera en la forma minus, del tpcbox en dos dimensiones, y en tres cuando la caja tiene dimensión Z. Los instantes cuyo parche filtra hasta cero puntos se descartan. Más lenta que la variante aproximada porque cada parche se descomprime y reconstruye; úsela cuando se necesite fidelidad a nivel de punto.

    SELECT numInstants(atTpcboxFine(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3),
      pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz)]),
      tpcboxXT(0, 0, 1, 1, tstzspan '[2001-01-01, 2001-01-03]', 1)));
    -- 1
    
  • Restringe un tpcpatch a los puntos cuya proyección XY intersecta (o no intersecta, en el caso de minus) una geometría 2D

    atGeometry(tpcpatch,geometry) → tpcpatch
    minusGeometry(tpcpatch,geometry) → tpcpatch
    

    Z se ignora. El llamador debe garantizar la compatibilidad de SRID entre el esquema del parche y la geometría.

    -- The polygon boundary touches the point (3 3) of the patch at 2001-01-02, so that patch
    -- survives both the at and the minus side.
    SELECT numInstants(atGeometry(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)]), geometry 'POLYGON((0 0, 0 3, 3 3, 3 0, 0 0))'));
    -- 2
    SELECT numInstants(minusGeometry(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)]), geometry 'POLYGON((0 0, 0 3, 3 3, 3 0, 0 0))'));
    -- 1
    
  • Restringe un tpcpatch a los instantes anteriores o posteriores a una marca de tiempo

    beforeTimestamp(tpcpatch,timestamptz,strict boolean=true) → tpcpatch
    afterTimestamp(tpcpatch,timestamptz,strict boolean=true) → tpcpatch
    

    El indicador strict excluye el instante en la marca de tiempo misma

    SELECT timeSpan(beforeTimestamp(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 5, 5, 5)), '2001-01-03'::timestamptz)]),
      timestamptz '2001-01-02'));
    -- [2001-01-01, 2001-01-02)
    SELECT timeSpan(afterTimestamp(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 5, 5, 5)), '2001-01-03'::timestamptz)]),
      timestamptz '2001-01-02'));
    -- (2001-01-02, 2001-01-03]
    

Operaciones de división

  • Devuelve los valores distintos de un tpcpatch con el conjunto de spans durante el cual toma cada uno de ellos

    unnest(tpcpatch) → {(value,time)}
    
    SELECT (un).time FROM (SELECT unnest(tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)), '2024-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 5, 5, 5), pcpoint(1, 6, 6, 6)), '2024-01-02'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2024-01-03'::timestamptz)])) AS un) t;
    -- {[2024-01-02, 2024-01-03)}
    -- {[2024-01-01, 2024-01-02), [2024-01-03, 2024-01-03]}
    
  • Fragmenta un tpcpatch en fragmentos, uno por cada intervalo de tiempo

    timeSplit(tpcpatch,duration interval,
      origin timestamptz='2000-01-03') → {(time,tpcpatch)}
    
    SELECT (ts).time, numInstants((ts).temp) FROM (SELECT timeSplit(tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)), '2024-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 5, 5, 5), pcpoint(1, 6, 6, 6)), '2024-01-02'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)),
      '2024-01-03'::timestamptz)]),
      interval '1 day', '2024-01-01'::timestamptz) AS ts) t;
    -- 2024-01-01 | 2
    -- 2024-01-02 | 2
    -- 2024-01-03 | 1
    
  • Devuelve el arreglo de lapsos de tiempo de los segmentos de un tpcpatch

    spans(tpcpatch) → tstzspan[]
    
    SELECT spans(tpcpatchSeq(ARRAY[tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2024-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 5, 5, 5), pcpoint(1, 6, 6, 6)), '2024-01-02'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2024-01-03'::timestamptz)]));
    -- {"[2024-01-01, 2024-01-02]","[2024-01-02, 2024-01-03]"}
    
  • Devuelve los lapsos de tiempo de un tpcpatch dividido en un número dado de contenedores, o con un número dado de segmentos por contenedor

    splitNSpans(tpcpatch,integer) → tstzspan[]
    splitEachNSpans(tpcpatch,integer) → tstzspan[]
    
    SELECT splitNSpans(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2024-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 5, 5, 5), pcpoint(1, 6, 6, 6)), '2024-01-02'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2024-01-03'::timestamptz)]), 2);
    -- {"[2024-01-01, 2024-01-02]","[2024-01-02, 2024-01-03]"}
    

Operaciones de caja delimitadora

La misma superficie de operadores de caja que en “Operaciones de caja delimitadora” se aplica a tpcpatch. El predicado se evalúa sobre el tpcbox del valor, calculado en O(1) por instante a partir del PCBOUNDS embebido en el parche.

  • Operadores topológicos

    {tstzspan,tpcbox,tpcpatch} {&&, @>, <@, ~=, -|-} {tstzspan,tpcbox,tpcpatch} → boolean
    
    SELECT tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz)])
      && tstzspan '[2001-01-01, 2001-01-03]';
    -- true
    
  • Operadores de posición

    {tpcbox,tpcpatch} {<<, >>, <<|, |>>, <</, />>} {tpcbox,tpcpatch} → boolean
    {tstzspan,tpcbox,tpcpatch} {<<#, #>>} {tstzspan,tpcbox,tpcpatch} → boolean
    
    SELECT tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz)])
      <<# tstzspan '[2001-01-05, 2001-01-06]';
    -- true
    

Operaciones de distancia

  • Devuelve la distancia más cercana

    nearestApproachDistance(tpcpatch,{tpcbox,tpcpatch}) → float
    
    SELECT round(nearestApproachDistance(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 8, 8, 8), pcpoint(1, 9, 9, 9)),
      '2001-01-01'::timestamptz))::numeric, 4);
    -- 8.4853
    

Relaciones siempre y alguna vez

  • Devuelve verdadero si y solo si al menos un punto de alguno de los instantes del tpcpatch intersecta la geometría (solo XY)

    eIntersects(tpcpatch,geometry) → boolean
    

    Las relaciones alguna vez y siempre cubren la misma matriz: eContains, eCovers, eDisjoint, eIntersects, eTouches y eDwithin, cada una en los tres órdenes de argumentos, y sus gemelas siempre. eIntersects(tpcpatch,geometry) es la que el tipo responde de forma nativa, recorriendo los puntos de cada instante y deteniéndose en el primer acierto; las demás convierten el parche a la geometría temporal de sus multipuntos.

    SELECT eIntersects(tpcpatchSeq(ARRAY[ tpcpatch(pcpatch(pcpoint(1, 1, 1, 1),
      pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3),
      pcpoint(1, 4, 4, 4)), '2001-01-02'::timestamptz)]), geometry 'POINT(1 1)');
    -- t
    

Relaciones espaciotemporales

Las relaciones temporales calculan la relación topológica o de distancia en cada instante y dan como resultado un tbool. Un parche llega al motor de geometría a través de la conversión a tgeometry anterior, por lo que basta con que un punto del parche esté dentro del argumento para que el parche lo intersecte. Un tpcpatch lleva la Z que declara su esquema, y tContains, tCovers y tTouches son relaciones planas que rechazan una dimensión Z, de modo que el tipo responde las tres que un valor con Z puede responder.

  • Relaciones espaciotemporales

    tDisjoint({geometry,tpcpatch},{geometry,tpcpatch}) → tbool
    tDwithin({geometry,tpcpatch},{geometry,tpcpatch},float) → tbool
    tIntersects({geometry,tpcpatch},{geometry,tpcpatch}) → tbool
    tContains({geometry,tpcpatch},{geometry,tpcpatch}) → tbool
    tCovers({geometry,tpcpatch},{geometry,tpcpatch}) → tbool
    tTouches({geometry,tpcpatch},{geometry,tpcpatch}) → tbool
    

    Un parche llega al motor de geometría como el multipunto de las posiciones que ocupan sus puntos, de modo que declara la matriz que declara la geometría temporal: cada predicado en cada dirección. Las planares responden para un esquema cuyas dimensiones no incluyen Z, y un esquema que lleva Z encuentra el rechazo The tgeometry cannot have Z dimension.

    SELECT tIntersects(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 9, 9, 9)),
      '2001-01-01'::timestamptz), geometry 'Polygon((0 0,0 2,2 2,2 0,0 0))');
    -- t@2001-01-01
    SELECT tDisjoint(tpcpatch(pcpatch(pcpoint(1, 9, 9, 9)), '2001-01-02'::timestamptz),
      geometry 'Polygon((0 0,0 2,2 2,2 0,0 0))');
    -- t@2001-01-02
    SELECT tDwithin(tpcpatch(pcpatch(pcpoint(1, 1, 1, 1)), '2001-01-01'::timestamptz),
      geometry 'Point(1 5)', 2.0);
    -- f@2001-01-01
    SELECT tIntersects(tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 9, 9, 9)), '2001-01-02'::timestamptz)]),
      geometry 'Polygon((0 0,0 2,2 2,2 0,0 0))');
    -- [t@2001-01-01, f@2001-01-02]
    

Comparaciones

  • Comparaciones alguna vez y siempre

    {pcpatch,tpcpatch} {?=, %=, ?<>, %<>} {pcpatch,tpcpatch} → boolean
    
    SELECT pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)) ?= tpcpatchSeq(ARRAY[
      tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)), '2001-01-01'::timestamptz),
      tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)]);
    -- t
    SELECT tpcpatchSeq(ARRAY[tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)),
      '2001-01-01'::timestamptz), tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)]) %= pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2));
    -- f
    
  • Comparaciones temporales

    {pcpatch,tpcpatch} {#=, #<>} {pcpatch,tpcpatch} → tbool
    
    SELECT tpcpatchSeq(ARRAY[tpcpatch(pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2)),
      '2001-01-01'::timestamptz), tpcpatch(pcpatch(pcpoint(1, 3, 3, 3), pcpoint(1, 4, 4, 4)),
      '2001-01-02'::timestamptz)]) #= pcpatch(pcpoint(1, 1, 1, 1), pcpoint(1, 2, 2, 2));
    -- [t@2001-01-01, f@2001-01-02]