Skip to main content

Chunk

Struct Chunk 

Source
#[non_exhaustive]
pub struct Chunk { pub key: VoxelKey, pub fields: Fields, /* private fields */ }
Expand description

A decompressed point data chunk.

A Chunk wraps a las::PointData along with the VoxelKey of the octree node it came from and the Fields mask that was used to decode it. Column accessors (intensity, gps_time, rgb, …) are guarded by the mask and return None for fields that were not decoded.

Construct via CopcStreamingReader::fetch_chunk or CopcStreamingReader::query_chunks.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§key: VoxelKey

The octree node this chunk belongs to.

§fields: Fields

Which fields were actually decompressed into this chunk.

Implementations§

Source§

impl Chunk

Source

pub fn new(key: VoxelKey, fields: Fields, cloud: PointData) -> Self

Construct a Chunk from a VoxelKey, a Fields mask, and a las::PointData.

Normally you’ll get chunks from CopcStreamingReader::fetch_chunk; this constructor exists for callers that drive their own decompression pipeline (and for tests). The caller is responsible for ensuring that fields accurately describes which LAZ layers were decoded into cloud — otherwise the chunk’s field guards will hide columns that are actually valid, or (worse) expose columns that contain zero’d bytes for skipped layers.

Source

pub fn cloud(&self) -> &PointData

Borrow the underlying las::PointData — an unchecked escape hatch to the raw byte-level accessors in las.

Use this when Chunk’s higher-level methods don’t expose what you need: cloud.x_raw(), cloud.record_len(), cloud.raw_bytes(), cloud.iter() for zero-copy PointRef walks, etc.

§⚠ Field guards are bypassed

Calling cloud.rgb(), cloud.gps_time(), cloud.intensity(), or any PointRef accessor on bytes from this cloud does not check whether the underlying layer was actually decoded. If you call one of those on a chunk that was fetched without the corresponding Fields flag, you get a valid-looking iterator of zeros.

Prefer the Chunk methods (rgb, gps_time, etc.) — they return None when the field is absent, making the hazard impossible to hit accidentally.

Source

pub fn point_count(&self) -> usize

Number of points in this chunk.

Source

pub fn is_empty(&self) -> bool

Whether this chunk contains zero points.

Source

pub fn to_points(&self) -> Result<Vec<Point>, CopcError>

Materialize every point in this chunk as an owned las::Point.

Returns CopcError::PartialDecode if this chunk was decoded with a partial field mask — otherwise the resulting las::Points would have silently-zero values for skipped fields.

This is the bridge from the column-oriented Chunk API back to the simple Vec<las::Point> API. Prefer the column accessors (intensity, gps_time, …) or chunk.cloud().iter() when you don’t need owned values.

Source

pub fn points_at(&self, indices: &[u32]) -> Result<Vec<Point>, CopcError>

Materialize las::Point values only at the given indices.

Pair with indices_in_bounds or any other index-producing filter to skip the materialization cost for rejected points entirely:

let chunk = reader.fetch_chunk(&key, Fields::ALL).await?;
let indices = chunk.indices_in_bounds(&bounds).unwrap();
let points = chunk.points_at(&indices)?;

Returns CopcError::PartialDecode if the chunk was decoded with a partial field mask, same as to_points.

Source

pub fn positions(&self) -> Option<impl Iterator<Item = [f64; 3]> + '_>

Iterate (x, y, z) world coordinates as [f64; 3], or None if Fields::Z was not set.

x and y are always decoded on LAS 1.4 layered formats (they share the always-on base layer with return_number, number_of_returns and scanner_channel), but z is its own skippable layer. A chunk without Fields::Z has zero bytes in the z slots; returning None here keeps the footgun out of reach.

Source

pub fn intensity(&self) -> Option<impl Iterator<Item = u16> + '_>

Intensity column, or None if Fields::INTENSITY was not set or the format does not include intensity.

Source

pub fn classification(&self) -> Option<impl Iterator<Item = u8> + '_>

Classification byte column, or None if Fields::CLASSIFICATION was not set.

Source

pub fn scan_angle(&self) -> Option<impl Iterator<Item = f32> + '_>

Scan angle column in degrees, or None if Fields::SCAN_ANGLE was not set.

Source

pub fn user_data(&self) -> Option<impl Iterator<Item = u8> + '_>

User data byte column, or None if Fields::USER_DATA was not set.

Source

pub fn point_source_id(&self) -> Option<impl Iterator<Item = u16> + '_>

Point source ID column, or None if Fields::POINT_SOURCE_ID was not set.

Source

pub fn gps_time(&self) -> Option<impl Iterator<Item = f64> + '_>

GPS time column, or None if Fields::GPS_TIME was not set or the format does not include GPS time.

Source

pub fn rgb(&self) -> Option<impl Iterator<Item = (u16, u16, u16)> + '_>

RGB column, or None if Fields::RGB was not set or the format does not include color.

Source

pub fn nir(&self) -> Option<impl Iterator<Item = u16> + '_>

NIR column, or None if Fields::NIR was not set or the format does not include NIR.

Source

pub fn indices_in_bounds(&self, bounds: &Aabb) -> Option<Vec<u32>>

Indices of points inside bounds, or None if Fields::Z was not set.

A 3D bounding-box intersection requires z, so a chunk without Fields::Z can’t produce meaningful results — None makes that impossible to misuse. Pair the returned indices with any column iterator on the chunk to produce a filtered view without materializing las::Point values.

Source

pub fn decompress( compressed: &[u8], entry: &HierarchyEntry, laz_vlr: &LazVlr, header: &Header, fields: Fields, ) -> Result<Self, CopcError>

Decompress already-fetched compressed bytes into a Chunk.

Public counterpart to the sync inner that CopcStreamingReader::fetch_chunks uses internally. Useful when the caller wants to issue the ByteSource::read_range on one executor (e.g. the browser main thread) and run the CPU-bound LAZ decompression on another (e.g. a Rayon worker pool).

compressed must be exactly entry.byte_size bytes for the chunk referenced by entry.key. laz_vlr and header come from CopcStreamingReader::header and are immutable for the lifetime of the dataset, so a caller can clone them out of the reader once and reuse them.

§Example
// Fetch on one thread, hand bytes to a worker for decode:
let entry = reader.get(&key).unwrap().clone();
let bytes = reader
    .source()
    .read_range(entry.offset, entry.byte_size as u64)
    .await?;
// ... move bytes to a worker thread ...
let chunk = Chunk::decompress(
    &bytes,
    &entry,
    reader.header().laz_vlr(),
    reader.header().las_header(),
    Fields::Z | Fields::RGB,
)?;

Auto Trait Implementations§

§

impl Freeze for Chunk

§

impl RefUnwindSafe for Chunk

§

impl Send for Chunk

§

impl Sync for Chunk

§

impl Unpin for Chunk

§

impl UnsafeUnpin for Chunk

§

impl UnwindSafe for Chunk

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.