Tipo Temporal tpcpatch

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.

Constructores

  • Construir un pcpatch temporal de subtipo instante

    tpcpatch(pcpatch,timestamptz) → tpcpatch

  • Construir un pcpatch temporal de subtipo secuencia

    tpcpatchSeq(tpcpatch[]) → tpcpatch

    tpcpatchSeq(tpcpatch[],text) → tpcpatch

  • Construir un pcpatch temporal de subtipo conjunto de secuencias

    tpcpatchSeqSet(tpcpatch[]) → tpcpatch

Accesores

Se aplican todos los accesores temporales genéricos, además del pcid y el SRID al estilo de tpcpoint. Adicionalmente:

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

    startNumPoints(tpcpatch) → integer

    endNumPoints(tpcpatch) → integer

    SELECT startNumPoints(tpcpatch(PC_Patch(PC_MakePoint(1, ARRAY[10.0, 20.0, 30.0])),
      '2024-02-01'::timestamptz));
    -- 1
    
  • Devolver el número total de puntos de todos los parches de todos los instantes. Se lee directamente de la cabecera de cada parche — sin descompresión.

    numPoints(tpcpatch) → bigint

    SELECT numPoints(tpcpatchSeq(ARRAY[
      tpcpatch(PC_Patch(ARRAY[PC_MakePoint(1, ARRAY[1.0, 1.0, 1.0]),
                              PC_MakePoint(1, ARRAY[2.0, 2.0, 2.0])]),
               '2024-01-01'::timestamptz),
      tpcpatch(PC_Patch(ARRAY[PC_MakePoint(1, ARRAY[3.0, 3.0, 3.0])]),
               '2024-01-02'::timestamptz)]));
    -- 3
    
  • Función devuelve-conjunto: emite una fila por cada (marca de tiempo de instante, punto) recorriendo el parche de cada instante y descomponiéndolo 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.

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

    SELECT t, point FROM points(tpcpatch(
      PC_Patch(ARRAY[PC_MakePoint(1, ARRAY[1.0, 1.0, 1.0]),
                     PC_MakePoint(1, ARRAY[2.0, 2.0, 2.0])]),
      '2024-01-01'::timestamptz));
    -- ('2024-01-01', '01:0000000000000000000000F03F0000000000000000F03F00000000000000F03F'::pcpoint)
    -- ('2024-01-01', '01:0000000000000000000000004000000000000000400000000000000040'::pcpoint)
    

Véase “Operaciones por punto: qué está y qué no está disponible” para conocer los límites de estos accesores y qué está y qué no está disponible a nivel de granularidad por punto.

Restricciones

  • Restringir un tpcpatch a los instantes cuyo parche supera una prueba de superposición aproximada de PCBOUNDS frente al tpcbox, o eliminarlos. 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.

    atTpcbox(tpcpatch,tpcbox,border_inc bool=TRUE) → tpcpatch

    minusTpcbox(tpcpatch,tpcbox,border_inc bool=TRUE) → tpcpatch

  • Variante por punto de la anterior: cada instante superviviente contiene un pcpatch recién construido que incluye solo los puntos dentro (o fuera, en el caso de minus) del tpcbox en 2D — y en 3D 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.

    atTpcboxFine(tpcpatch,tpcbox,border_inc bool=TRUE) → tpcpatch

    minusTpcboxFine(tpcpatch,tpcbox,border_inc bool=TRUE) → tpcpatch

  • Restringir un tpcpatch a los puntos cuya proyección XY intersecta (o no intersecta, en el caso de minus) una geometría 2D. Z se ignora. El llamador debe garantizar la compatibilidad de SRID entre el esquema del parche y la geometría.

    atGeometry(tpcpatch,geometry) → tpcpatch

    minusGeometry(tpcpatch,geometry) → tpcpatch

Relaciones espaciales

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

Operadores de caja delimitadora

