createVectorTilePolylines.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import Cartesian3 from "../Core/Cartesian3.js";
  2. import combine from "../Core/combine.js";
  3. import decodeVectorPolylinePositions from "../Core/decodeVectorPolylinePositions.js";
  4. import Ellipsoid from "../Core/Ellipsoid.js";
  5. import IndexDatatype from "../Core/IndexDatatype.js";
  6. import Rectangle from "../Core/Rectangle.js";
  7. import createTaskProcessorWorker from "./createTaskProcessorWorker.js";
  8. const scratchRectangle = new Rectangle();
  9. const scratchEllipsoid = new Ellipsoid();
  10. const scratchCenter = new Cartesian3();
  11. const scratchMinMaxHeights = {
  12. min: undefined,
  13. max: undefined,
  14. };
  15. function unpackBuffer(packedBuffer) {
  16. packedBuffer = new Float64Array(packedBuffer);
  17. let offset = 0;
  18. scratchMinMaxHeights.min = packedBuffer[offset++];
  19. scratchMinMaxHeights.max = packedBuffer[offset++];
  20. Rectangle.unpack(packedBuffer, offset, scratchRectangle);
  21. offset += Rectangle.packedLength;
  22. Ellipsoid.unpack(packedBuffer, offset, scratchEllipsoid);
  23. offset += Ellipsoid.packedLength;
  24. Cartesian3.unpack(packedBuffer, offset, scratchCenter);
  25. }
  26. function getPositionOffsets(counts) {
  27. const countsLength = counts.length;
  28. const positionOffsets = new Uint32Array(countsLength + 1);
  29. let offset = 0;
  30. for (let i = 0; i < countsLength; ++i) {
  31. positionOffsets[i] = offset;
  32. offset += counts[i];
  33. }
  34. positionOffsets[countsLength] = offset;
  35. return positionOffsets;
  36. }
  37. const scratchP0 = new Cartesian3();
  38. const scratchP1 = new Cartesian3();
  39. const scratchPrev = new Cartesian3();
  40. const scratchCur = new Cartesian3();
  41. const scratchNext = new Cartesian3();
  42. function createVectorTilePolylines(parameters, transferableObjects) {
  43. const encodedPositions = new Uint16Array(parameters.positions);
  44. const widths = new Uint16Array(parameters.widths);
  45. const counts = new Uint32Array(parameters.counts);
  46. const batchIds = new Uint16Array(parameters.batchIds);
  47. unpackBuffer(parameters.packedBuffer);
  48. const rectangle = scratchRectangle;
  49. const ellipsoid = scratchEllipsoid;
  50. const center = scratchCenter;
  51. const minimumHeight = scratchMinMaxHeights.min;
  52. const maximumHeight = scratchMinMaxHeights.max;
  53. const positions = decodeVectorPolylinePositions(
  54. encodedPositions,
  55. rectangle,
  56. minimumHeight,
  57. maximumHeight,
  58. ellipsoid
  59. );
  60. const positionsLength = positions.length / 3;
  61. const size = positionsLength * 4 - 4;
  62. const curPositions = new Float32Array(size * 3);
  63. const prevPositions = new Float32Array(size * 3);
  64. const nextPositions = new Float32Array(size * 3);
  65. const expandAndWidth = new Float32Array(size * 2);
  66. const vertexBatchIds = new Uint16Array(size);
  67. let positionIndex = 0;
  68. let expandAndWidthIndex = 0;
  69. let batchIdIndex = 0;
  70. let i;
  71. let offset = 0;
  72. let length = counts.length;
  73. for (i = 0; i < length; ++i) {
  74. const count = counts[i];
  75. const width = widths[i];
  76. const batchId = batchIds[i];
  77. for (let j = 0; j < count; ++j) {
  78. let previous;
  79. if (j === 0) {
  80. const p0 = Cartesian3.unpack(positions, offset * 3, scratchP0);
  81. const p1 = Cartesian3.unpack(positions, (offset + 1) * 3, scratchP1);
  82. previous = Cartesian3.subtract(p0, p1, scratchPrev);
  83. Cartesian3.add(p0, previous, previous);
  84. } else {
  85. previous = Cartesian3.unpack(
  86. positions,
  87. (offset + j - 1) * 3,
  88. scratchPrev
  89. );
  90. }
  91. const current = Cartesian3.unpack(
  92. positions,
  93. (offset + j) * 3,
  94. scratchCur
  95. );
  96. let next;
  97. if (j === count - 1) {
  98. const p2 = Cartesian3.unpack(
  99. positions,
  100. (offset + count - 1) * 3,
  101. scratchP0
  102. );
  103. const p3 = Cartesian3.unpack(
  104. positions,
  105. (offset + count - 2) * 3,
  106. scratchP1
  107. );
  108. next = Cartesian3.subtract(p2, p3, scratchNext);
  109. Cartesian3.add(p2, next, next);
  110. } else {
  111. next = Cartesian3.unpack(positions, (offset + j + 1) * 3, scratchNext);
  112. }
  113. Cartesian3.subtract(previous, center, previous);
  114. Cartesian3.subtract(current, center, current);
  115. Cartesian3.subtract(next, center, next);
  116. const startK = j === 0 ? 2 : 0;
  117. const endK = j === count - 1 ? 2 : 4;
  118. for (let k = startK; k < endK; ++k) {
  119. Cartesian3.pack(current, curPositions, positionIndex);
  120. Cartesian3.pack(previous, prevPositions, positionIndex);
  121. Cartesian3.pack(next, nextPositions, positionIndex);
  122. positionIndex += 3;
  123. const direction = k - 2 < 0 ? -1.0 : 1.0;
  124. expandAndWidth[expandAndWidthIndex++] = 2 * (k % 2) - 1;
  125. expandAndWidth[expandAndWidthIndex++] = direction * width;
  126. vertexBatchIds[batchIdIndex++] = batchId;
  127. }
  128. }
  129. offset += count;
  130. }
  131. const indices = IndexDatatype.createTypedArray(size, positionsLength * 6 - 6);
  132. let index = 0;
  133. let indicesIndex = 0;
  134. length = positionsLength - 1;
  135. for (i = 0; i < length; ++i) {
  136. indices[indicesIndex++] = index;
  137. indices[indicesIndex++] = index + 2;
  138. indices[indicesIndex++] = index + 1;
  139. indices[indicesIndex++] = index + 1;
  140. indices[indicesIndex++] = index + 2;
  141. indices[indicesIndex++] = index + 3;
  142. index += 4;
  143. }
  144. transferableObjects.push(
  145. curPositions.buffer,
  146. prevPositions.buffer,
  147. nextPositions.buffer
  148. );
  149. transferableObjects.push(
  150. expandAndWidth.buffer,
  151. vertexBatchIds.buffer,
  152. indices.buffer
  153. );
  154. let results = {
  155. indexDatatype:
  156. indices.BYTES_PER_ELEMENT === 2
  157. ? IndexDatatype.UNSIGNED_SHORT
  158. : IndexDatatype.UNSIGNED_INT,
  159. currentPositions: curPositions.buffer,
  160. previousPositions: prevPositions.buffer,
  161. nextPositions: nextPositions.buffer,
  162. expandAndWidth: expandAndWidth.buffer,
  163. batchIds: vertexBatchIds.buffer,
  164. indices: indices.buffer,
  165. };
  166. if (parameters.keepDecodedPositions) {
  167. const positionOffsets = getPositionOffsets(counts);
  168. transferableObjects.push(positions.buffer, positionOffsets.buffer);
  169. results = combine(results, {
  170. decodedPositions: positions.buffer,
  171. decodedPositionOffsets: positionOffsets.buffer,
  172. });
  173. }
  174. return results;
  175. }
  176. export default createTaskProcessorWorker(createVectorTilePolylines);