Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(PointCloudLayer) add points filtre based on classification #2374

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/copc_simple_loader.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</style>

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lil-gui@0.19"></script>
</head>
<body>
<div id="description">Specify the URL of a COPC file to load:
Expand All @@ -38,7 +38,7 @@

const uri = new URL(location);

const gui = new dat.GUI();
const gui = new lil.GUI();

const viewerDiv = document.getElementById('viewerDiv');
const view = new itowns.View('EPSG:4326', viewerDiv);
Expand Down Expand Up @@ -96,7 +96,7 @@
const source = new itowns.CopcSource({ url });

if (layer) {
gui.removeFolder(layer.debugUI);
layer.debugUI.destroy()
view.removeLayer('COPC');
view.notifyChange();
layer.delete();
Expand Down
4 changes: 2 additions & 2 deletions examples/entwine_3d_loader.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</style>

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lil-gui@0.19"></script>
</head>
<body>
<div id="description">Specify the URL of a Entwine Point Tree to load:
Expand All @@ -31,7 +31,7 @@
<script src="js/GUI/LoadingScreen.js"></script>
<script src="../dist/debug.js"></script>
<script type="text/javascript">
var debugGui = new dat.GUI();
var debugGui = new lil.GUI();
var viewerDiv = document.getElementById('viewerDiv');

var view = new itowns.GlobeView(viewerDiv);
Expand Down
16 changes: 10 additions & 6 deletions examples/entwine_simple_loader.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</style>

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lil-gui@0.19"></script>
</head>
<body>
<div id="description">Specify the URL of a Entwine Point Tree to load:
Expand All @@ -33,7 +33,7 @@
<script type="text/javascript">
itowns.proj4.defs('EPSG:3946', '+proj=lcc +lat_0=46 +lon_0=3 +lat_1=45.25 +lat_2=46.75 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs');

var debugGui = new dat.GUI();
var debugGui = new lil.GUI();
var viewerDiv = document.getElementById('viewerDiv');
viewerDiv.style.display = 'block';
var view = new itowns.View('EPSG:3946', viewerDiv);
Expand Down Expand Up @@ -84,12 +84,13 @@
}
}

let eptName;
function loadEPT(url, options) {
eptSource = new itowns.EntwinePointTileSource({ url });

if (eptLayer) {
debugGUI.removeFolder(eptLayer.debugUI);
view.removeLayer('Entwine Point Tile');
eptLayer.debugUI.destroy();
view.removeLayer(eptName);
view.notifyChange();
eptLayer.delete();
}
Expand All @@ -99,7 +100,10 @@
crs: view.referenceCrs,
...options,
}
eptLayer = new itowns.EntwinePointTileLayer('Entwine Point Tile', config);

eptName = url.split('/').pop()
eptName = eptName[0].toUpperCase() + eptName.slice(1);
eptLayer = new itowns.EntwinePointTileLayer(eptName, config);

view.addLayer(eptLayer).then(onLayerReady);

Expand All @@ -121,7 +125,7 @@
}

function loadGrandLyon() {
document.getElementById('ept_url').value = 'https://download.data.grandlyon.com/files/grandlyon/imagerie/mnt2018/lidar/ept/';
document.getElementById('ept_url').value = 'https://download.data.grandlyon.com/files/grandlyon/imagerie/mnt2018/lidar/ept';
readEPTURL();
}