La misma superficie de operadores de caja que en “Operadores 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.

  • Predicados topológicos: &&, @>, <@, ~=, -|-. Véase “Operadores Topológicos”.

  • Predicados direccionales estrictos sobre los ejes X / Y / Z / tiempo (<<, >>, <<|, |>>, <</, />>, <<#, #>>) y sus variantes «solapa-o-X» (&<, &>, &<|, |&>, &</, /&>, &<#, #&>). Véase “Operadores de Posición”.

  • La distancia de aproximación más cercana (|=|) es ordenable KNN a través de la clase de operador GiST.

    nearestApproachDistance(tpcpatch,tpcbox) → float

    nearestApproachDistance(tpcpatch,tpcpatch) → float

Ordenación B-tree — qué significa ORDER BY tpcpatch

La clase de operador tpcpatch_btree_ops produce un orden total sobre los valores tpcpatch, pero ese orden no es espacial. El comparador sobre el pcpatch subyacente es byte a byte (memcmp sobre los bytes varlena significativos); el comparador al nivel temporal es la combinación lexicográfica de las marcas de tiempo por instante y el orden de bytes de pcpatch por instante. Las consecuencias observables son:

  • pcid es el discriminador primario. Un parche con un pcid menor se ordena antes que uno con un pcid mayor, independientemente de las coordenadas de los puntos, su cantidad o la compresión. Esto hace que ORDER BY sobre una columna de pcid mixto agrupe las filas primero por esquema, lo que a veces resulta útil como paso de agrupación gruesa «por esquema de origen».

  • Dentro de un mismo pcid, el orden sigue la disposición de bytes en disco: esquema de compression, luego npoints, luego el PCBOUNDS 2D (xmin, xmax, ymin, ymax) y finalmente el payload data comprimido. Este orden está bien definido y es estable para una versión dada de pgPointCloud, pero no es un orden geométrico o espacial — dos parches cuyos cuadros delimitadores se superponen en el espacio 3D pueden ordenarse de forma arbitraria entre sí si difieren en su esquema de compresión o en el número de puntos.

  • La igualdad es igualdad exacta de bytes sobre los bytes significativos (se excluye el relleno de ceros al final que reserva el varlena de pgPointCloud). Dos parches construidos a partir del mismo conjunto de puntos en el mismo orden, con la misma compresión, son iguales; reordenar los puntos o cambiar la compresión los hace desiguales.

Para un orden con sentido espacial, use el operador KNN de GiST |=| (véase distancia de aproximación más cercana en tpcpatch); para un orden con sentido temporal, proyecte a startTimestamp o timespan y ordene sobre ese valor.

Operaciones por punto: qué está y qué no está disponible

Las operaciones sobre valores tpcpatch se realizan a dos granularidades: nivel de parche y por punto. La distinción importa porque los parches de pgPointCloud almacenan sus puntos en un payload comprimido que la capa de caja delimitadora no puede inspeccionar.

  • Nivel de parche — soportado. El parche de cada instante se trata como opaco y se conserva o descarta como un todo, usando únicamente la cabecera PCBOUNDS de 4 valores double (xmin / xmax / ymin / ymax) y la marca de tiempo del instante. Esta es la granularidad de atTpcbox / minusTpcbox y de los operadores de caja delimitadora en “Operadores de caja delimitadora”, así como del agregado tpcbox basado en caja. No se produce descompresión del payload; las consultas son O(número de instantes).

    Como PCBOUNDS es 2D, la dimensión Z de cualquier argumento tpcbox se ignora a esta granularidad, incluso cuando el esquema subyacente tiene dimensión Z.

  • Inspección por punto — soportada. La función devuelve-conjunto points emite una fila por cada (marca de tiempo de instante, punto) descomponiendo el parche de cada instante mediante la API C en memoria de pgPointCloud. El coste es O(total de puntos) — una descompresión por instante más una emisión de fila por punto.

  • Filtrado / construcción por punto — soportado. atTpcboxFine / minusTpcboxFine, atGeometry / minusGeometry y eIntersects(tpcpatch, geometry) recorren en C cada punto de cada instante, aplicando su predicado sobre las coordenadas reales del punto en lugar de limitarse al cuadro delimitador del parche. Los instantes supervivientes contienen un parche recién construido que incluye solo los puntos que superaron el predicado; los instantes cuyos parches filtran hasta cero puntos se descartan.

El flujo de trabajo recomendado cuando ambas granularidades están disponibles es: (a) podar al nivel de parche con atTpcbox o un escaneo de índice SP-GiST/GiST para descartar los instantes completos cuyo PCBOUNDS no se superpone con el área de interés, y (b) refinar sobre los supervivientes con atTpcboxFine / atGeometry cuando se necesite fidelidad a nivel de punto.