@giro3d/giro3d
Version:
A JS/WebGL framework for 3D geospatial data visualization
109 lines (102 loc) • 4.27 kB
JavaScript
/*
* Copyright (c) 2015-2018, IGN France.
* Copyright (c) 2018-2026, Giro3D team.
* SPDX-License-Identifier: MIT
*/
import { Color, DataTexture } from 'three';
/**
* Parameters for a point cloud classification.
*/
export class Classification {
/**
* The color of this classification.
*/
/**
* Toggles the visibility of points with this classification.
*/
constructor(color, visible = true) {
this.color = new Color(color);
this.visible = visible;
}
/**
* Clones this classification.
* @returns The cloned object.
*/
clone() {
return new Classification(this.color.clone(), this.visible);
}
}
/**
* A set of 256 pre-defined classifications following the ASPRS scheme, with pre-defined colors for
* classifications 0 to 18. The remaining classifications have the default color (#FF8100)
*
* See https://www.asprs.org/wp-content/uploads/2010/12/LAS_Specification.pdf
*/
export const ASPRS_CLASSIFICATIONS = new Array(256);
const DEFAULT_CLASSIFICATION = new Classification(0xff8100);
for (let i = 0; i < ASPRS_CLASSIFICATIONS.length; i++) {
ASPRS_CLASSIFICATIONS[i] = DEFAULT_CLASSIFICATION.clone();
}
ASPRS_CLASSIFICATIONS[0] = new Classification('#858585'); // Created, never classified
ASPRS_CLASSIFICATIONS[1] = new Classification('#bfbfbf'); // Unclassified
ASPRS_CLASSIFICATIONS[2] = new Classification('#834000'); // Ground
ASPRS_CLASSIFICATIONS[3] = new Classification('#008100'); // Low vegetation
ASPRS_CLASSIFICATIONS[4] = new Classification('#00bf00'); // Medium vegetation
ASPRS_CLASSIFICATIONS[5] = new Classification('#00ff00'); // High vegetation
ASPRS_CLASSIFICATIONS[6] = new Classification('#0081c1'); // Building
ASPRS_CLASSIFICATIONS[7] = new Classification('#ff0000'); // Low point (noise)
ASPRS_CLASSIFICATIONS[8] = DEFAULT_CLASSIFICATION.clone(); // Reserved
ASPRS_CLASSIFICATIONS[9] = new Classification('#0000ff'); // Water
ASPRS_CLASSIFICATIONS[10] = new Classification('#606d73'); // Rail
ASPRS_CLASSIFICATIONS[11] = new Classification('#858585'); // Road surface
ASPRS_CLASSIFICATIONS[12] = DEFAULT_CLASSIFICATION.clone(); // Reserved
ASPRS_CLASSIFICATIONS[13] = new Classification('#ede440'); // Wire - Guard (Shield)
ASPRS_CLASSIFICATIONS[14] = new Classification('#ed6840'); // Wire - Conductor (Phase)
ASPRS_CLASSIFICATIONS[15] = new Classification('#29fff8'); // Transmission Tower
ASPRS_CLASSIFICATIONS[16] = new Classification('#5e441d'); // Wire Structure connector (e.g Insulator)
ASPRS_CLASSIFICATIONS[17] = new Classification('#7992c7'); // Bridge Deck
ASPRS_CLASSIFICATIONS[18] = new Classification('#cd27d6'); // High Noise
export class ClassificationsTexture {
static maxCount = 256;
constructor() {
this.classifications = ASPRS_CLASSIFICATIONS.map(c => c.clone());
this._array = new Uint8Array(4 * ClassificationsTexture.maxCount);
this.texture = new DataTexture(this._array, ClassificationsTexture.maxCount, 1);
}
updateUniform() {
this.sanitizeClassifications();
const temp = new Uint8Array(4);
for (let i = 0; i < ClassificationsTexture.maxCount; i++) {
const classification = this.classifications[i] ?? DEFAULT_CLASSIFICATION;
temp[0] = 255 * classification.color.r;
temp[1] = 255 * classification.color.g;
temp[2] = 255 * classification.color.b;
temp[3] = classification.visible ? 255 : 0;
let classifChanged = false;
const classifOffset = 4 * i;
for (let j = 0; j < 4; j++) {
if (this._array[classifOffset + j] !== temp[j]) {
classifChanged = true;
break;
}
}
if (classifChanged) {
this._array.set(temp, classifOffset);
this.texture.needsUpdate = true;
}
}
}
dispose() {
this.texture.dispose();
}
sanitizeClassifications() {
if (this.classifications.length > ClassificationsTexture.maxCount) {
this.classifications = this.classifications.slice(0, ClassificationsTexture.maxCount);
console.warn(`The provided classification array has been truncated to ${ClassificationsTexture.maxCount} elements`);
} else {
while (this.classifications.length < ClassificationsTexture.maxCount) {
this.classifications.push(DEFAULT_CLASSIFICATION.clone());
}
}
}
}