hypc
A Rust crate for reading and writing HPC1 point clouds, with first-class support for SMC1 semantic masks and GEOT georeferencing chunks.
This crate provides a simple, fast, and safe way to interact with .hpc files. It is designed to be lightweight, with minimal dependencies (anyhow for error handling and miniz_oxide for zlib compression).
Features
- HPC1 Core Support: Read and write the base HPC1 point cloud format, including header and quantized position data.
- TileKey Integration: Natively handles
TileKeymetadata, allowing for slippy-map style(zoom, x, y)keys or 64-bit name hashes to be embedded directly in the file header. - Semantic Masks (SMC1): Full support for reading and writing the
SMC1chunk. This allows for a 2D semantic label grid to be associated with the point cloud, useful for classification and segmentation tasks. Supports both raw and zlib-compressed mask data. - Georeferencing (GEOT): Full support for reading and writing the
GEOTchunk. This provides a geographic bounding box (CRS:84) for the point cloud, enabling coordinate transformations between the local decode space and longitude/latitude. - High-Level Helpers: Provides convenient methods for common tasks, such as:
- Looking up a semantic class ID from a point's
(x, y)coordinate. - Converting between geographic coordinates (lon/lat) and the point cloud's local decode space.
- Looking up a semantic class ID directly from a lon/lat coordinate.
- Looking up a semantic class ID from a point's
- Robust Parsing: Gracefully skips unknown trailing chunks, ensuring forward compatibility with future extensions to the format.
Format Specification
The .hpc file format as implemented by this crate consists of a main HPC1 header and payload, followed by zero or more tagged chunks.
Main HPC1 Format
The file begins with a fixed-size 52-byte header, followed by the point data payload.
| Offset | Size (bytes) | Type | Field | Description |
|---|---|---|---|---|
| 0 | 4 | [u8; 4] |
Magic | Must be b"HPC1". |
| 4 | 4 | u32 (LE) |
Version | Currently must be 1. |
| 8 | 4 | u32 (LE) |
Flags | Bitfield. Bit 0 (1 << 0) indicates a TileKey is present. |
| 12 | 4 | u32 (LE) |
Count | The number of points in the cloud. |
| 16 | 1 | u8 |
QBits | Quantization bits per component. Currently must be 16. |
| 17 | 11 | [u8; 11] |
Reserved | Used for TileKey payload if Flags bit 0 is set. Otherwise, zeroed. |
| 28 | 12 | [f32; 3] |
Decode Min | The minimum [x, y, z] corner of the point cloud's bounding box. |
| 40 | 12 | [f32; 3] |
Decode Max | The maximum [x, y, z] corner of the point cloud's bounding box. |
| 52 | Count * 6 |
[u16; N*3] |
Payload | Quantized positions. Each point is (qx, qy, qz) as little-endian u16. |
TileKey Payload
When Flags bit 0 is set, the 11-byte Reserved field is used to store a TileKey. The first byte of the reserved field acts as a type discriminator.
TileKey::XY (Type 0)
| Offset in Reserved | Size | Type | Description |
|---|---|---|---|
| 0 | 1 | u8 |
Type (0) |
| 1 | 1 | u8 |
Zoom level |
| 2 | 4 | u32 (LE) |
X coordinate |
| 6 | 4 | u32 (LE) |
Y coordinate |
| 10 | 1 | u8 |
Scheme |
TileKey::NameHash64 (Type 4)
| Offset in Reserved | Size | Type | Description |
|---|---|---|---|
| 0 | 1 | u8 |
Type (4) |
| 1 | 8 | u64 (LE) |
64-bit hash value |
| 9 | 2 | [u8; 2] |
Unused (zeroed) |
Trailing Chunks
After the main HPC1 payload, any number of tagged chunks can appear. The format is designed to be extensible; unknown chunks are skipped using their provided length.
Each chunk follows a simple [TAG][LENGTH][PAYLOAD] structure:
- Tag: A 4-byte ASCII identifier (e.g.,
b"SMC1",b"GEOT"). - Length: A
u32(LE) specifying the size of the payload in bytes. - Payload: The chunk-specific data.
SMC1 Chunk (Semantic Mask)
The SMC1 chunk provides a 2D classification grid that maps onto the point cloud's XY plane.
Tag: b"SMC1"
Payload Layout (Version 1):
| Field | Type | Description |
|---|---|---|
| Version | u8 |
1 for the current version. |
| Encoding | u8 |
0 for Raw (uncompressed), 1 for Zlib-compressed. |
| Width | u16 (LE) |
Width of the mask grid in pixels. |
| Height | u16 (LE) |
Height of the mask grid in pixels. |
| Coord Space | u8 |
0 indicates the mask maps to the point cloud's decode XY space. |
| Class Count | u8 |
Number of entries in the palette. |
| Reserved | u16 (LE) |
Zeroed. |
| Palette | [Entry] |
Class Count entries. Each entry is (class_id: u8, precedence: u8) followed by 2 reserved bytes. |
| Data Length | u32 (LE) |
The length of the following data block in bytes. |
| Data | [u8] |
The mask data (row-major), possibly zlib-compressed. After decompression, its size is Width * Height. Each byte is a class_id. |
GEOT Chunk (Georeferencing)
The GEOT chunk provides a geographic bounding box for the point cloud, linking it to real-world coordinates.
Tag: b"GEOT"
Payload Layout (Version 1, CRS:84): This is a fixed-size 24-byte payload.
| Field | Type | Description |
|---|---|---|
| Version | u8 |
1. |
| CRS ID | u8 |
1 for CRS:84 (WGS 84, lon/lat in degrees). |
| Mode | u8 |
0 for BBOX_DEG_Q7 (bounding box in degrees with Q7 quantization). |
| Reserved | u8 |
Zeroed. |
| Lon Min (Q7) | i32 (LE) |
Minimum longitude quantized by 1e7. (lon_min * 1e7) |
| Lat Min (Q7) | i32 (LE) |
Minimum latitude quantized by 1e7. (lat_min * 1e7) |
| Delta Lon (Q7) | u32 (LE) |
Longitude extent quantized by 1e7. (lon_max - lon_min) * 1e7 |
| Delta Lat (Q7) | u32 (LE) |
Latitude extent quantized by 1e7. (lat_max - lat_min) * 1e7 |
Usage
Add to Your Project
Add hypc to your Cargo.toml:
[]
= "0.1.0"
Reading an .hpc File
The easiest way to read a file is with hypc::read_file. This returns a HypcPointCloud struct containing all parsed data.
use HypcPointCloud;
Using Semantic and Geographic Helpers
The real power of hypc comes from the high-level methods that combine data from different chunks. For example, you can find the semantic class of any geographic coordinate.
Writing an .hpc File
To write a file, you construct a HypcWrite struct with all the necessary data and pass it to hypc::write_file.
Note that for writing, you must provide the positions in their quantized u16 form.
use ;
License
This project is licensed under the MIT License.