Expand Down
53 changes: 47 additions & 6 deletions src/Renderer/PointsMaterial.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,15 @@ function recomputeTexture(scheme, texture, nbClass) {
for (let i = 0; i < width; i++) {
let color;
let opacity;
let visible = true;

if (scheme[i]) {
color = scheme[i].color;
visible = scheme[i].visible;
opacity = scheme[i].opacity;
} else if (scheme[i % nbClass]) {
color = scheme[i % nbClass].color;
visible = scheme[i % nbClass].visible;
opacity = scheme[i % nbClass].opacity;
} else if (scheme.DEFAULT) {
color = scheme.DEFAULT.color;
visible = scheme.DEFAULT.visible;
opacity = scheme.DEFAULT.opacity;
} else {
color = white;
Expand All @@ -144,9 +140,9 @@ function recomputeTexture(scheme, texture, nbClass) {
data[j + 0] = parseInt(255 * color.r, 10);
data[j + 1] = parseInt(255 * color.g, 10);
data[j + 2] = parseInt(255 * color.b, 10);
data[j + 3] = visible ? parseInt(255 * opacity, 10) : 0;
data[j + 3] = parseInt(255 * opacity, 10);

needTransparency = needTransparency || opacity < 1 || !visible;
needTransparency = needTransparency || opacity < 1;
}
texture.needsUpdate = true;
return needTransparency;
Expand Down Expand Up @@ -256,13 +252,22 @@ class PointsMaterial extends THREE.ShaderMaterial {
textureLUT.magFilter = THREE.NearestFilter;
CommonMaterial.setUniformProperty(this, 'discreteTexture', textureLUT);

// add texture to apply visibility.
const dataVisi = new Uint8Array(256 * 1);
const textureVisi = new THREE.DataTexture(dataVisi, 256, 1, THREE.RedFormat);

textureVisi.needsUpdate = true;
textureVisi.magFilter = THREE.NearestFilter;
CommonMaterial.setUniformProperty(this, 'visiTexture', textureVisi);

// Classification and other discrete values scheme
this.classificationScheme = classificationScheme;
this.discreteScheme = discreteScheme;

// Update classification and discrete Texture
this.recomputeClassification();
this.recomputeDiscreteTexture();
this.recomputeVisibleTexture();

// Gradient texture for continuous values
this.gradient = gradient;
Expand Down Expand Up @@ -391,6 +396,42 @@ class PointsMaterial extends THREE.ShaderMaterial {
});
}

recomputeVisibleTexture() {
let needTransparency;
const texture = this.visiTexture;
const scheme = this.classificationScheme;

const data = texture.image.data;
const width = texture.image.width;

for (let i = 0; i < width; i++) {
let visible;

if (scheme[i]) {
visible = scheme[i].visible;
} else if (scheme.DEFAULT) {
visible = scheme.DEFAULT.visible;
} else {
visible = true;
}

data[i] = visible ? 255 : 0;
needTransparency = needTransparency || visible === false;
}
texture.needsUpdate = true;

this.userData.needTransparency[PNTS_MODE.CLASSIFICATION] = needTransparency;
this.userData.needTransparency[PNTS_MODE.RETURN_NUMBER] = needTransparency;
this.userData.needTransparency[PNTS_MODE.RETURN_TYPE] = needTransparency;
this.userData.needTransparency[PNTS_MODE.RETURN_COUNT] = needTransparency;
this.userData.needTransparency[PNTS_MODE.POINT_SOURCE_ID] = needTransparency;

this.dispatchEvent({
type: 'material_property_changed',
target: this.uniforms,
});
}

enablePicking(picking) {
this.picking = picking;
this.blending = picking ? THREE.NoBlending : THREE.NormalBlending;
Expand Down
13 changes: 10 additions & 3 deletions src/Renderer/Shader/PointsVS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ varying vec4 vColor; // color_pars_vertex
uniform mat3 uvTransform;
#endif

#define NB_CLASS 8.
#define SOURCE_ID_GROUP 8.

uniform float size;
uniform float scale;
Expand All @@ -25,6 +25,8 @@ uniform vec2 angleRange;
uniform sampler2D classificationTexture;
uniform sampler2D discreteTexture;
uniform sampler2D gradientTexture;
uniform sampler2D visiTexture;

uniform int sizeMode;
uniform float minAttenuatedSize;
uniform float maxAttenuatedSize;
Expand All @@ -39,12 +41,13 @@ attribute float numberOfReturns;
attribute float scanAngle;

void main() {
vec2 uv = vec2(classification/255., 0.5);

vColor = vec4(1.0);
if (picking) {
vColor = unique_id;
} else {
if (mode == PNTS_MODE_CLASSIFICATION) {
vec2 uv = vec2(classification/255., 0.5);
vColor = texture2D(classificationTexture, uv);
} else if (mode == PNTS_MODE_NORMAL) {
vColor.rgb = abs(normal);
Expand Down Expand Up @@ -84,7 +87,7 @@ void main() {
vec2 uv = vec2(numberOfReturns/255., 0.5);
vColor = texture2D(discreteTexture, uv);
} else if (mode == PNTS_MODE_POINT_SOURCE_ID) {
vec2 uv = vec2(mod(pointSourceID, NB_CLASS)/255., 0.5);
vec2 uv = vec2(mod(pointSourceID, SOURCE_ID_GROUP)/255., 0.5);
vColor = texture2D(discreteTexture, uv);
} else if (mode == PNTS_MODE_SCAN_ANGLE) {
float i = (scanAngle - angleRange.x) / (angleRange.y - angleRange.x);
Expand All @@ -102,6 +105,10 @@ void main() {
}
}

if (texture2D(visiTexture, uv).r == 0.) {
vColor.a = 0.;
}

#define USE_COLOR_ALPHA
#include <morphcolor_vertex>
#include <begin_vertex>
Expand Down
78 changes: 35 additions & 43 deletions utils/debug/PointCloudDebug.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,55 @@
import { PNTS_MODE, PNTS_SHAPE, PNTS_SIZE_MODE } from 'Renderer/PointsMaterial';

const folderName = 'Styling';

function getController(gui, name) {
let controller = null;
const controllers = gui.__folders.Styling.__controllers;
for (let i = 0; i < controllers.length; i += 1) {
const c = controllers[i];
if (c.property === name || c.name === name) {
controller = c;
break;
}
}
const controllers = gui.folders.filter(f => f._title === folderName)[0].controllers;
const controller = controllers.filter(c => (c.property === name || c.name === name))[0];
return controller;
}

function hideController(gui, name) {
const controller = getController(gui, name);
if (controller) {
controller.__li.style.display = 'none';
}
}

function showController(gui, name) {
const controller = getController(gui, name);
if (controller) {
controller.__li.style.display = '';
}
}

function setupControllerVisibily(gui, displayMode, sizeMode) {
displayMode = parseInt(displayMode, 10);
if ([PNTS_MODE.INTENSITY, PNTS_MODE.ELEVATION, PNTS_MODE.SCAN_ANGLE].includes(displayMode)) {
showController(gui, 'gradient');
getController(gui, 'gradient').show();
} else {
hideController(gui, 'gradient');
getController(gui, 'gradient').hide();
}
if (PNTS_MODE.INTENSITY === displayMode) {
showController(gui, 'minIntensityRange');
showController(gui, 'maxIntensityRange');
getController(gui, 'minIntensityRange').show();
getController(gui, 'maxIntensityRange').show();
} else {
hideController(gui, 'minIntensityRange');
hideController(gui, 'maxIntensityRange');
getController(gui, 'minIntensityRange').hide();
getController(gui, 'maxIntensityRange').hide();
}
if (PNTS_MODE.ELEVATION === displayMode) {
showController(gui, 'minElevationRange');
showController(gui, 'maxElevationRange');
getController(gui, 'minElevationRange').show();
getController(gui, 'maxElevationRange').show();
} else {
hideController(gui, 'minElevationRange');
hideController(gui, 'maxElevationRange');
getController(gui, 'minElevationRange').hide();
getController(gui, 'maxElevationRange').hide();
}
if (PNTS_MODE.SCAN_ANGLE === displayMode) {
showController(gui, 'minAngleRange');
showController(gui, 'maxAngleRange');
getController(gui, 'minAngleRange').show();
getController(gui, 'maxAngleRange').show();
} else {
hideController(gui, 'minAngleRange');
hideController(gui, 'maxAngleRange');
getController(gui, 'minAngleRange').hide();
getController(gui, 'maxAngleRange').hide();
}

sizeMode = parseInt(sizeMode, 10);
if (sizeMode === PNTS_SIZE_MODE.VALUE) {
hideController(gui, 'minAttenuatedSize');
hideController(gui, 'maxAttenuatedSize');
getController(gui, 'minAttenuatedSize').hide();
getController(gui, 'maxAttenuatedSize').hide();
} else {
showController(gui, 'minAttenuatedSize');
showController(gui, 'maxAttenuatedSize');
getController(gui, 'minAttenuatedSize').show();
getController(gui, 'maxAttenuatedSize').show();
}
}

export default {
initTools(view, layer, datUi) {
datUi.title('Layer Controls');
layer.debugUI = datUi.addFolder(`${layer.id}`);

const update = () => {
Expand All @@ -89,7 +71,7 @@ export default {
layer.dbgDisplayChildren = true;
layer.dbgDisplayParents = true;

const styleUI = layer.debugUI.addFolder('Styling');
const styleUI = layer.debugUI.addFolder(folderName).close();
if (layer.material.mode != undefined) {
const modeNames = Object.keys(PNTS_MODE);
const mode = modeNames.filter(v => PNTS_MODE[v] === layer.material.mode)[0];
Expand All @@ -98,6 +80,16 @@ export default {
layer.material.mode = PNTS_MODE[value];
update();
});

const classeUI = styleUI.addFolder('Classe Visibility').close();
Object.entries(layer.material.classificationScheme).forEach((classe) => {
classeUI.add(classe[1], 'visible').name(classe[1].name)
.onChange(() => {
layer.material.recomputeVisibleTexture();
update();
});
});

const gradiantsNames = Object.keys(layer.material.gradients);
styleUI.add({ gradient: gradiantsNames[0] }, 'gradient', gradiantsNames).name('gradient')
.onChange((value) => {
Expand Down Expand Up @@ -184,7 +176,7 @@ export default {
}

// UI
const debugUI = layer.debugUI.addFolder('Debug');
const debugUI = layer.debugUI.addFolder('Debug').close();
debugUI.add(layer.bboxes, 'visible').name('Display Bounding Boxes').onChange(update);
debugUI.add(layer, 'dbgStickyNode').name('Sticky node name').onChange(update);
debugUI.add(layer, 'dbgDisplaySticky').name('Display sticky node').onChange(update);
Expand Down
Loading