Point Cloud & COPC Conversion for Spatial Archives
LiDAR is usually the largest thing in a spatial archive by volume and the least well organised for retrieval: a survey arrives as tens of thousands of LAS or LAZ tiles whose only index is their file names, so any question that crosses tile boundaries means fetching every tile that might contribute. Cloud-Optimized Point Cloud (COPC) is LAZ with an octree written into it, which turns that pattern into a ranged read of exactly the nodes a query intersects. This topic is for the archivist or data engineer converting point-cloud holdings, and it covers the decisions — scale and offset, octree depth, tile consolidation — that are fixed at write time.
The Failure Mode: Coordinates That Change Meaning
Point clouds store coordinates as 32-bit integers with a per-file scale and offset, so the true position is offset + integer × scale. That representation is exact and efficient, and it makes conversion unusually dangerous: a converter that recomputes scale or offset from the data it happens to be processing produces a file whose coordinates decode differently from the source, with no error and no visible symptom. Tiles converted in separate jobs can end up with different offsets, so a merged read shows a survey that does not line up with itself.
Prerequisite Context
Before converting, three facts about the source must be established and recorded: the shared scale and offset used across the survey, the coordinate reference system including any vertical datum, and the point data record format, since formats differ in whether they carry time, colour and classification. All three live in the LAS header and the variable-length records, and all three should be asserted rather than assumed — legacy deliveries frequently carry a reference system in an accompanying document and nothing in the file.
Concept & Design Decisions
Preserve scale and offset; never derive them. Read them from the source and pass them explicitly to the writer. Where a survey genuinely has no shared offset — different deliveries over years — choose one for the archive, apply it uniformly, and record the decision.
Octree depth. COPC organises points into an octree whose depth determines how selectively a query can read. Depth is chosen so that the deepest nodes hold a workable number of points — a few tens of thousands each is typical. Too shallow and every query reads large nodes; too deep and the node index itself becomes large and the per-node overhead dominates.
Tile consolidation. A survey delivered as 30,000 tiles of 60 MB is better archived as a few hundred COPC files of several gigabytes, because the octree replaces the tile grid as the access mechanism and object count drives both request charges and restore complexity. Consolidate along acquisition boundaries so a restore maps to something a user asks for.
Compression. LAZ compression is already applied and is lossless; do not layer a general-purpose codec on top. The archival decision is whether to keep the delivered LAZ as-is or rewrite it as COPC — and the answer for anything that will be queried rather than only retrieved whole is COPC.
Implementation
PDAL is the workhorse. The pipeline below reads a set of source tiles, pins the scale and offset, and writes a single COPC object.
{
"pipeline": [
{ "type": "readers.las",
"filename": "datasets/lidar/2023/region_north/*.laz",
"nosrs": false },
{ "type": "filters.reprojection",
"in_srs": "EPSG:27700+5701",
"out_srs": "EPSG:27700+5701" },
{ "type": "writers.copc",
"filename": "/vsis3/spatial-archive/archive/lidar/2023/region_north.copc.laz",
"scale_x": 0.001, "scale_y": 0.001, "scale_z": 0.001,
"offset_x": 500000, "offset_y": 5430000, "offset_z": 0,
"forward": "header,vlr",
"a_srs": "EPSG:27700+5701" }
]
}
pdal pipeline region_north.json --nostream
The scale_* and offset_* values are the whole point of the configuration: pinning them makes the conversion reproducible and keeps every object in the archive in one frame. forward carries the source header fields and variable-length records through, which is how acquisition metadata survives.
Validation Gate
Verify the header before anything else — a COPC whose scale, offset or reference system changed is wrong regardless of how many points it holds.
pdal info --metadata /vsis3/spatial-archive/archive/lidar/2023/region_north.copc.laz \
| jq '.metadata | {count, scale_x, offset_x, scale_z, offset_z, srs: .srs.compoundwkt[0:60]}'
Expected output reports the point count equal to the sum of the source tiles, the exact scale and offset that were pinned, and a compound reference system including the vertical datum. A count that is short by a few thousand usually means one source tile failed to read and the pipeline continued.
Cost & Performance Trade-offs
| Decision | Storage effect | Retrieval effect |
|---|---|---|
| Keep delivered LAZ tiles | baseline | every query reads whole tiles; high object count |
| Rewrite as COPC, same tiling | +2–4% for the octree | selective within a tile, still many objects |
| Consolidate to ~8 GB COPC | +2–4% | 18× less data per query, 14× fewer requests |
| Consolidate beyond ~20 GB | +2–4% | restores become coarse; a small query restores a lot |
The octree overhead is small and constant; the consolidation decision is what moves the numbers. Beyond roughly twenty gigabytes per object the restore granularity starts to hurt, which places the sweet spot for archive-class point clouds between about four and twelve gigabytes.
Failure Modes & Edge Cases
Vertical datum dropped. Point clouds carry a vertical component, and a conversion that writes only the horizontal reference system leaves elevations ambiguous by up to fifty metres. Assert a compound reference system on both sides.
Classification codes remapped. Some tools renumber classification values to match their own conventions. Compare the histogram of classification codes before and after; a shifted histogram is a silent semantic change.
Point data record format downgraded. Writing a format that lacks a time or colour field discards those attributes without error. Pin the output format explicitly rather than letting the writer choose.
Streaming mode reorders points. COPC writing needs the full point set to build the octree; running the pipeline in streaming mode either fails or produces a degenerate index. Use --nostream for COPC output.
Operational Execution Checklist
Classification Semantics Across Deliveries
A point cloud’s classification codes are only meaningful against a scheme, and archives that accept deliveries from several contractors over several years end up holding three or four schemes under one set of numbers. Code 6 means “building” in the standard scheme and something else entirely in a vendor extension.
Record the scheme identifier with each delivery and never renumber to normalise: renumbering rewrites the data to match a decision that may itself be revised, and it destroys the ability to reproduce the delivery as received. Store the mapping instead, in the manifest, and let readers translate — the same reasoning that keeps an alias table beside truncated field names rather than renaming the columns.
Point Clouds in the Archive’s Wider Lifecycle
Point-cloud collections behave differently from vector and raster holdings in three ways that shape how the rest of the archive treats them, and each has a consequence for tiering, cataloguing and integrity that is worth stating before the first survey lands.
They are the largest thing in the archive by volume and often by a wide margin, which makes them the collection where storage-class choice moves the budget most. A survey that is genuinely finished — classified, delivered, accepted — is also the archetype of data that goes cold quickly and then stays cold for years, which argues for an early transition to a deep class. The complication is the re-survey: when the same area is flown again, the previous survey becomes the comparison baseline and is read heavily for a few weeks. An archive that knows its re-survey schedule can pre-restore the relevant collections rather than discovering the need mid-project.
They are read spatially rather than wholesale, which is the entire argument for COPC over plain LAZ tiles, and it interacts with the storage class in the same way COG does. A collection that will be queried needs a class that serves ranges; one that will only ever be retrieved whole does not. Splitting a survey between the two — the classified product in an instant-retrieval class, the raw swaths in Deep Archive — is usually the arrangement that satisfies both the access pattern and the budget.
They carry semantics that are not self-describing. Classification codes mean whatever the delivery’s scheme says they mean, scale and offset determine what the integers decode to, and the vertical datum determines what the elevations refer to. All three are per-delivery facts that must be recorded in the catalogue rather than assumed, and all three are the kind of thing that is obvious to the team receiving the survey and unrecoverable to the team reading it fifteen years later.
Taken together these argue for treating a point-cloud collection as its own thing within the archive rather than as another set of objects: its own profile with the frame and scheme recorded, its own tiering rule keyed to the re-survey cycle, and its own place in the integrity sampling, since a COPC’s octree is a structure that a whole-file checksum will not tell you is intact.
Frequently Asked Questions
Should the delivered LAZ tiles be kept after conversion?
Keep them until the COPC archive has been validated and used, then tier them deeply rather than deleting. They are the source of record for provenance, and because COPC is a rearrangement rather than a transformation, keeping them is cheap insurance against a conversion defect discovered later.
Does COPC lose anything relative to LAZ?
No — COPC is LAZ with an octree and an index, readable by any LAZ reader that ignores the extra structure. That backwards compatibility is what makes it a safe archival target: a reader from before COPC existed still opens the file and sees the points.
How does COPC interact with archive storage classes?
The same way COG does. Its selective-read advantage requires a class that serves ranges without a restore, so a queried point-cloud collection belongs in an instant-retrieval class while a purely preservation copy can sit deeper. Once restored, the octree makes the temporary copy far cheaper to work with, which is worth having even in the deep case.
Planning a Point-Cloud Conversion Programme
Converting an existing point-cloud holding is a programme rather than a job, because the volumes are large enough that it will run for weeks and because the decisions it fixes are permanent. Four planning steps make the difference between a programme that finishes and one that stalls.
Start with an audit of what is actually held. Point-cloud archives accumulate deliveries with inconsistent frames, mixed record formats, several classification schemes and a surprising number of files whose reference system exists only in an accompanying document. Enumerating that before converting anything is what turns a series of surprises into a plan, and the audit itself is cheap — headers only, a few kilobytes per file.
Decide the archive frame next, once, for everything. That single decision — scale, offset, reference system including the vertical datum, and the point record format — is what makes the converted archive internally coherent, and it is far easier to make deliberately at the start than to reconcile later across a partly converted holding. Where deliveries genuinely differ, the frame decision becomes a transformation decision for the outliers, which should be recorded per delivery.
Then sequence by value rather than by convenience. The collections worth converting first are the ones that are queried, the ones whose re-survey is imminent, and the ones whose delivery format is least well supported. Converting the largest collection first is the common instinct and rarely the right order, because it delays every benefit until the hardest work is finished.
Finally, decide what happens to the deliveries. Keeping them is the default and should be a deliberate default: they are the source of record, they permit reclassification with future methods, and they are the only thing that makes a conversion defect correctable. Tiering them deeply costs little; deleting them to fund the conversion is the one irreversible economy in the whole programme.
A programme planned this way typically spends a fortnight on the audit and the frame decision and then runs largely unattended, which is the correct ratio — the expensive part is the decisions, and the compute is comparatively cheap.
How should point-cloud collections be represented in the catalogue?
As collections with the same discovery properties as imagery — footprint, temporal extent, reference system — plus the point-cloud specifics: point density, classification scheme, the frame, and the record format. The first set makes them findable alongside everything else; the second is what a user needs before deciding whether the data suits their analysis, and it is exactly the information that becomes unrecoverable once the delivery team has moved on.
Do point clouds need their own integrity checks?
They need the same fixity and one additional structural check: that the octree hierarchy is intact. A whole-file checksum confirms the bytes are unchanged and says nothing about whether the index inside them is complete, and a truncated hierarchy produces a file that opens, reports its point count correctly, and fails every spatial query. Include a hierarchy read in the structural sampling for point-cloud collections.
What is the most common regret in a point-cloud archive?
Discarding the raw swaths. They are large, they are rarely read, and they are the only thing that allows a survey to be reclassified when methods improve — which over a twenty-five-year retention is close to certain to be wanted at least once. Tiering them deeply costs little; the decision to delete them is usually made for storage reasons that the cost model would not have supported.
How much of a point-cloud holding is typically worth converting?
The classified products, always; the raw swaths, rarely. Swaths are retrieved whole when they are retrieved at all, so the octree buys them nothing, and converting them doubles the programme’s compute for no access benefit. Convert what will be queried and leave the rest as delivered LAZ, tiered deeply.
Can a COPC archive be served without any server component?
Yes, and that is the point of the format: a client reads the header, walks the octree and fetches node ranges directly from object storage. What the archive supplies is bytes and a manifest, which is exactly the property that makes the arrangement survivable over decades.
Related
- Converting LAS to COPC for Cold Archives — the fleet-scale conversion procedure.
- Compressing LiDAR with LASzip for Deep Archive — what compression buys before the tiering decision.
- Streaming COPC Octree Nodes Over HTTP Range Requests — how a client turns a spatial query into ranged reads.
- Validating Point Cloud CRS and Scaling After Conversion — the gate that catches the offset drift described above.
- Evaluating Glacier Deep Archive for LiDAR Point Clouds — where consolidated point-cloud objects should live.
- CRS Synchronization in Pipelines — the reference-system discipline this conversion depends on.
Up one level: Format Conversion & Pipeline Automation.