LASDecoderWorker.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. function readUsingTempArrays(event) {
  2. performance.mark("laslaz-start");
  3. let buffer = event.data.buffer;
  4. let numPoints = event.data.numPoints;
  5. let sourcePointSize = event.data.pointSize;
  6. let pointFormatID = event.data.pointFormatID;
  7. let scale = event.data.scale;
  8. let offset = event.data.offset;
  9. let temp = new ArrayBuffer(4);
  10. let tempUint8 = new Uint8Array(temp);
  11. let tempUint16 = new Uint16Array(temp);
  12. let tempInt32 = new Int32Array(temp);
  13. let sourceUint8 = new Uint8Array(buffer);
  14. let tightBoundingBox = {
  15. min: [ Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY ],
  16. max: [ Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY ]
  17. };
  18. let mean = [0, 0, 0];
  19. let pBuff = new ArrayBuffer(numPoints * 3 * 4);
  20. let cBuff = new ArrayBuffer(numPoints * 4);
  21. let iBuff = new ArrayBuffer(numPoints * 4);
  22. let clBuff = new ArrayBuffer(numPoints);
  23. let rnBuff = new ArrayBuffer(numPoints);
  24. let nrBuff = new ArrayBuffer(numPoints);
  25. let psBuff = new ArrayBuffer(numPoints * 2);
  26. let positions = new Float32Array(pBuff);
  27. let colors = new Uint8Array(cBuff);
  28. let intensities = new Float32Array(iBuff);
  29. let classifications = new Uint8Array(clBuff);
  30. let returnNumbers = new Uint8Array(rnBuff);
  31. let numberOfReturns = new Uint8Array(nrBuff);
  32. let pointSourceIDs = new Uint16Array(psBuff);
  33. for (let i = 0; i < numPoints; i++) {
  34. // POSITION
  35. tempUint8[0] = sourceUint8[i * sourcePointSize + 0];
  36. tempUint8[1] = sourceUint8[i * sourcePointSize + 1];
  37. tempUint8[2] = sourceUint8[i * sourcePointSize + 2];
  38. tempUint8[3] = sourceUint8[i * sourcePointSize + 3];
  39. let x = tempInt32[0];
  40. tempUint8[0] = sourceUint8[i * sourcePointSize + 4];
  41. tempUint8[1] = sourceUint8[i * sourcePointSize + 5];
  42. tempUint8[2] = sourceUint8[i * sourcePointSize + 6];
  43. tempUint8[3] = sourceUint8[i * sourcePointSize + 7];
  44. let y = tempInt32[0];
  45. tempUint8[0] = sourceUint8[i * sourcePointSize + 8];
  46. tempUint8[1] = sourceUint8[i * sourcePointSize + 9];
  47. tempUint8[2] = sourceUint8[i * sourcePointSize + 10];
  48. tempUint8[3] = sourceUint8[i * sourcePointSize + 11];
  49. let z = tempInt32[0];
  50. x = x * scale[0] + offset[0] - event.data.mins[0];
  51. y = y * scale[1] + offset[1] - event.data.mins[1];
  52. z = z * scale[2] + offset[2] - event.data.mins[2];
  53. positions[3 * i + 0] = x;
  54. positions[3 * i + 1] = y;
  55. positions[3 * i + 2] = z;
  56. mean[0] += x / numPoints;
  57. mean[1] += y / numPoints;
  58. mean[2] += z / numPoints;
  59. tightBoundingBox.min[0] = Math.min(tightBoundingBox.min[0], x);
  60. tightBoundingBox.min[1] = Math.min(tightBoundingBox.min[1], y);
  61. tightBoundingBox.min[2] = Math.min(tightBoundingBox.min[2], z);
  62. tightBoundingBox.max[0] = Math.max(tightBoundingBox.max[0], x);
  63. tightBoundingBox.max[1] = Math.max(tightBoundingBox.max[1], y);
  64. tightBoundingBox.max[2] = Math.max(tightBoundingBox.max[2], z);
  65. // INTENSITY
  66. tempUint8[0] = sourceUint8[i * sourcePointSize + 12];
  67. tempUint8[1] = sourceUint8[i * sourcePointSize + 13];
  68. let intensity = tempUint16[0];
  69. intensities[i] = intensity;
  70. // RETURN NUMBER, stored in the first 3 bits - 00000111
  71. let returnNumber = sourceUint8[i * sourcePointSize + 14] & 0b111;
  72. returnNumbers[i] = returnNumber;
  73. // NUMBER OF RETURNS, stored in 00111000
  74. numberOfReturns[i] = (sourceUint8[i * pointSize + 14] & 0b111000) >> 3;
  75. debugger;
  76. // CLASSIFICATION
  77. let classification = sourceUint8[i * sourcePointSize + 15];
  78. classifications[i] = classification;
  79. // POINT SOURCE ID
  80. tempUint8[0] = sourceUint8[i * sourcePointSize + 18];
  81. tempUint8[1] = sourceUint8[i * sourcePointSize + 19];
  82. let pointSourceID = tempUint16[0];
  83. pointSourceIDs[i] = pointSourceID;
  84. // COLOR, if available
  85. if (pointFormatID === 2) {
  86. tempUint8[0] = sourceUint8[i * sourcePointSize + 20];
  87. tempUint8[1] = sourceUint8[i * sourcePointSize + 21];
  88. let r = tempUint16[0];
  89. tempUint8[0] = sourceUint8[i * sourcePointSize + 22];
  90. tempUint8[1] = sourceUint8[i * sourcePointSize + 23];
  91. let g = tempUint16[0];
  92. tempUint8[0] = sourceUint8[i * sourcePointSize + 24];
  93. tempUint8[1] = sourceUint8[i * sourcePointSize + 25];
  94. let b = tempUint16[0];
  95. r = r / 256;
  96. g = g / 256;
  97. b = b / 256;
  98. colors[4 * i + 0] = r;
  99. colors[4 * i + 1] = g;
  100. colors[4 * i + 2] = b;
  101. }
  102. }
  103. let indices = new ArrayBuffer(numPoints * 4);
  104. let iIndices = new Uint32Array(indices);
  105. for (let i = 0; i < numPoints; i++) {
  106. iIndices[i] = i;
  107. }
  108. performance.mark("laslaz-end");
  109. performance.measure("laslaz", "laslaz-start", "laslaz-end");
  110. let measure = performance.getEntriesByType("measure")[0];
  111. let dpp = 1000 * measure.duration / numPoints;
  112. let debugMessage = `${measure.duration.toFixed(3)} ms, ${numPoints} points, ${dpp.toFixed(3)} micros / point`;
  113. console.log(debugMessage);
  114. performance.clearMarks();
  115. performance.clearMeasures();
  116. let message = {
  117. mean: mean,
  118. position: pBuff,
  119. color: cBuff,
  120. intensity: iBuff,
  121. classification: clBuff,
  122. returnNumber: rnBuff,
  123. numberOfReturns: nrBuff,
  124. pointSourceID: psBuff,
  125. tightBoundingBox: tightBoundingBox,
  126. indices: indices
  127. };
  128. let transferables = [
  129. message.position,
  130. message.color,
  131. message.intensity,
  132. message.classification,
  133. message.returnNumber,
  134. message.numberOfReturns,
  135. message.pointSourceID,
  136. message.indices];
  137. debugger;
  138. postMessage(message, transferables);
  139. };
  140. function readUsingDataView(event) {
  141. performance.mark("laslaz-start");
  142. let buffer = event.data.buffer;
  143. let numPoints = event.data.numPoints;
  144. let sourcePointSize = event.data.pointSize;
  145. let pointFormatID = event.data.pointFormatID;
  146. let scale = event.data.scale;
  147. let offset = event.data.offset;
  148. let sourceView = new DataView(buffer);
  149. let tightBoundingBox = {
  150. min: [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE],
  151. max: [-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE]
  152. };
  153. let mean = [0, 0, 0];
  154. let pBuff = new ArrayBuffer(numPoints * 3 * 4);
  155. let cBuff = new ArrayBuffer(numPoints * 4);
  156. let iBuff = new ArrayBuffer(numPoints * 4);
  157. let clBuff = new ArrayBuffer(numPoints);
  158. let rnBuff = new ArrayBuffer(numPoints);
  159. let nrBuff = new ArrayBuffer(numPoints);
  160. let psBuff = new ArrayBuffer(numPoints * 2);
  161. let positions = new Float32Array(pBuff);
  162. let colors = new Uint8Array(cBuff);
  163. let intensities = new Float32Array(iBuff);
  164. let classifications = new Uint8Array(clBuff);
  165. let returnNumbers = new Uint8Array(rnBuff);
  166. let numberOfReturns = new Uint8Array(nrBuff);
  167. let pointSourceIDs = new Uint16Array(psBuff);
  168. const rangeIntensity = [Infinity, -Infinity];
  169. const rangeClassification = [Infinity, -Infinity];
  170. const rangeReturnNumber = [Infinity, -Infinity];
  171. const rangeNumberOfReturns = [Infinity, -Infinity];
  172. const rangeSourceID = [Infinity, -Infinity];
  173. for (let i = 0; i < numPoints; i++) {
  174. // POSITION
  175. let ux = sourceView.getInt32(i * sourcePointSize + 0, true);
  176. let uy = sourceView.getInt32(i * sourcePointSize + 4, true);
  177. let uz = sourceView.getInt32(i * sourcePointSize + 8, true);
  178. x = ux * scale[0] + offset[0] - event.data.mins[0];
  179. y = uy * scale[1] + offset[1] - event.data.mins[1];
  180. z = uz * scale[2] + offset[2] - event.data.mins[2];
  181. positions[3 * i + 0] = x;
  182. positions[3 * i + 1] = y;
  183. positions[3 * i + 2] = z;
  184. mean[0] += x / numPoints;
  185. mean[1] += y / numPoints;
  186. mean[2] += z / numPoints;
  187. tightBoundingBox.min[0] = Math.min(tightBoundingBox.min[0], x);
  188. tightBoundingBox.min[1] = Math.min(tightBoundingBox.min[1], y);
  189. tightBoundingBox.min[2] = Math.min(tightBoundingBox.min[2], z);
  190. tightBoundingBox.max[0] = Math.max(tightBoundingBox.max[0], x);
  191. tightBoundingBox.max[1] = Math.max(tightBoundingBox.max[1], y);
  192. tightBoundingBox.max[2] = Math.max(tightBoundingBox.max[2], z);
  193. // INTENSITY
  194. let intensity = sourceView.getUint16(i * sourcePointSize + 12, true);
  195. intensities[i] = intensity;
  196. rangeIntensity[0] = Math.min(rangeIntensity[0], intensity);
  197. rangeIntensity[1] = Math.max(rangeIntensity[1], intensity);
  198. // RETURN NUMBER, stored in the first 3 bits - 00000111
  199. // number of returns stored in next 3 bits - 00111000
  200. let returnNumberAndNumberOfReturns = sourceView.getUint8(i * sourcePointSize + 14, true);
  201. let returnNumber = returnNumberAndNumberOfReturns & 0b0111;
  202. let numberOfReturn = (returnNumberAndNumberOfReturns & 0b00111000) >> 3;
  203. returnNumbers[i] = returnNumber;
  204. numberOfReturns[i] = numberOfReturn;
  205. rangeReturnNumber[0] = Math.min(rangeReturnNumber[0], returnNumber);
  206. rangeReturnNumber[1] = Math.max(rangeReturnNumber[1], returnNumber);
  207. rangeNumberOfReturns[0] = Math.min(rangeNumberOfReturns[0], numberOfReturn);
  208. rangeNumberOfReturns[1] = Math.max(rangeNumberOfReturns[1], numberOfReturn);
  209. // CLASSIFICATION
  210. let classification = sourceView.getUint8(i * sourcePointSize + 15, true);
  211. classifications[i] = classification;
  212. rangeClassification[0] = Math.min(rangeClassification[0], classification);
  213. rangeClassification[1] = Math.max(rangeClassification[1], classification);
  214. // POINT SOURCE ID
  215. let pointSourceID = sourceView.getUint16(i * sourcePointSize + 18, true);
  216. pointSourceIDs[i] = pointSourceID;
  217. rangeSourceID[0] = Math.min(rangeSourceID[0], pointSourceID);
  218. rangeSourceID[1] = Math.max(rangeSourceID[1], pointSourceID);
  219. // COLOR, if available
  220. if (pointFormatID === 2) {
  221. let r = sourceView.getUint16(i * sourcePointSize + 20, true) / 256;
  222. let g = sourceView.getUint16(i * sourcePointSize + 22, true) / 256;
  223. let b = sourceView.getUint16(i * sourcePointSize + 24, true) / 256;
  224. colors[4 * i + 0] = r;
  225. colors[4 * i + 1] = g;
  226. colors[4 * i + 2] = b;
  227. colors[4 * i + 3] = 255;
  228. }
  229. }
  230. let indices = new ArrayBuffer(numPoints * 4);
  231. let iIndices = new Uint32Array(indices);
  232. for (let i = 0; i < numPoints; i++) {
  233. iIndices[i] = i;
  234. }
  235. performance.mark("laslaz-end");
  236. //{ // print timings
  237. // performance.measure("laslaz", "laslaz-start", "laslaz-end");
  238. // let measure = performance.getEntriesByType("measure")[0];
  239. // let dpp = 1000 * measure.duration / numPoints;
  240. // let debugMessage = `${measure.duration.toFixed(3)} ms, ${numPoints} points, ${dpp.toFixed(3)} µs / point`;
  241. // console.log(debugMessage);
  242. //}
  243. performance.clearMarks();
  244. performance.clearMeasures();
  245. const ranges = {
  246. "intensity": rangeIntensity,
  247. "classification": rangeClassification,
  248. "return number": rangeReturnNumber,
  249. "number of returns": rangeNumberOfReturns,
  250. "source id": rangeSourceID,
  251. };
  252. let message = {
  253. mean: mean,
  254. position: pBuff,
  255. color: cBuff,
  256. intensity: iBuff,
  257. classification: clBuff,
  258. returnNumber: rnBuff,
  259. numberOfReturns: nrBuff,
  260. pointSourceID: psBuff,
  261. tightBoundingBox: tightBoundingBox,
  262. indices: indices,
  263. ranges: ranges,
  264. };
  265. let transferables = [
  266. message.position,
  267. message.color,
  268. message.intensity,
  269. message.classification,
  270. message.returnNumber,
  271. message.numberOfReturns,
  272. message.pointSourceID,
  273. message.indices];
  274. postMessage(message, transferables);
  275. };
  276. onmessage = readUsingDataView;
  277. //onmessage = readUsingTempArrays;