pointcloud-viewer
Un nuage LiDAR lu en Rust compilé en WebAssembly, puis posé sur la carte par three.js : tout se passe dans le navigateur.
- Stack
- Rust · WASM · React · three.js
- Année
- 2026
Anatomie
7 pièces · une seule les compteChoisir le fichier
Un .las ou un .laz part à la conversion ; un .bin déjà converti s’ouvre aussitôt.
openFile()78
const openFile = useCallback(79
(file: File) => {80
if (/\.(bin|pcbk)$/i.test(file.name)) {Travailler en arrière-plan
Lance la conversion à part, sans figer la page, puis rend le résultat sans le recopier.
self.onmessage13
let wasmReady: Promise<unknown> | null = null15
self.onmessage = async (event: MessageEvent<BakeRequest>) => {16
const post = (message: BakeWorkerMessage, transfer: Transferable[] = []) =>Convertir les points
Rust relit chaque point et le recentre sur le coin du nuage pour rester précis en 32 bits.
bake_to_pcbk()48
pub fn bake_to_pcbk(49
las_bytes: Vec<u8>,50
mut on_progress: impl FnMut(u64, u64),Lire le format maison
Un en-tête de 72 octets, puis 18 octets par point, lus sur place sans rien décoder.
parseBakedPointCloud()41
export function parseBakedPointCloud(buffer: ArrayBuffer): BakedPointCloud {42
if (buffer.byteLength < HEADER_SIZE) {43
throw new Error('PCBK buffer is smaller than its header')Placer le nuage sur la carte
Seul le coin du nuage passe du Lambert-93 au GPS ; tous les points s’y accrochent.
computeAnchor()22
export function computeAnchor(cloud: BakedPointCloud, epsg: number): Anchor {23
const { worldOffset, bboxMin, bboxMax } = cloud24
const lngLat = toWgs84(epsg, worldOffset.x, worldOffset.y)Dessiner les points
three.js dessine le nuage par-dessus le fond de carte, en un seul envoi au GPU.
PointCloudLayer25
export class PointCloudLayer implements CustomLayerInterface {26
readonly id = 'pointcloud'27
readonly type = 'custom' as constChanger les couleurs
RGB, intensité, classe ou altitude : une seule valeur change, les points restent.
createPointsMaterial()127
export function createPointsMaterial(128
cloud: BakedPointCloud,129
mode: ColorMode,
Visez le terrain : la tête tourne vers le pointeur · clic sur la roue : couleurTouchez le terrain : la tête tourne jusqu’au point · toucher la roue : couleur
Nomenclature
- 01 Carte LAS/LAZ Le fichier choisi. Un .las ou un .laz part au bake dans un Worker, un .bin déjà cuit s’ouvre sur place. Code : src/hooks/use-bake.ts, lignes 78–87 ↗
- 02 Boîtier scellé Le Web Worker : il lit les octets du fichier, initialise le WebAssembly une seule fois, remonte la progression et rend le PCBK par transfert, sans copie. Code : src/workers/bake-worker.ts, lignes 13–37 ↗
- 03 Tambour du miroir Le bake Rust compilé en WebAssembly : il parcourt les points du LAS/LAZ, les recentre sur le minimum par axe pour qu’ils restent précis en f32, puis écrit l’en-tête de 72 octets et les blocs planaires. Code : webassembly/src/lib.rs, lignes 48–132 ↗
- 04 Disque PCBK Le format maison : vérifie le magic et la version, puis pose des vues TypedArray sur le buffer, sans rien décoder. Code : src/lib/baked-pointcloud.ts, lignes 41–91 ↗
- 05 Borne d’angle L’ancre : seul le World Offset est reprojeté (proj4 vers WGS84, puis Mercator), et tout le nuage se place autour de lui. Code : src/lib/map-anchor.ts, lignes 22–46 ↗
- 06 Nuage de points Le calque three.js sur le contexte WebGL de MapLibre : positions envoyées telles quelles, matrices composées en doubles à chaque image. Code : src/lib/pointcloud-layer.ts, lignes 25–121 ↗
- 07 Roue de filtres Le mode de couleur (RGB, intensité, classification, altitude) : un uniform change, la géométrie reste. Code : src/lib/pointcloud-shaders.ts, lignes 127–156 ↗