PCD (.pcd)
The Point Cloud Library format (v0.7): a short text header (VERSION, FIELDS, SIZE, TYPE, COUNT, WIDTH, HEIGHT, VIEWPOINT, POINTS, DATA) followed by the points as ASCII rows (DATA ascii), packed little-endian records (DATA binary) or a field-by-field (struct-of-arrays) block inside an LZF stream (DATA binary_compressed, two uint32 sizes then the stream).
| Format name | pcd |
| Extensions | .pcd |
| Read / Write | ✓ / ✓ |
| Extra dependencies | — |
Reading & writing
import meshioplusplus
mesh = meshioplusplus.read("cloud.pcd")
meshioplusplus.pcd.write("out.pcd", mesh, data="binary")data—"ascii","binary"(the default) or"binary_compressed"; when omitted,binary=True/Falsepicks between the first two.point_dtype— the precision ofx y z(and of normals, curvature and intensity):"float32"(the default: PCL's typedPointXYZloaders reject any other field type),"float64", or"keep"to follow the mesh's own points (what the in-placeascii/binary/compress/decompressverbs use). A lossy narrowing is recorded in the provenance.drop_invalid(read) — drop the points whose x, y or z is not finite (an organised cloud's invalid returns) and, when any is dropped, the organisation with them.
Mesh mapping
The points plus exactly one vertex block — what subsample_points produces. Point data is keyed by field name, with three conventions: normal_x/y/z → "normals" (n, 3); PCL's rgb/rgba, a uint32 0x00RRGGBB/0xAARRGGBB that lives in a float32 slot (unpacked by bit-cast, never by value) → "rgb" (n, 3) / "rgba" (n, 4) uint8; any other field keeps its own name and dtype, with COUNT > 1 giving (n, count). _ padding fields are skipped. x/y/z keep the file's precision (all F4 → float32, otherwise float64).
File structure
# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z [...]
SIZE 4 4 4 [...]
TYPE F F F [...]
COUNT 1 1 1 [...]
WIDTH <n>
HEIGHT 1
VIEWPOINT <tx ty tz qw qx qy qz>
POINTS <n>
DATA ascii | binary | binary_compressed
<points>Quirks & limitations
- Organised clouds (
HEIGHT > 1) are kept whole, NaN rows included, withWIDTH/HEIGHTinfield_data["pcd:width"]/["pcd:height"](restored on write whenWIDTH * HEIGHTequals the point count). VIEWPOINTis recorded, never applied: a non-identity viewpoint goes tofield_data["pcd:viewpoint"].- Only
vertexcells are writable; anything else, all cell data and unrelated field data are dropped with a warning and a provenance note. - Point-data names are sanitised to the header's word vocabulary (spaces become
_, collisions get a numeric suffix).
Notes
tests/python/meshes/pcd/— PCL's own test corpus (BSD-3, seeLICENSE.PCLthere):bun0.pcd(ascii, normals + curvature),colored_cloud.pcd(binary, organised, uintrgb),pcl_logo.pcd(binary_compressed, float-slotrgb, non-identity viewpoint),milk_color.pcd(binary_compressed,rgba).- The C++ core handles all three
DATAmodes. Its LZF codec is an independent implementation of the liblzf stream format (no liblzf code is copied), and the Python reference writes byte-identical files. The CLI verbsascii,binary,compress(binary_compressed) anddecompressrewrite a.pcdin place, and the MCPconverttool takesmodeandcompression: lzf. The flat bindings (C, Fortran, Julia, R, WASM) read every mode and writeascii/binary;binary_compressedwriting is on the roadmap.
Web output
A PCD cloud is a vertex block (or no cells at all), which the glTF writer turns into a POINTS primitive, keeping the normals point data as NORMAL and every other point array as a raw _NAME attribute: meshioplusplus convert cloud.pcd cloud.glb puts a scanned cloud on the web. Run compute_normals first when the cloud has none.