npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

maplibre-copc-layer

v0.2.0

Published

A library for loading and rendering Cloud-Optimized Point Cloud (COPC) data in MapLibre GL JS using Three.js.

Readme

maplibre-copc-layer

npm version license

A MapLibre GL JS custom layer for streaming and rendering Cloud-Optimized Point Cloud (COPC) data, powered by Three.js.

Only the tiles visible on screen are fetched via SSE-based LOD, enabling smooth visualization of massive point clouds in the browser.

Live Demo

Features

  • Streaming LOD — Screen-space error based level-of-detail fetches only what you see
  • Web Worker — COPC decoding and coordinate reprojection run off the main thread
  • LRU cache — Configurable node count and memory limits
  • Ambient Occlusion — SSAO post-processing for depth perception
  • Color modes — RGB, height ramp, intensity, classification, and white
  • Custom color expressions — User-defined linear/discrete color ramps for height and intensity
  • Filtering — By classification, intensity range, or bounding box (WGS84)

Install

npm install maplibre-copc-layer maplibre-gl three

Usage

import maplibregl from 'maplibre-gl';
import { CopcLayer } from 'maplibre-copc-layer';

const map = new maplibregl.Map({
  container: 'map',
  style: 'https://demotiles.maplibre.org/style.json',
  center: [139.7, 35.7],
  zoom: 14,
});

const layer = new CopcLayer('https://example.com/pointcloud.copc.laz', {
  colorMode: 'rgb',
  pointSize: 4,
  enableSSAO: true,
  onInitialized: ({ bounds }) => map.flyTo({
    center: [(bounds.minx + bounds.maxx) / 2, (bounds.miny + bounds.maxy) / 2],
    zoom: 16,
  }),
});

map.on('load', () => map.addLayer(layer));

API

new CopcLayer(url, options?, layerId?)

| Option | Type | Default | Description | |---|---|---|---| | pointSize | number | 6 | Point size in pixels | | colorMode | 'rgb' \| 'height' \| 'intensity' \| 'classification' \| 'white' | 'rgb' | Coloring mode | | heightColor | ColorExpression | auto | Color ramp for height mode. Default: blue→yellow→red across data bounds | | intensityColor | ColorExpression | auto | Color ramp for intensity mode. Default: black→white (0–1) | | classificationColors | Record<number, RGBColor> | ASPRS defaults | Classification code colors (0–1 RGB) | | filter | PointFilter | {} | Filter points by classification, intensity range, or bounding box | | alwaysShowRoot | boolean | false | Always show root node even when SSE is below threshold | | sseThreshold | number | 8 | SSE threshold for LOD — lower loads more detail | | depthTest | boolean | true | Enable depth testing | | maxCacheSize | number | 100 | Max cached nodes | | maxCacheMemory | number | 104857600 | Max cache memory in bytes (100 MB) | | enableSSAO | boolean | false | Enable Screen Space Ambient Occlusion | | ssaoStrength | number | 1.0 | SSAO effect strength | | ssaoRadius | number | 8.0 | SSAO sampling radius in pixels | | debug | boolean | false | Enable debug logging | | onInitialized | (msg) => void | — | Called with { nodeCount, bounds } after COPC header loads. bounds contains minx/maxx/miny/maxy/minz/maxz in WGS84 |

Methods

| Method | Description | |---|---| | setPointSize(size) | Update point size | | setColorMode(mode) | Switch color mode without reloading data | | setHeightColor(expr) | Update height color expression (instant, no reload) | | setIntensityColor(expr) | Update intensity color expression (instant, no reload) | | setClassificationColors(colors) | Update classification colors (instant, no reload) | | setSseThreshold(threshold) | Update SSE threshold | | setDepthTest(enabled) | Toggle depth testing | | setSSAOEnabled(enabled) | Toggle Screen Space Ambient Occlusion | | setSSAOParameters({ strength?, radius? }) | Update SSAO parameters | | setFilter(filter) | Update point filter (classification / intensity / bbox) | | getFilter() | Get current point filter | | setCacheConfig(config) | Update cache limits at runtime | | clearCache() | Clear all cached nodes | | isLoading() | Whether data is currently being fetched | | getNodeStats() | Returns { loaded, visible } node counts |

Examples

Height-based coloring with custom color ramp

ColorExpression uses a MapLibre Style-like syntax: ["linear", stop, color, stop, color, ...] or ["discrete", ...].

const layer = new CopcLayer('https://example.com/pointcloud.copc.laz', {
  colorMode: 'height',
  // Linear interpolation: blue at 0m, green at 50m, red at 100m
  heightColor: ['linear', 0, [0, 0, 1], 50, [0, 1, 0], 100, [1, 0, 0]],
});

Discrete height coloring

const layer = new CopcLayer('https://example.com/pointcloud.copc.laz', {
  colorMode: 'height',
  // Step function: blue below 50m, green 50-100m, red above 100m
  heightColor: ['discrete', 0, [0, 0, 1], 50, [0, 1, 0], 100, [1, 0, 0]],
});

Custom intensity coloring

const layer = new CopcLayer('https://example.com/pointcloud.copc.laz', {
  colorMode: 'intensity',
  // Intensity values are normalized 0-1
  intensityColor: ['linear', 0, [0, 0, 0.2], 0.5, [1, 1, 0], 1, [1, 0, 0]],
});

Updating colors at runtime (no data reload)

// Switch color mode instantly
layer.setColorMode('height');

// Update height color ramp — reflected immediately
layer.setHeightColor(['linear', 0, [1, 1, 1], 200, [1, 0, 0]]);

// Update classification colors
layer.setClassificationColors({
  2: [0.4, 0.2, 0.1],  // Ground: brown
  6: [0.8, 0.1, 0.1],  // Building: red
});

Filtering points

const layer = new CopcLayer('https://example.com/pointcloud.copc.laz', {
  filter: {
    // Show only ground and buildings
    classification: new Set([2, 6]),
    // Intensity range (0-1)
    intensityRange: [0.1, 0.9],
    // Bounding box in WGS84
    bbox: { minx: 139.7, maxx: 139.8, miny: 35.6, maxy: 35.7 },
  },
});

// Update filter at runtime
layer.setFilter({
  classification: new Set([2, 3, 4, 5, 6]),
});

Ambient Occlusion

const layer = new CopcLayer('https://example.com/pointcloud.copc.laz', {
  enableSSAO: true,
  ssaoStrength: 1.0,
  ssaoRadius: 8.0,
});

Development

pnpm install
pnpm dev       # Dev server with demo app
pnpm test      # Run tests
pnpm build     # Build library

Third-Party Notices

This project bundles laz-perf (Apache License 2.0).

License

Apache-2.0