Skip to content

Commit

Permalink
fix(PointCloud): fix precision error for entwinePointTileLayer
Browse files Browse the repository at this point in the history
(cherry picked from commit 7eaff5c)
  • Loading branch information
ftoromanoff committed Mar 11, 2024
1 parent 06c7181 commit bf38a72
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 30 deletions.
1 change: 1 addition & 0 deletions src/Layer/EntwinePointTileLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class EntwinePointTileLayer extends PointCloudLayer {
constructor(id, config) {
super(id, config);
this.isEntwinePointTileLayer = true;
this.scale = new THREE.Vector3(1, 1, 1);

const resolve = this.addInitializationStep();
this.whenReady = this.source.whenReady.then(() => {
Expand Down
10 changes: 7 additions & 3 deletions src/Parser/LASLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,16 @@ class LASLoader {
*/
const scanAngles = new Float32Array(view.pointCount);

// For precision we take the first point that will be use as origin for a local referentiel.
const origin = getPosition.map(f => f(0)).map(val => Math.floor(val));

for (let i = 0; i < view.pointCount; i++) {
// `getPosition` apply scale and offset transform to the X, Y, Z
// values. See https://github.com/connormanning/copc.js/blob/master/src/las/extractor.ts.
const [x, y, z] = getPosition.map(f => f(i));
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
positions[i * 3] = x - origin[0];
positions[i * 3 + 1] = y - origin[1];
positions[i * 3 + 2] = z - origin[2];

intensities[i] = getIntensity(i);
returnNumbers[i] = getReturnNumber(i);
Expand Down Expand Up @@ -115,6 +118,7 @@ class LASLoader {
pointSourceID: pointSourceIDs,
color: colors,
scanAngle: scanAngles,
origin,
};
}

Expand Down
1 change: 1 addition & 0 deletions src/Parser/LASParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export default {
geometry.setAttribute('scanAngle', scanAngle);

geometry.computeBoundingBox();
geometry.userData.origin = new THREE.Vector3().fromArray(attributes.origin);
return geometry;
});
},
Expand Down
10 changes: 5 additions & 5 deletions src/Parser/PotreeBinParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as THREE from 'three';

// See the different constants holding ordinal, name, numElements, byteSize in PointAttributes.cpp in PotreeConverter
// elementByteSize is byteSize / numElements
const POINT_ATTTRIBUTES = {
const POINT_ATTRIBUTES = {
POSITION_CARTESIAN: {
numElements: 3,
arrayType: Float32Array,
Expand Down Expand Up @@ -49,8 +49,8 @@ const POINT_ATTTRIBUTES = {
},
};

for (const potreeName of Object.keys(POINT_ATTTRIBUTES)) {
const attr = POINT_ATTTRIBUTES[potreeName];
for (const potreeName of Object.keys(POINT_ATTRIBUTES)) {
const attr = POINT_ATTRIBUTES[potreeName];
attr.potreeName = potreeName;
attr.numByte = attr.numByte || attr.arrayType.BYTES_PER_ELEMENT;
attr.byteSize = attr.numElements * attr.numByte;
Expand Down Expand Up @@ -81,15 +81,15 @@ export default {
// Format: X1,Y1,Z1,R1,G1,B1,A1,[...],XN,YN,ZN,RN,GN,BN,AN
let pointByteSize = 0;
for (const potreeName of options.in.pointAttributes) {
pointByteSize += POINT_ATTTRIBUTES[potreeName].byteSize;
pointByteSize += POINT_ATTRIBUTES[potreeName].byteSize;
}
const numPoints = Math.floor(buffer.byteLength / pointByteSize);

const geometry = new THREE.BufferGeometry();
let elemOffset = 0;
let attrOffset = 0;
for (const potreeName of options.in.pointAttributes) {
const attr = POINT_ATTTRIBUTES[potreeName];
const attr = POINT_ATTRIBUTES[potreeName];
const arrayLength = attr.numElements * numPoints;
const array = new attr.arrayType(arrayLength);
for (let arrayOffset = 0; arrayOffset < arrayLength; arrayOffset += attr.numElements) {
Expand Down
6 changes: 2 additions & 4 deletions src/Provider/PointCloudProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ export default {
addPickingAttribute(points);
points.frustumCulled = false;
points.matrixAutoUpdate = false;
if (!layer.isEntwinePointTileLayer) {
points.position.copy(node.bbox.min);
points.scale.copy(layer.scale);
}
points.position.copy(geometry.userData.origin || node.bbox.min);
points.scale.copy(layer.scale);
points.updateMatrix();
points.tightbbox = geometry.boundingBox.applyMatrix4(points.matrix);
points.layer = layer;
Expand Down
36 changes: 18 additions & 18 deletions test/unit/lasparser.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ describe('LASParser', function () {
assert.strictEqual(bufferGeometry.attributes.classification.count, bufferGeometry.userData.pointCount);
assert.strictEqual(bufferGeometry.attributes.color, undefined);

assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.x, bufferGeometry.userData.min[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.y, bufferGeometry.userData.min[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.z, bufferGeometry.userData.min[2], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.x, bufferGeometry.userData.max[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.y, bufferGeometry.userData.max[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.z, bufferGeometry.userData.max[2], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.x + bufferGeometry.userData.origin.x, bufferGeometry.userData.min[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.y + bufferGeometry.userData.origin.y, bufferGeometry.userData.min[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.z + bufferGeometry.userData.origin.z, bufferGeometry.userData.min[2], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.x + bufferGeometry.userData.origin.x, bufferGeometry.userData.max[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.y + bufferGeometry.userData.origin.y, bufferGeometry.userData.max[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.z + bufferGeometry.userData.origin.z, bufferGeometry.userData.max[2], 0.1));
});

describe('parses a laz file to a THREE.BufferGeometry', function () {
Expand All @@ -43,12 +43,12 @@ describe('LASParser', function () {
assert.strictEqual(bufferGeometry.attributes.classification.count, bufferGeometry.userData.pointCount);
assert.strictEqual(bufferGeometry.attributes.color, undefined);

assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.x, bufferGeometry.userData.min[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.y, bufferGeometry.userData.min[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.z, bufferGeometry.userData.min[2], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.x, bufferGeometry.userData.max[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.y, bufferGeometry.userData.max[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.z, bufferGeometry.userData.max[2], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.x + bufferGeometry.userData.origin.x, bufferGeometry.userData.min[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.y + bufferGeometry.userData.origin.y, bufferGeometry.userData.min[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.z + bufferGeometry.userData.origin.z, bufferGeometry.userData.min[2], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.x + bufferGeometry.userData.origin.x, bufferGeometry.userData.max[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.y + bufferGeometry.userData.origin.y, bufferGeometry.userData.max[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.z + bufferGeometry.userData.origin.z, bufferGeometry.userData.max[2], 0.1));
});

it('laz v1.4', async () => {
Expand All @@ -59,12 +59,12 @@ describe('LASParser', function () {
assert.strictEqual(bufferGeometry.attributes.classification.count, bufferGeometry.userData.pointCount);
assert.strictEqual(bufferGeometry.attributes.color.count, bufferGeometry.userData.pointCount);

assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.x, bufferGeometry.userData.min[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.y, bufferGeometry.userData.min[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.z, bufferGeometry.userData.min[2], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.x, bufferGeometry.userData.max[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.y, bufferGeometry.userData.max[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.z, bufferGeometry.userData.max[2], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.x + bufferGeometry.userData.origin.x, bufferGeometry.userData.min[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.y + bufferGeometry.userData.origin.y, bufferGeometry.userData.min[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.min.z + bufferGeometry.userData.origin.z, bufferGeometry.userData.min[2], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.x + bufferGeometry.userData.origin.x, bufferGeometry.userData.max[0], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.y + bufferGeometry.userData.origin.y, bufferGeometry.userData.max[1], 0.1));
assert.ok(compareWithEpsilon(bufferGeometry.boundingBox.max.z + bufferGeometry.userData.origin.z, bufferGeometry.userData.max[2], 0.1));
});
});
});

0 comments on commit bf38a72

Please sign in to comment.