Skip to main content

copc_streaming/
lib.rs

1//! Async streaming reader for [COPC](https://copc.io/) (Cloud-Optimized Point Cloud) files.
2//!
3//! COPC organises LAS/LAZ point cloud data in a spatial octree so that clients can
4//! fetch only the regions they need. This crate reads COPC files incrementally through
5//! the [`ByteSource`] trait — any random-access backend (local files, HTTP range
6//! requests, in-memory buffers) works out of the box.
7//!
8//! # Quick start
9//!
10//! ```rust,ignore
11//! use copc_streaming::{CopcStreamingReader, FileSource, VoxelKey};
12//!
13//! let mut reader = CopcStreamingReader::open(
14//!     FileSource::open("points.copc.laz")?,
15//! ).await?;
16//!
17//! // Coarse octree nodes are available immediately.
18//! // Load deeper hierarchy pages as you need them.
19//! let root_bounds = reader.copc_info().root_bounds();
20//!
21//! while reader.has_pending_pages() {
22//!     reader.load_pending_pages().await?;
23//! }
24//!
25//! // Walk the octree — check which nodes intersect your region.
26//! for (key, entry) in reader.entries() {
27//!     if entry.point_count == 0 { continue; }
28//!     if !key.bounds(&root_bounds).intersects(&my_query_box) { continue; }
29//!
30//!     // Drill into finer nodes when available.
31//!     let finer = reader.children(key);
32//!     if !finer.is_empty() { continue; } // render children instead
33//!
34//!     let chunk = reader.fetch_chunk(key).await?;
35//!     let points = reader.read_points(&chunk)?;
36//!     // each `point` has .x, .y, .z, .gps_time, .color, etc.
37//! }
38//! ```
39//!
40//! # Load everything at once
41//!
42//! If you don't need progressive loading, pull the full hierarchy in one call:
43//!
44//! ```rust,ignore
45//! let mut reader = CopcStreamingReader::open(
46//!     FileSource::open("points.copc.laz")?,
47//! ).await?;
48//! reader.load_all_hierarchy().await?;
49//!
50//! // Every node is now available via reader.entries() / reader.get().
51//! ```
52//!
53//! # Hierarchy loading
54//!
55//! [`CopcStreamingReader::open`] reads the LAS header, COPC info and root hierarchy
56//! page. Coarse octree nodes are available right away. Deeper pages are loaded
57//! on demand:
58//!
59//! - [`load_pending_pages`](CopcStreamingReader::load_pending_pages) — fetch the
60//!   next level of pages. Call repeatedly, or only when you need finer detail.
61//! - [`load_all_hierarchy`](CopcStreamingReader::load_all_hierarchy) — convenience
62//!   to pull every remaining page in one go.
63//! - [`children`](CopcStreamingReader::children) — list loaded children of a node.
64//! - [`has_pending_pages`](CopcStreamingReader::has_pending_pages) — check if there
65//!   are still unloaded pages.
66//!
67//! # Custom byte sources
68//!
69//! Implement [`ByteSource`] to read from any backend. The trait requires only
70//! `read_range(offset, length)` and `size()`. A default `read_ranges` implementation
71//! issues sequential reads — override it for backends that support parallel fetches
72//! (e.g. HTTP/2 multiplexing).
73//!
74//! Built-in implementations: [`FileSource`] (local files), `Vec<u8>` and `&[u8]`
75//! (in-memory).
76//!
77//! Futures returned by `ByteSource` are *not* required to be `Send`, so the crate
78//! works in single-threaded runtimes and WASM environments.
79
80mod byte_source;
81mod chunk;
82mod error;
83mod file_source;
84mod header;
85mod hierarchy;
86mod reader;
87mod types;
88
89pub use byte_source::ByteSource;
90pub use chunk::DecompressedChunk;
91pub use error::CopcError;
92pub use file_source::FileSource;
93pub use header::{CopcHeader, CopcInfo};
94pub use hierarchy::{HierarchyCache, HierarchyEntry};
95pub use reader::CopcStreamingReader;
96pub use types::{Aabb, VoxelKey};