Skip to content

Commit 9643de9

Browse files
committed
feat(pointcloud): use 'changeSource' mechanism to avoid useless work
Implements a simple logic to avoid updating the full layer if we already know that the result won't change. This feature is already implemented for tile based layers (see 3f340b9).
1 parent d6a74ed commit 9643de9

3 files changed

Lines changed: 114 additions & 9 deletions

File tree

src/Process/PointCloudProcessing.js

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,18 +163,49 @@ function markForDeletion(elt) {
163163
}
164164

165165
export default {
166-
preUpdate(context, layer) {
167-
// TODO: use changeSource
168-
layer.counters = {
169-
pointCount: 0,
170-
displayedCount: 0,
171-
};
172-
166+
preUpdate(context, layer, changeSources) {
173167
// Bail-out if not ready
174168
if (!layer.root) {
175169
return [];
176170
}
177171

172+
if (changeSources.has(undefined) || changeSources.size == 0) {
173+
return [layer.root];
174+
}
175+
176+
// lookup lowest common ancestor of changeSources
177+
let commonAncestorName;
178+
for (const source of changeSources.values()) {
179+
if (source.isCamera) {
180+
// if the change is caused by a camera move, no need to bother
181+
// to find common ancestor: we need to update the whole tree:
182+
// some invisible tiles may now be visible
183+
return [layer.root];
184+
}
185+
if (source.obj === undefined) {
186+
continue;
187+
}
188+
if (source.obj.isPoints && source.obj.layer == layer.id) {
189+
if (!commonAncestorName) {
190+
commonAncestorName = source.name;
191+
} else {
192+
let i;
193+
for (i = 0; i < Math.min(source.name.length, commonAncestorName.length); i++) {
194+
if (source.name[i] != commonAncestorName[i]) {
195+
break;
196+
}
197+
}
198+
commonAncestorName = commonAncestorName.substr(0, i);
199+
if (commonAncestorName.length == 0) {
200+
break;
201+
}
202+
}
203+
}
204+
}
205+
if (commonAncestorName && commonAncestorName.length > 0) {
206+
return [layer.root.findChildrenByName(commonAncestorName)];
207+
}
208+
178209
// Start updating from hierarchy root
179210
return [layer.root];
180211
},
@@ -205,8 +236,6 @@ export default {
205236
}
206237
const count = Math.max(1.0, Math.floor(shouldBeLoaded * elt.obj.geometry.attributes.position.count));
207238
elt.obj.geometry.setDrawRange(0, count);
208-
layer.counters.pointCount += elt.obj.realPointCount;
209-
layer.counters.displayedCount += Math.floor(shouldBeLoaded * elt.obj.geometry.attributes.position.count);
210239
elt.obj.material.uniforms.size.value = layer.pointSize;
211240
} else if (!elt.promise) {
212241
// TODO:
@@ -261,6 +290,13 @@ export default {
261290
return;
262291
}
263292

293+
layer.counters = {
294+
displayedCount: 0,
295+
};
296+
for (const pts of layer.group.children) {
297+
layer.counters.displayedCount += pts.geometry.drawRange.count;
298+
}
299+
264300
if (layer.counters.displayedCount > layer.pointBudget) {
265301
const reduction = layer.pointBudget / layer.counters.displayedCount;
266302
for (const pts of layer.group.children) {

src/Provider/PointCloudProvider.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ function parseOctree(layer, hierarchyStepSize, root) {
9494
});
9595
}
9696

97+
function findChildrenByName(node, name) {
98+
if (node.name === name) {
99+
return node;
100+
}
101+
const charIndex = node.name.length;
102+
for (let i = 0; i < node.children.length; i++) {
103+
if (node.children[i].name[charIndex] == name[charIndex]) {
104+
return findChildrenByName(node.children[i], name);
105+
}
106+
}
107+
throw new Error(`Cannot find node with name '${name}'`);
108+
}
109+
97110
let nextuuid = 1;
98111
function addPickingAttribute(points) {
99112
// generate unique id for picking
@@ -206,6 +219,8 @@ export default {
206219
// eslint-disable-next-line no-console
207220
console.log('LAYER metadata:', root);
208221
layer.root = root;
222+
root.findChildrenByName = findChildrenByName.bind(root, root);
223+
209224
return layer;
210225
});
211226
},
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import PointCloudProcessing from '../src/Process/PointCloudProcessing';
2+
/* global describe, it */
3+
4+
const assert = require('assert');
5+
6+
describe('preUpdate', function () {
7+
it('should return root if no change source', () => {
8+
const layer = { root: {} };
9+
const sources = new Set();
10+
assert.equal(
11+
layer.root,
12+
PointCloudProcessing.preUpdate(null, layer, sources)[0]);
13+
});
14+
15+
it('should return root if no common ancestors', () => {
16+
const layer = { root: {}, id: 'a' };
17+
const elt1 = { name: '12', obj: { layer: 'a', isPoints: true } };
18+
const elt2 = { name: '345', obj: { layer: 'a', isPoints: true } };
19+
const sources = new Set();
20+
sources.add(elt1);
21+
sources.add(elt2);
22+
assert.equal(
23+
layer.root,
24+
PointCloudProcessing.preUpdate(null, layer, sources)[0]);
25+
});
26+
27+
it('should return common ancestor', () => {
28+
const layer = { root: {}, id: 'a' };
29+
const elt1 = { name: '123', obj: { layer: 'a', isPoints: true } };
30+
const elt2 = { name: '12567', obj: { layer: 'a', isPoints: true } };
31+
const elt3 = { name: '122', obj: { layer: 'a', isPoints: true } };
32+
const sources = new Set();
33+
sources.add(elt1);
34+
sources.add(elt2);
35+
sources.add(elt3);
36+
layer.root.findChildrenByName = (name) => {
37+
assert.equal('12', name);
38+
};
39+
PointCloudProcessing.preUpdate(null, layer, sources);
40+
});
41+
42+
it('should not search ancestors if layer are different root if no common ancestors', () => {
43+
const layer = { root: {}, id: 'a' };
44+
const elt1 = { name: '12', obj: { layer: 'a', isPoints: true } };
45+
const elt2 = { name: '13', obj: { layer: 'b', isPoints: true } };
46+
const sources = new Set();
47+
sources.add(elt1);
48+
sources.add(elt2);
49+
layer.root.findChildrenByName = (name) => {
50+
assert.equal('12', name);
51+
};
52+
PointCloudProcessing.preUpdate(null, layer, sources);
53+
});
54+
});

0 commit comments

Comments
 (0)