EptLaszipDecoderWorker.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. function readUsingDataView(event) {
  2. performance.mark("laslaz-start");
  3. let buffer = event.data.buffer;
  4. let numPoints = event.data.numPoints;
  5. let pointSize = event.data.pointSize;
  6. let pointFormat = event.data.pointFormatID;
  7. // gps time byte offsets from LAS specification
  8. let gpsOffsets = [null, 20, null, 20, 20, 20, 22, 22, 22, 22, 22]
  9. let gpsOffset = gpsOffsets[pointFormat];
  10. let scale = event.data.scale;
  11. let offset = event.data.offset;
  12. let sourceUint8 = new Uint8Array(buffer);
  13. let sourceView = new DataView(buffer);
  14. let tightBoundingBox = {
  15. min: [
  16. Number.POSITIVE_INFINITY,
  17. Number.POSITIVE_INFINITY,
  18. Number.POSITIVE_INFINITY
  19. ],
  20. max: [
  21. Number.NEGATIVE_INFINITY,
  22. Number.NEGATIVE_INFINITY,
  23. Number.NEGATIVE_INFINITY
  24. ]
  25. };
  26. let mean = [0, 0, 0];
  27. let pBuff = new ArrayBuffer(numPoints * 3 * 4);
  28. let cBuff = new ArrayBuffer(numPoints * 4);
  29. let iBuff = new ArrayBuffer(numPoints * 4);
  30. let clBuff = new ArrayBuffer(numPoints);
  31. let rnBuff = new ArrayBuffer(numPoints);
  32. let nrBuff = new ArrayBuffer(numPoints);
  33. let psBuff = new ArrayBuffer(numPoints * 2);
  34. let gpsBuff64 = new ArrayBuffer(numPoints * 8);
  35. let gpsBuff32 = new ArrayBuffer(numPoints * 4);
  36. let positions = new Float32Array(pBuff);
  37. let colors = new Uint8Array(cBuff);
  38. let intensities = new Float32Array(iBuff);
  39. let classifications = new Uint8Array(clBuff);
  40. let returnNumbers = new Uint8Array(rnBuff);
  41. let numberOfReturns = new Uint8Array(nrBuff);
  42. let pointSourceIDs = new Uint16Array(psBuff);
  43. let gpsTime64 = new Float64Array(gpsBuff64)
  44. let gpsTime32 = new Float32Array(gpsBuff32)
  45. // Point format 3 contains an 8-byte GpsTime before RGB values, so make
  46. // sure we have the correct color offset.
  47. let hasColor = pointFormat == 2 || pointFormat == 3;
  48. let co = pointFormat == 2 ? 20 : 28;
  49. // TODO This should be cached per-resource since this is an expensive check.
  50. let twoByteColor = false;
  51. if (hasColor) {
  52. let r, g, b, pos;
  53. for (let i = 0; i < numPoints && !twoByteColor; ++i) {
  54. pos = i * pointSize;
  55. r = sourceView.getUint16(pos + co, true)
  56. g = sourceView.getUint16(pos + co + 2, true)
  57. b = sourceView.getUint16(pos + co + 4, true)
  58. if (r > 255 || g > 255 || b > 255) twoByteColor = true;
  59. }
  60. }
  61. for (let i = 0; i < numPoints; i++) {
  62. // POSITION
  63. let ux = sourceView.getInt32(i * pointSize + 0, true);
  64. let uy = sourceView.getInt32(i * pointSize + 4, true);
  65. let uz = sourceView.getInt32(i * pointSize + 8, true);
  66. x = ux * scale[0] + offset[0] - event.data.mins[0];
  67. y = uy * scale[1] + offset[1] - event.data.mins[1];
  68. z = uz * scale[2] + offset[2] - event.data.mins[2];
  69. positions[3 * i + 0] = x;
  70. positions[3 * i + 1] = y;
  71. positions[3 * i + 2] = z;
  72. mean[0] += x / numPoints;
  73. mean[1] += y / numPoints;
  74. mean[2] += z / numPoints;
  75. tightBoundingBox.min[0] = Math.min(tightBoundingBox.min[0], x);
  76. tightBoundingBox.min[1] = Math.min(tightBoundingBox.min[1], y);
  77. tightBoundingBox.min[2] = Math.min(tightBoundingBox.min[2], z);
  78. tightBoundingBox.max[0] = Math.max(tightBoundingBox.max[0], x);
  79. tightBoundingBox.max[1] = Math.max(tightBoundingBox.max[1], y);
  80. tightBoundingBox.max[2] = Math.max(tightBoundingBox.max[2], z);
  81. // INTENSITY
  82. let intensity = sourceView.getUint16(i * pointSize + 12, true);
  83. intensities[i] = intensity;
  84. // RETURN NUMBER, stored in the first 3 bits - 00000111
  85. // number of returns stored in next 3 bits - 00111000
  86. let returnNumberAndNumberOfReturns = sourceView.getUint8(i * pointSize + 14, true);
  87. let returnNumber = returnNumberAndNumberOfReturns & 0b0111;
  88. let numberOfReturn = (returnNumberAndNumberOfReturns & 0b00111000) >> 3;
  89. returnNumbers[i] = returnNumber;
  90. numberOfReturns[i] = numberOfReturn;
  91. // CLASSIFICATION
  92. let classification = sourceView.getUint8(i * pointSize + 15, true);
  93. classifications[i] = classification;
  94. // POINT SOURCE ID
  95. let pointSourceID = sourceView.getUint16(i * pointSize + 18, true);
  96. pointSourceIDs[i] = pointSourceID;
  97. // COLOR, if available
  98. if (hasColor) {
  99. let r = sourceView.getUint16(i * pointSize + co, true)
  100. let g = sourceView.getUint16(i * pointSize + co + 2, true)
  101. let b = sourceView.getUint16(i * pointSize + co + 4, true)
  102. if (twoByteColor) {
  103. r /= 256;
  104. g /= 256;
  105. b /= 256;
  106. }
  107. colors[4 * i + 0] = r;
  108. colors[4 * i + 1] = g;
  109. colors[4 * i + 2] = b;
  110. colors[4 * i + 3] = 255;
  111. }
  112. }
  113. let min = Infinity
  114. let max = -Infinity
  115. for (let i = 0; i < numPoints; i++) {
  116. min = Math.min(min, gpsTime64[i])
  117. max = Math.max(max, gpsTime64[i])
  118. }
  119. for (let i = 0; i < numPoints; i++) {
  120. gpsTime32[i] = gpsTime64[i] = min
  121. }
  122. let indices = new ArrayBuffer(numPoints * 4);
  123. let iIndices = new Uint32Array(indices);
  124. for (let i = 0; i < numPoints; i++) {
  125. iIndices[i] = i;
  126. }
  127. performance.mark("laslaz-end");
  128. //{ // print timings
  129. // performance.measure("laslaz", "laslaz-start", "laslaz-end");
  130. // let measure = performance.getEntriesByType("measure")[0];
  131. // let dpp = 1000 * measure.duration / numPoints;
  132. // let debugMessage = `${measure.duration.toFixed(3)} ms, ${numPoints} points, ${dpp.toFixed(3)} µs / point`;
  133. // console.log(debugMessage);
  134. //}
  135. performance.clearMarks();
  136. performance.clearMeasures();
  137. let message = {
  138. mean: mean,
  139. position: pBuff,
  140. color: cBuff,
  141. intensity: iBuff,
  142. classification: clBuff,
  143. returnNumber: rnBuff,
  144. numberOfReturns: nrBuff,
  145. pointSourceID: psBuff,
  146. tightBoundingBox: tightBoundingBox,
  147. indices: indices,
  148. gpsTime: gpsBuff32,
  149. gpsMeta: { offset: min, range: max-min }
  150. };
  151. let transferables = [
  152. message.position,
  153. message.color,
  154. message.intensity,
  155. message.classification,
  156. message.returnNumber,
  157. message.numberOfReturns,
  158. message.pointSourceID,
  159. message.indices,
  160. message.gpsTime
  161. ];
  162. postMessage(message, transferables);
  163. };
  164. onmessage = readUsingDataView;