EptBinaryDecoderWorker.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. function parseEpt(event) {
  2. let buffer = event.data.buffer;
  3. let view = new DataView(buffer);
  4. let schema = event.data.schema;
  5. let scale = event.data.scale;
  6. let offset = event.data.offset;
  7. let mins = event.data.mins;
  8. let dimensions = schema.reduce((p, c) => {
  9. p[c.name] = c;
  10. return p;
  11. }, { });
  12. let dimOffset = (name) => {
  13. let offset = 0;
  14. for (var i = 0; i < schema.length; ++i) {
  15. if (schema[i].name == name) return offset;
  16. offset += schema[i].size;
  17. }
  18. return undefined;
  19. };
  20. let getExtractor = (name) => {
  21. let offset = dimOffset(name);
  22. let type = dimensions[name].type;
  23. let size = dimensions[name].size;
  24. if (type == 'signed') switch (size) {
  25. case 1: return (p) => view.getInt8(p + offset);
  26. case 2: return (p) => view.getInt16(p + offset, true);
  27. case 4: return (p) => view.getInt32(p + offset, true);
  28. case 8: return (p) => view.getInt64(p + offset, true);
  29. }
  30. if (type == 'unsigned') switch (size) {
  31. case 1: return (p) => view.getUint8(p + offset);
  32. case 2: return (p) => view.getUint16(p + offset, true);
  33. case 4: return (p) => view.getUint32(p + offset, true);
  34. case 8: return (p) => view.getUint64(p + offset, true);
  35. }
  36. if (type == 'float') switch (size) {
  37. case 4: return (p) => view.getFloat32(p + offset, true);
  38. case 8: return (p) => view.getFloat64(p + offset, true);
  39. }
  40. let str = JSON.stringify(dimensions[name]);
  41. throw new Error(`Invalid dimension specification for ${name}: ${str}`);
  42. };
  43. let pointSize = schema.reduce((p, c) => p + c.size, 0);
  44. let numPoints = buffer.byteLength / pointSize;
  45. let xyzBuffer, rgbBuffer, intensityBuffer, classificationBuffer,
  46. returnNumberBuffer, numberOfReturnsBuffer, pointSourceIdBuffer;
  47. let xyz, rgb, intensity, classification, returnNumber, numberOfReturns,
  48. pointSourceId;
  49. let xyzExtractor, rgbExtractor, intensityExtractor, classificationExtractor,
  50. returnNumberExtractor, numberOfReturnsExtractor, pointSourceIdExtractor;
  51. let twoByteColor = false;
  52. if (dimensions['X'] && dimensions['Y'] && dimensions['Z']) {
  53. xyzBuffer = new ArrayBuffer(numPoints * 4 * 3);
  54. xyz = new Float32Array(xyzBuffer);
  55. xyzExtractor = [
  56. getExtractor('X'),
  57. getExtractor('Y'),
  58. getExtractor('Z')
  59. ];
  60. }
  61. if (dimensions['Red'] && dimensions['Green'] && dimensions['Blue']) {
  62. rgbBuffer = new ArrayBuffer(numPoints * 4);
  63. rgb = new Uint8Array(rgbBuffer);
  64. rgbExtractor = [
  65. getExtractor('Red'),
  66. getExtractor('Green'),
  67. getExtractor('Blue')
  68. ];
  69. let r, g, b, pos;
  70. for (let i = 0; i < numPoints && !twoByteColor; ++i) {
  71. pos = i * pointSize;
  72. r = rgbExtractor[0](pos);
  73. g = rgbExtractor[1](pos);
  74. b = rgbExtractor[2](pos);
  75. if (r > 255 || g > 255 || b > 255) twoByteColor = true;
  76. }
  77. }
  78. if (dimensions['Intensity']) {
  79. intensityBuffer = new ArrayBuffer(numPoints * 4);
  80. intensity = new Float32Array(intensityBuffer);
  81. intensityExtractor = getExtractor('Intensity');
  82. }
  83. if (dimensions['Classification']) {
  84. classificationBuffer = new ArrayBuffer(numPoints);
  85. classification = new Uint8Array(classificationBuffer);
  86. classificationExtractor = getExtractor('Classification');
  87. }
  88. if (dimensions['ReturnNumber']) {
  89. returnNumberBuffer = new ArrayBuffer(numPoints);
  90. returnNumber = new Uint8Array(returnNumberBuffer);
  91. returnNumberExtractor = getExtractor('ReturnNumber');
  92. }
  93. if (dimensions['NumberOfReturns']) {
  94. numberOfReturnsBuffer = new ArrayBuffer(numPoints);
  95. numberOfReturns = new Uint8Array(numberOfReturnsBuffer);
  96. numberOfReturnsExtractor = getExtractor('NumberOfReturns');
  97. }
  98. if (dimensions['PointSourceId']) {
  99. pointSourceIdBuffer = new ArrayBuffer(numPoints * 2);
  100. pointSourceId = new Uint16Array(pointSourceIdBuffer);
  101. pointSourceIdExtractor = getExtractor('PointSourceId');
  102. }
  103. let mean = [0, 0, 0];
  104. let bounds = {
  105. min: [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE],
  106. max: [-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE],
  107. };
  108. let x, y, z, r, g, b;
  109. for (let i = 0; i < numPoints; ++i) {
  110. let pos = i * pointSize;
  111. if (xyz) {
  112. x = xyzExtractor[0](pos) * scale.x + offset.x - mins[0];
  113. y = xyzExtractor[1](pos) * scale.y + offset.y - mins[1];
  114. z = xyzExtractor[2](pos) * scale.z + offset.z - mins[2];
  115. mean[0] += x / numPoints;
  116. mean[1] += y / numPoints;
  117. mean[2] += z / numPoints;
  118. bounds.min[0] = Math.min(bounds.min[0], x);
  119. bounds.min[1] = Math.min(bounds.min[1], y);
  120. bounds.min[2] = Math.min(bounds.min[2], z);
  121. bounds.max[0] = Math.max(bounds.max[0], x);
  122. bounds.max[1] = Math.max(bounds.max[1], y);
  123. bounds.max[2] = Math.max(bounds.max[2], z);
  124. xyz[3 * i + 0] = x;
  125. xyz[3 * i + 1] = y;
  126. xyz[3 * i + 2] = z;
  127. }
  128. if (rgb) {
  129. r = rgbExtractor[0](pos);
  130. g = rgbExtractor[1](pos);
  131. b = rgbExtractor[2](pos);
  132. if (twoByteColor) {
  133. r /= 256;
  134. g /= 256;
  135. b /= 256;
  136. }
  137. rgb[4 * i + 0] = r;
  138. rgb[4 * i + 1] = g;
  139. rgb[4 * i + 2] = b;
  140. }
  141. if (intensity) intensity[i] = intensityExtractor(pos);
  142. if (classification) classification[i] = classificationExtractor(pos);
  143. if (returnNumber) returnNumber[i] = returnNumberExtractor(pos);
  144. if (numberOfReturns) numberOfReturns[i] = numberOfReturnsExtractor(pos);
  145. if (pointSourceId) pointSourceId[i] = pointSourceIdExtractor(pos);
  146. }
  147. let indicesBuffer = new ArrayBuffer(numPoints * 4);
  148. let indices = new Uint32Array(indicesBuffer);
  149. for (let i = 0; i < numPoints; ++i) {
  150. indices[i] = i;
  151. }
  152. let message = {
  153. numPoints: numPoints,
  154. tightBoundingBox: bounds,
  155. mean: mean,
  156. position: xyzBuffer,
  157. color: rgbBuffer,
  158. intensity: intensityBuffer,
  159. classification: classificationBuffer,
  160. returnNumber: returnNumberBuffer,
  161. numberOfReturns: numberOfReturnsBuffer,
  162. pointSourceId: pointSourceIdBuffer,
  163. indices: indicesBuffer
  164. };
  165. let transferables = [
  166. message.position,
  167. message.color,
  168. message.intensity,
  169. message.classification,
  170. message.returnNumber,
  171. message.numberOfReturns,
  172. message.pointSourceId,
  173. message.indices
  174. ].filter((v) => v);
  175. postMessage(message, transferables);
  176. }
  177. // importScripts('/libs/ept/ParseBuffer.js');
  178. onmessage = function(event) {
  179. parseEpt(event);
  180. }