UNPKG

potree

Version:

WebGL point cloud viewer - WORK IN PROGRESS

149 lines (110 loc) 3.8 kB
Potree.LASExporter = class LASExporter { static toLAS (points) { // TODO Unused: let string = ''; let boundingBox = points.boundingBox; let offset = boundingBox.min.clone(); let diagonal = boundingBox.min.distanceTo(boundingBox.max); let scale = new THREE.Vector3(0.001, 0.001, 0.001); if (diagonal > 1000 * 1000) { scale = new THREE.Vector3(0.01, 0.01, 0.01); } else { scale = new THREE.Vector3(0.001, 0.001, 0.001); } let setString = function (string, offset, buffer) { let view = new Uint8Array(buffer); for (let i = 0; i < string.length; i++) { let charCode = string.charCodeAt(i); view[offset + i] = charCode; } }; let buffer = new ArrayBuffer(227 + 28 * points.numPoints); let view = new DataView(buffer); let u8View = new Uint8Array(buffer); // let u16View = new Uint16Array(buffer); setString('LASF', 0, buffer); u8View[24] = 1; u8View[25] = 2; // system identifier o:26 l:32 // generating software o:58 l:32 setString('Potree 1.5', 58, buffer); // file creation day of year o:90 l:2 // file creation year o:92 l:2 // header size o:94 l:2 view.setUint16(94, 227, true); // offset to point data o:96 l:4 view.setUint32(96, 227, true); // number of letiable length records o:100 l:4 // point data record format 104 1 u8View[104] = 2; // point data record length 105 2 view.setUint16(105, 28, true); // number of point records 107 4 view.setUint32(107, points.numPoints, true); // number of points by return 111 20 // x scale factor 131 8 view.setFloat64(131, scale.x, true); // y scale factor 139 8 view.setFloat64(139, scale.y, true); // z scale factor 147 8 view.setFloat64(147, scale.z, true); // x offset 155 8 view.setFloat64(155, offset.x, true); // y offset 163 8 view.setFloat64(163, offset.y, true); // z offset 171 8 view.setFloat64(171, offset.z, true); // max x 179 8 view.setFloat64(179, boundingBox.max.x, true); // min x 187 8 view.setFloat64(187, boundingBox.min.x, true); // max y 195 8 view.setFloat64(195, boundingBox.max.y, true); // min y 203 8 view.setFloat64(203, boundingBox.min.y, true); // max z 211 8 view.setFloat64(211, boundingBox.max.z, true); // min z 219 8 view.setFloat64(219, boundingBox.min.z, true); let boffset = 227; for (let i = 0; i < points.numPoints; i++) { // let point = points[i]; // let position = new THREE.Vector3(point.x, point.y, point.z); let px = points.data.position[3 * i + 0]; let py = points.data.position[3 * i + 1]; let pz = points.data.position[3 * i + 2]; let ux = parseInt((px - offset.x) / scale.x); let uy = parseInt((py - offset.y) / scale.y); let uz = parseInt((pz - offset.z) / scale.z); view.setUint32(boffset + 0, ux, true); view.setUint32(boffset + 4, uy, true); view.setUint32(boffset + 8, uz, true); if (points.data.intensity) { view.setUint16(boffset + 12, (points.data.intensity[i]), true); } let rt = 0; if (points.data.returnNumber) { rt += points.data.returnNumber[i]; } if (points.data.numberOfReturns) { rt += (points.data.numberOfReturns[i] << 3); } view.setUint8(boffset + 14, rt); if (points.data.classification) { view.setUint8(boffset + 15, points.data.classification[i]); } // scan angle rank // user data // point source id if (points.data.pointSourceID) { view.setUint16(boffset + 18, points.data.pointSourceID[i]); } if (points.data.color) { view.setUint16(boffset + 20, (points.data.color[3 * i + 0] * 255), true); view.setUint16(boffset + 22, (points.data.color[3 * i + 1] * 255), true); view.setUint16(boffset + 24, (points.data.color[3 * i + 2] * 255), true); } boffset += 28; } return buffer; } };