Skip to content

Latest commit

 

History

History
293 lines (209 loc) · 7.36 KB

File metadata and controls

293 lines (209 loc) · 7.36 KB

COPC-Cesium API Documentation

COPCPointCloudProvider

Main class for loading and rendering COPC files in CesiumJS.

Constructor

new COPCPointCloudProvider(options: COPCProviderOptions)

Options

interface COPCProviderOptions {
  /** URL to the COPC file (required) */
  url: string;

  /** Color rendering mode (default: 'rgb') */
  colorMode?: 'rgb' | 'intensity' | 'classification' | 'elevation';

  /** Point size in pixels (default: 2) */
  pointSize?: number;

  /**
   * Maximum memory usage in MB (default: 512) for the LRU cache of decoded
   * data from nodes that have scrolled out of view (so they can reappear
   * without a re-fetch/re-decode). Nodes currently visible are never
   * evicted regardless of this budget - it only bounds the retained,
   * off-screen backlog.
   */
  maximumMemoryUsage?: number;

  /** Maximum screen space error for LOD (default: 16) */
  maximumScreenSpaceError?: number;

  /** Skip LOD levels for debugging (default: 0) */
  skipLevels?: number;

  /**
   * URL of the LAZ decoder Web Worker script
   * (src/workers/laz-decoder.worker.ts). When set, point data is decoded
   * off the main thread. Left unset, decoding runs on the main thread.
   */
  workerUrl?: string | URL;

  /** Number of decoder workers to spawn when workerUrl is set (default 4) */
  workerPoolSize?: number;
}

Methods

async initialize(): Promise<void>

Initialize the COPC provider. Must be called before adding to scene.

const provider = new COPCPointCloudProvider({ url: 'data.copc.laz' });
await provider.initialize();

async loadRootNode(): Promise<void>

Load and render the root node, and set up the octree traversal state used by update(). Required before adding the provider's primitive to the scene.

await provider.loadRootNode();

getPrimitive(): Cesium.PrimitiveCollection

Returns the PrimitiveCollection to add to the scene (viewer.scene.primitives.add(provider.getPrimitive())). Individual node primitives are added/removed from this collection internally as update() streams nodes in and out.

update(frameState: any): void

Drives camera-based LOD selection and frustum culling for one frame - streams new nodes in, evicts nodes no longer needed. Not called automatically: the provider is not itself a Cesium primitive, so you must call it yourself, e.g. from viewer.scene.postRender:

viewer.scene.postRender.addEventListener(() => {
  provider.update(viewer.scene.frameState);
});

setPointSize(pointSize: number): void

Update the rendered point size. Already-rendered nodes are rebuilt from their already-decoded data (no re-fetch/re-decode).

provider.setPointSize(4);

setMaximumScreenSpaceError(maximumScreenSpaceError: number): void

Update the LOD threshold. Takes effect on the next update() call.

provider.setMaximumScreenSpaceError(8); // more detail, more requests

destroy(): void

Clean up and release all resources.

provider.destroy();

isDestroyed(): boolean

Check if the provider has been destroyed.

getStats(): { loadedNodeCount, totalPointsLoaded, cachedNodeCount, cachedMemoryMB }

Current loading/rendering stats, for HUD/debug display. cachedNodeCount/ cachedMemoryMB reflect the off-screen LRU cache (see maximumMemoryUsage), not what's currently rendered.


Usage Examples

Basic Usage

import { Viewer } from 'cesium';
import { COPCPointCloudProvider } from 'copc-cesium';

const viewer = new Viewer('cesiumContainer');

const copcLayer = new COPCPointCloudProvider({
  url: 'https://example.com/pointcloud.copc.laz',
  colorMode: 'rgb',
  pointSize: 2
});

await copcLayer.initialize();
await copcLayer.loadRootNode();

viewer.scene.primitives.add(copcLayer.getPrimitive());

// Drive camera-based LOD/culling every frame
viewer.scene.postRender.addEventListener(() => {
  copcLayer.update(viewer.scene.frameState);
});

With Custom Styling

const copcLayer = new COPCPointCloudProvider({
  url: 'https://example.com/terrain.copc.laz',
  colorMode: 'elevation', // Color by elevation
  pointSize: 3
});

Higher-Quality LOD

const copcLayer = new COPCPointCloudProvider({
  url: 'https://example.com/large-dataset.copc.laz',
  maximumScreenSpaceError: 8 // lower = more detail, more requests
});

Web Worker Decoding

const copcLayer = new COPCPointCloudProvider({
  url: 'https://example.com/large-dataset.copc.laz',
  workerUrl: new URL('../src/workers/laz-decoder.worker.ts', import.meta.url),
  workerPoolSize: 4
});

Color Modes

RGB

Display point cloud with original RGB colors from the COPC file.

Intensity

Display points based on intensity values (grayscale).

Classification

Color points based on ASPRS classification codes:

  • Ground (brown)
  • Vegetation (green shades)
  • Buildings (red)
  • Water (blue)
  • etc.

Elevation

Color points based on Z coordinate (blue = low, red = high).


Performance Tips

Memory Management

  • maximumMemoryUsage bounds the LRU cache of off-screen nodes' decoded data (kept around so revisiting them skips network/decode). It does not bound what's currently visible - a wide view with many simultaneously-visible nodes can still use more memory than this.
  • Lower it on memory-constrained devices; raise it to make camera back-and-forth over the same area cheaper.

LOD Quality

  • maximumScreenSpaceError controls detail level
  • Lower values = more detail, more requests
  • Higher values = less detail, fewer requests
  • Default (16) is good balance for most cases

Point Size

  • Adjust pointSize based on point density
  • Dense clouds: smaller points (1-2 pixels)
  • Sparse clouds: larger points (3-5 pixels)

Browser Compatibility

  • Modern browsers with WebGL support
  • HTTP Range Request support required
  • Web Workers support required only if you opt into workerUrl

Error Handling

try {
  const provider = new COPCPointCloudProvider({ url: 'data.copc.laz' });
  await provider.initialize();
} catch (error) {
  console.error('Failed to load COPC:', error);
}

Common errors:

  • Network errors (404, CORS)
  • Invalid COPC file format
  • Unsupported coordinate systems
  • Memory exhaustion

Advanced Usage

Custom Request Manager

The library uses HTTP Range Requests for efficient streaming (RangeRequestManager). Requests are:

  • Prioritized by node depth (deeper/more-detailed nodes first)
  • Limited to 6 concurrent requests by default
  • Queued (not dropped) once the concurrency limit is reached
  • Cancellable via AbortController, including while still queued

fetchMergedRanges() (merging adjacent byte ranges into one request) exists on RangeRequestManager but isn't wired into the loading path yet - each node is currently fetched as its own request.

Coordinate Systems

Supports automatic transformation from:

  • Korean coordinate systems (EPSG:5186, 5187, 5185)
  • Web Mercator (EPSG:3857)
  • Any projection defined in WKT VLR

Transforms to WGS84/ECEF for Cesium rendering.

Web Workers

Off by default. Set workerUrl to move LAZ decoding into Web Worker threads (4 by default, via workerPoolSize) and keep the main thread free for camera interaction. See the workerUrl option above and demo/autzen.html for a working example.


License

MIT