MobilityDB incluye complementos PDAL nativos bajo contrib/pdal/ que leen y escriben valores tpcpatch directamente sin pasar por readers.pgpointcloud + tpcpatchSeq(). Compílelos con:
cd contrib/pdal cmake -B build && cmake --build build -j sudo cmake --install build
PDAL descubre los complementos mediante PDAL_DRIVER_PATH o, tras la instalación, en su ruta de búsqueda por defecto. Verifique con pdal --drivers | grep tpcpatch.
Lee cualquier consulta SQL que devuelva filas de (timestamp, pcpatch, pcid) y emite un PointView de PDAL con todas las dimensiones del esquema más una dimensión time_t que lleva microsegundos desde la época. La decodificación se delega a pc_patch_from_wkb de pgPointCloud, por lo que se manejan los tres tipos de compresión (PC_NONE, PC_DIMENSIONAL, PC_LAZPERF).
Para descomprimir un tpcpatch almacenado en filas por instante que el lector pueda consumir:
{
"type": "readers.tpcpatch",
"connection": "host=/tmp dbname=mydb",
"query": "SELECT (EXTRACT(EPOCH FROM timestampN(traj, n))*1000000)::bigint AS t,
valueN(traj, n) AS pcp,
PC_PCId(valueN(traj, n)) AS pcid
FROM trajectories,
generate_series(1, numInstants(traj)) n
WHERE id = 42
ORDER BY n"
}Recibe un PointView con una dimensión de tiempo configurable, agrupa los puntos por marca de tiempo en valores pcpatch por instante, luego despacha un INSERT, UPDATE, fusión-append o upsert contra una columna tpcpatch usando los constructores tpcpatch(pcpatch, timestamptz) + tpcpatchSeq(pcpatch[]) de MobilityDB. La codificación se delega a pc_patch_to_wkb de pgPointCloud con pc_patch_compress opcional. La escala / desplazamiento del esquema se aplica simétricamente — los valores fluyen como sus unidades semánticas (metros, grados, …) a través de PDAL incluso cuando el esquema los almacena como int32 escalado.
Opciones:
connection (posicional) — cadena de conexión libpq.
table (posicional) — nombre de la tabla de destino.
column — nombre de la columna tpcpatch (por defecto traj).
pcid (requerido) — entrada en pointcloud_formats cuyo esquema deben coincidir las dimensiones de entrada.
id_column, id_value — identifican la fila de destino para cualquier modo distinto de insert.
mode — insert (por defecto — nueva fila por ejecución de la tubería), update (sobrescribe la fila identificada por id_column = id_value), append (concatena mediante merge() sobre la fila existente), o upsert (inserta si está ausente, añade si está presente). append / update generan un error claro «matched no row» si no se encuentra id_value, por lo que no pueden ocurrir escrituras silenciosas de cero filas.
time_dim — nombre de la dimensión de tiempo de origen (por defecto time_t; establézcalo en GpsTime para consumir marcas de tiempo LAS directamente sin una etapa filters.assign).
time_format — interpretación de time_dim: unix_microseconds (por defecto), unix_seconds, o gps_adjusted (Tiempo GPS Estándar Ajustado LAS-1.4 — el escritor aplica el desplazamiento de época GPS-Unix y el offset de segundo intercalar de 2024).
compression — none (por defecto), dimensional, o laz. MobilityDB normaliza el almacenamiento en disco de tpcpatch a PC_NONE, por lo que la opción solo afecta al tamaño de transporte libpq — la reducción típica es ~3x para dimensional en datos con dimensiones redundantes.
flush_threshold (por defecto 1024) — número de parches por instante completados almacenados en memoria antes de emitir un INSERT/append. Se respeta para mode=append/upsert; mode=insert/update difieren a un único vaciado final ya que cada ejecución de la tubería produce una única fila.
El escritor emite líneas de progreso periódicas de nivel Info mediante el registrador de PDAL y un resumen final en done(): total de puntos / parches escritos, columna de destino, pcid, compresión y modo. Visible con pdal pipeline -v 5.
El lector y el escritor admiten los tres tipos de compresión de pgPointCloud: PC_NONE, PC_DIMENSIONAL y PC_LAZPERF. La regresión PC_LAZPERF en contrib/pdal/examples/test_lazperf.sql requiere que la instalación de pgPointCloud en ejecución esté compilada con --with-lazperf=DIR; el fixture SQL aborta con un mensaje claro en caso contrario. Los complementos se mantienen bajo contrib/pdal/ en lugar de en el árbol de compilación principal de MobilityDB para que puedan compilarse y actualizarse de forma independiente.
Endianness de WKB. readers.tpcpatch acepta solo pcpatch WKB little-endian (NDR). Un parche big-endian (primer byte 0x00) se rechaza con un error claro en lugar de decodificarse mal silenciosamente. pgPointCloud emite NDR en toda plataforma común; el soporte XDR sería aditivo.
Compresión del tpcpatch almacenado. La opción compression de writers.tpcpatch controla solo la forma de transporte libpq. El tpcpatch de MobilityDB normaliza su almacenamiento de pcpatch en disco a PC_NONE.
Escritura en flujo. writers.tpcpatch implementa la interfaz Streamable::processOne de PDAL, por lo que una tubería readers.las → writers.tpcpatch se ejecuta en modo de flujo de PDAL automáticamente y nunca mantiene toda la nube de puntos en memoria. La cola de parches completados está limitada por la opción del escritor flush_threshold (por defecto 1024); en mode=append / mode=upsert cada vaciado activado por umbral emite un lote SQL incremental mediante merge(), mientras que mode=insert / mode=update difieren a un único vaciado final en done() (semántica de fila única). Esta es la ruta que hace tratable la ingesta de LAS de varios GB.