@cesium/engine 25.0.0 → 26.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/Build/Workers/{chunk-GPIGURCG.js → chunk-3VFEWOBI.js} +7 -7
  2. package/Build/Workers/{chunk-BTX2NL3P.js → chunk-424RNO3D.js} +18 -18
  3. package/Build/Workers/{chunk-HSVQATK2.js → chunk-4MGMYHOO.js} +6 -6
  4. package/Build/Workers/{chunk-FIBS5S7R.js → chunk-4S7IE3LB.js} +2 -2
  5. package/Build/Workers/{chunk-A7ZBMVFS.js → chunk-52JDLOEM.js} +14 -14
  6. package/Build/Workers/{chunk-ZCCIIBZT.js → chunk-54I6Y66F.js} +6 -6
  7. package/Build/Workers/{chunk-J647NNZW.js → chunk-6YEE6JDR.js} +6 -6
  8. package/Build/Workers/{chunk-HVMG6AG4.js → chunk-7J2HKPRH.js} +9 -9
  9. package/Build/Workers/{chunk-K6NFIRFB.js → chunk-7WM2PX4V.js} +5 -5
  10. package/Build/Workers/{chunk-3LSD7OOA.js → chunk-ACXQXN46.js} +16 -16
  11. package/Build/Workers/{chunk-CZ23Y3RM.js → chunk-AYKR4VBR.js} +2 -2
  12. package/Build/Workers/{chunk-4MTRQFJP.js → chunk-C6J67V5A.js} +1 -1
  13. package/Build/Workers/{chunk-WTQGE7Q6.js → chunk-C6KNZ7T4.js} +17 -17
  14. package/Build/Workers/{chunk-AWFZHD2B.js → chunk-CFQP6LYM.js} +4 -4
  15. package/Build/Workers/{chunk-ST2UWDUU.js → chunk-CXOYE2WM.js} +5 -5
  16. package/Build/Workers/{chunk-H2A4USJR.js → chunk-CZEYZU4N.js} +10 -10
  17. package/Build/Workers/{chunk-DFEI5MAV.js → chunk-DBOEKL43.js} +7 -7
  18. package/Build/Workers/{chunk-A7A433MD.js → chunk-DDWSZVMY.js} +5 -5
  19. package/Build/Workers/{chunk-J7KQEKPK.js → chunk-DOBXCNC3.js} +13 -13
  20. package/Build/Workers/{chunk-URUCCIPS.js → chunk-E7VQ76KE.js} +6 -6
  21. package/Build/Workers/{chunk-ZAPOS52G.js → chunk-EBSIOBXY.js} +8 -8
  22. package/Build/Workers/{chunk-3VDDRF2E.js → chunk-EF2QYXGA.js} +14 -14
  23. package/Build/Workers/{chunk-WN6P5UDH.js → chunk-EPYXRCDB.js} +12 -12
  24. package/Build/Workers/{chunk-EZARA5FJ.js → chunk-F6QDY6HU.js} +13 -13
  25. package/Build/Workers/{chunk-GL7DNVUS.js → chunk-FRQZECAO.js} +5 -5
  26. package/Build/Workers/{chunk-VQKLRBIK.js → chunk-G7PXZRVF.js} +7 -7
  27. package/Build/Workers/{chunk-4QQXGTCE.js → chunk-INUEEEQA.js} +8 -8
  28. package/Build/Workers/{chunk-ITD2IN7N.js → chunk-IRBKFCEJ.js} +2 -2
  29. package/Build/Workers/{chunk-6SDGQI27.js → chunk-IYOUHCZB.js} +1 -1
  30. package/Build/Workers/{chunk-DYT5NR6P.js → chunk-J6BWOHUF.js} +3 -3
  31. package/Build/Workers/{chunk-4GF4MVPY.js → chunk-KFSTQKNM.js} +7 -7
  32. package/Build/Workers/{chunk-4XXHJI6Y.js → chunk-KKOSKAZB.js} +17 -17
  33. package/Build/Workers/{chunk-WC57YYBN.js → chunk-KSSWJIZW.js} +2 -2
  34. package/Build/Workers/{chunk-5T6QQAJW.js → chunk-M3B5JKSM.js} +1 -1
  35. package/Build/Workers/{chunk-QO2CGXMP.js → chunk-MPZHGZU6.js} +6 -6
  36. package/Build/Workers/{chunk-WUBKZFF6.js → chunk-MYP774IS.js} +9 -9
  37. package/Build/Workers/{chunk-WNN5D4W3.js → chunk-O3EA5HS7.js} +10 -10
  38. package/Build/Workers/{chunk-77RL3MBD.js → chunk-P3CK7MCY.js} +25 -4
  39. package/Build/Workers/{chunk-QXNQQYPV.js → chunk-Q3PY526V.js} +8 -8
  40. package/Build/Workers/{chunk-CKQP3DSS.js → chunk-QN67VG36.js} +6 -6
  41. package/Build/Workers/{chunk-ACFFCHHZ.js → chunk-QRWGUWI6.js} +11 -11
  42. package/Build/Workers/{chunk-LH5SF3XV.js → chunk-S4MCOY6I.js} +5 -5
  43. package/Build/Workers/{chunk-FVLVVOBQ.js → chunk-SMQZZOW6.js} +10 -10
  44. package/Build/Workers/{chunk-TA777BGS.js → chunk-TKKIREQ6.js} +1 -1
  45. package/Build/Workers/{chunk-AEAVLYPS.js → chunk-U3ZA64U7.js} +2 -2
  46. package/Build/Workers/{chunk-7LSFAEWF.js → chunk-UA25D5MX.js} +10 -10
  47. package/Build/Workers/{chunk-J3OFS2RD.js → chunk-UOOIQ3KX.js} +12 -12
  48. package/Build/Workers/{chunk-ND3NTTOF.js → chunk-V7VQKN6N.js} +6 -6
  49. package/Build/Workers/{chunk-I3A6DXYZ.js → chunk-VQYETPWC.js} +4 -4
  50. package/Build/Workers/{chunk-35H3UBIO.js → chunk-VWV2IJRB.js} +11 -11
  51. package/Build/Workers/{chunk-QSDY4NS7.js → chunk-XZMBNNDX.js} +9 -9
  52. package/Build/Workers/{chunk-TAI4HLII.js → chunk-Y57HREW5.js} +4 -4
  53. package/Build/Workers/{chunk-3TKLDHV3.js → chunk-Y5BF6AFU.js} +2 -2
  54. package/Build/Workers/{chunk-3XY3MVPG.js → chunk-YLY7NKAB.js} +4 -4
  55. package/Build/Workers/{chunk-BVAIWR7O.js → chunk-ZK3CF7ZD.js} +12 -12
  56. package/Build/Workers/{chunk-DH26SNAB.js → chunk-ZP7JMQV4.js} +1 -1
  57. package/Build/Workers/{chunk-3RFFPH4M.js → chunk-ZZ46LWL6.js} +1 -1
  58. package/Build/Workers/combineGeometry.js +24 -24
  59. package/Build/Workers/createBoxGeometry.js +18 -18
  60. package/Build/Workers/createBoxOutlineGeometry.js +16 -16
  61. package/Build/Workers/createCircleGeometry.js +26 -26
  62. package/Build/Workers/createCircleOutlineGeometry.js +19 -19
  63. package/Build/Workers/createCoplanarPolygonGeometry.js +33 -33
  64. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +31 -31
  65. package/Build/Workers/createCorridorGeometry.js +29 -29
  66. package/Build/Workers/createCorridorOutlineGeometry.js +28 -28
  67. package/Build/Workers/createCylinderGeometry.js +20 -20
  68. package/Build/Workers/createCylinderOutlineGeometry.js +18 -18
  69. package/Build/Workers/createEllipseGeometry.js +26 -26
  70. package/Build/Workers/createEllipseOutlineGeometry.js +19 -19
  71. package/Build/Workers/createEllipsoidGeometry.js +19 -19
  72. package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -18
  73. package/Build/Workers/createFrustumGeometry.js +18 -18
  74. package/Build/Workers/createFrustumOutlineGeometry.js +18 -18
  75. package/Build/Workers/createGeometry.js +24 -24
  76. package/Build/Workers/createGroundPolylineGeometry.js +22 -22
  77. package/Build/Workers/createPlaneGeometry.js +16 -16
  78. package/Build/Workers/createPlaneOutlineGeometry.js +15 -15
  79. package/Build/Workers/createPolygonGeometry.js +32 -32
  80. package/Build/Workers/createPolygonOutlineGeometry.js +30 -30
  81. package/Build/Workers/createPolylineGeometry.js +25 -25
  82. package/Build/Workers/createPolylineVolumeGeometry.js +31 -31
  83. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +27 -27
  84. package/Build/Workers/createRectangleGeometry.js +27 -27
  85. package/Build/Workers/createRectangleOutlineGeometry.js +20 -20
  86. package/Build/Workers/createSimplePolylineGeometry.js +23 -23
  87. package/Build/Workers/createSphereGeometry.js +19 -19
  88. package/Build/Workers/createSphereOutlineGeometry.js +18 -18
  89. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  90. package/Build/Workers/createVectorTileClampedPolylines.js +14 -14
  91. package/Build/Workers/createVectorTileGeometries.js +24 -24
  92. package/Build/Workers/createVectorTilePoints.js +13 -13
  93. package/Build/Workers/createVectorTilePolygons.js +22 -22
  94. package/Build/Workers/createVectorTilePolylines.js +14 -14
  95. package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +25 -25
  96. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +22 -22
  97. package/Build/Workers/createVerticesFromHeightmap.js +22 -22
  98. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +20 -20
  99. package/Build/Workers/createWallGeometry.js +24 -24
  100. package/Build/Workers/createWallOutlineGeometry.js +23 -23
  101. package/Build/Workers/decodeDraco.js +10 -10
  102. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  103. package/Build/Workers/decodeI3S.js +10 -10
  104. package/Build/Workers/gaussianSplatSorter.js +4 -4
  105. package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
  106. package/Build/Workers/incrementallyBuildTerrainPicker.js +10 -10
  107. package/Build/Workers/transcodeKTX2.js +6 -6
  108. package/Build/Workers/transferTypedArrayTest.js +1 -1
  109. package/Build/Workers/upsampleQuantizedTerrainMesh.js +22 -22
  110. package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +25 -25
  111. package/Source/Core/Cartesian2.js +1 -1
  112. package/Source/Core/Cartesian3.js +1 -1
  113. package/Source/Core/Cartesian4.js +1 -1
  114. package/Source/Core/ComponentDatatype.js +35 -0
  115. package/Source/Core/Ion.js +1 -1
  116. package/Source/Core/MapProjection.js +1 -0
  117. package/Source/Core/Matrix2.js +1 -1
  118. package/Source/Core/Matrix3.js +1 -1
  119. package/Source/Core/Matrix4.js +1 -1
  120. package/Source/Core/Resource.js +1 -1
  121. package/Source/Core/ScreenSpaceEventHandler.js +51 -41
  122. package/Source/Core/createColorRamp.js +37 -0
  123. package/Source/Core/globalTypes.js +25 -0
  124. package/Source/Renderer/Pass.js +3 -2
  125. package/Source/Renderer/createUniform.js +346 -239
  126. package/Source/Renderer/createUniformArray.js +494 -381
  127. package/Source/Scene/ArcGisMapService.js +1 -1
  128. package/Source/Scene/BufferPoint.js +1 -0
  129. package/Source/Scene/BufferPointCollection.js +14 -1
  130. package/Source/Scene/BufferPolygon.js +3 -2
  131. package/Source/Scene/BufferPolygonCollection.js +10 -0
  132. package/Source/Scene/BufferPolyline.js +1 -0
  133. package/Source/Scene/BufferPolylineCollection.js +2 -0
  134. package/Source/Scene/BufferPrimitiveCollection.js +79 -28
  135. package/Source/Scene/CameraEventAggregator.js +30 -18
  136. package/Source/Scene/Cesium3DTile.js +54 -1
  137. package/Source/Scene/Cesium3DTileContent.js +195 -254
  138. package/Source/Scene/Cesium3DTileContentFactory.js +10 -2
  139. package/Source/Scene/Cesium3DTileset.js +45 -5
  140. package/Source/Scene/Composite3DTileContent.js +254 -292
  141. package/Source/Scene/EdgeDisplayMode.js +50 -0
  142. package/Source/Scene/Empty3DTileContent.js +100 -132
  143. package/Source/Scene/GaussianSplat3DTileContent.js +436 -478
  144. package/Source/Scene/GeoJsonPrimitive.js +874 -0
  145. package/Source/Scene/Geometry3DTileContent.js +151 -185
  146. package/Source/Scene/GltfLoader.js +109 -0
  147. package/Source/Scene/Implicit3DTileContent.js +179 -214
  148. package/Source/Scene/MVTDataProvider.js +147 -0
  149. package/Source/Scene/Model/EdgeVisibilityPipelineStage.js +79 -311
  150. package/Source/Scene/Model/Model.js +34 -0
  151. package/Source/Scene/Model/Model3DTileContent.js +424 -458
  152. package/Source/Scene/Model/ModelDrawCommand.js +31 -3
  153. package/Source/Scene/Model/ModelUtility.js +4 -0
  154. package/Source/Scene/Model/createVectorTileBuffersFromModelComponents.js +466 -150
  155. package/Source/Scene/ModelComponents.js +39 -1
  156. package/Source/Scene/Multiple3DTileContent.js +291 -334
  157. package/Source/Scene/Scene.js +26 -0
  158. package/Source/Scene/Tileset3DTileContent.js +113 -146
  159. package/Source/Scene/UrlTemplate3DTilesDataProvider.js +499 -0
  160. package/Source/Scene/Vector3DTileContent.js +205 -234
  161. package/Source/Scene/VectorGltf3DTileContent.js +85 -36
  162. package/Source/Scene/VoxelPrimitive.js +159 -175
  163. package/Source/Scene/VoxelProvider.js +64 -91
  164. package/Source/Scene/buildVectorGltfFromMVT.js +1059 -0
  165. package/Source/Scene/buildVoxelCustomShader.js +199 -0
  166. package/Source/Scene/decodeMVT.js +634 -0
  167. package/Source/Scene/renderBufferPointCollection.js +110 -64
  168. package/Source/Scene/renderBufferPolygonCollection.js +102 -55
  169. package/Source/Scene/renderBufferPolylineCollection.js +365 -166
  170. package/Source/Shaders/BufferPointMaterialFS.glsl +1 -0
  171. package/Source/Shaders/BufferPointMaterialFS.js +1 -0
  172. package/Source/Shaders/BufferPointMaterialVS.glsl +19 -9
  173. package/Source/Shaders/BufferPointMaterialVS.js +20 -10
  174. package/Source/Shaders/BufferPolygonMaterialVS.glsl +13 -4
  175. package/Source/Shaders/BufferPolygonMaterialVS.js +14 -5
  176. package/Source/Shaders/BufferPolylineMaterialVS.glsl +16 -2
  177. package/Source/Shaders/BufferPolylineMaterialVS.js +17 -3
  178. package/Source/Shaders/Builtin/Constants/passCesium3DTileEdgesDirect.glsl +9 -0
  179. package/Source/Shaders/Builtin/Constants/passCesium3DTileEdgesDirect.js +11 -0
  180. package/Source/Shaders/Builtin/Constants/passOverlay.glsl +1 -1
  181. package/Source/Shaders/Builtin/Constants/passOverlay.js +1 -1
  182. package/Source/Shaders/Builtin/CzmBuiltins.js +2 -0
  183. package/Source/Shaders/Model/EdgeVisibilityStageVS.glsl +0 -1
  184. package/Source/Shaders/Model/EdgeVisibilityStageVS.js +0 -1
  185. package/index.d.ts +253 -35
  186. package/index.js +71 -62
  187. package/package.json +2 -2
@@ -0,0 +1,634 @@
1
+ // @ts-check
2
+ import RuntimeError from "../Core/RuntimeError.js";
3
+
4
+ // Mapbox Vector Tile specification:
5
+ // https://github.com/mapbox/vector-tile-spec/tree/master/2.1
6
+
7
+ /**
8
+ * @typedef {object} MVTPoint
9
+ * @property {number} x Tile-local x (0–extent)
10
+ * @property {number} y Tile-local y (0–extent)
11
+ * @ignore
12
+ */
13
+
14
+ /**
15
+ * @typedef {object} MVTFeature
16
+ * @property {"Point"|"LineString"|"Polygon"|"Unknown"} type
17
+ * @property {Array<MVTPoint>|Array<Array<MVTPoint>>} geometry
18
+ * @property {Record<string, string|number|boolean|bigint>} properties
19
+ * @ignore
20
+ */
21
+
22
+ /**
23
+ * @typedef {object} MVTLayer
24
+ * @property {string} name
25
+ * @property {number} extent
26
+ * @property {MVTFeature[]} features
27
+ * @ignore
28
+ */
29
+
30
+ /**
31
+ * @typedef {object} DecodedMVT
32
+ * @property {MVTLayer[]} layers
33
+ * @ignore
34
+ */
35
+
36
+ /**
37
+ * @typedef {(string|number|boolean|bigint)} MVTValue
38
+ * @ignore
39
+ */
40
+
41
+ /**
42
+ * @typedef {object} ReadTagResult
43
+ * @property {number} fieldNumber
44
+ * @property {number} wireType
45
+ * @property {number} newPos
46
+ * @ignore
47
+ */
48
+
49
+ /**
50
+ * @typedef {object} ReadVarintResult
51
+ * @property {number} value
52
+ * @property {number} newPos
53
+ * @ignore
54
+ */
55
+
56
+ /**
57
+ * @typedef {object} ReadBigVarintResult
58
+ * @property {bigint} value
59
+ * @property {number} newPos
60
+ * @ignore
61
+ */
62
+
63
+ const textDecoder = new TextDecoder();
64
+
65
+ // Geometry type enum from the MVT spec
66
+ const GeomType = {
67
+ UNKNOWN: 0,
68
+ POINT: 1,
69
+ LINESTRING: 2,
70
+ POLYGON: 3,
71
+ };
72
+
73
+ // Tile message field numbers (spec §4.1)
74
+ const TileField = {
75
+ LAYERS: 3,
76
+ };
77
+
78
+ // Layer message field numbers (spec §4.1)
79
+ const LayerField = {
80
+ NAME: 1,
81
+ FEATURES: 2,
82
+ KEYS: 3,
83
+ VALUES: 4,
84
+ EXTENT: 5,
85
+ };
86
+
87
+ // Feature message field numbers (spec §4.2)
88
+ const FeatureField = {
89
+ TAGS: 2,
90
+ TYPE: 3,
91
+ GEOMETRY: 4,
92
+ };
93
+
94
+ // Value message field numbers (spec §4.4)
95
+ const ValueField = {
96
+ STRING: 1,
97
+ FLOAT: 2,
98
+ DOUBLE: 3,
99
+ INT64: 4,
100
+ UINT64: 5,
101
+ SINT64: 6,
102
+ BOOL: 7,
103
+ };
104
+
105
+ const geomTypeName = ["Unknown", "Point", "LineString", "Polygon"];
106
+
107
+ /**
108
+ * Decode a Mapbox Vector Tile (MVT / .pbf) binary buffer into layers and
109
+ * features. Geometry coordinates remain in tile-local integer space
110
+ * (0 – layer.extent, typically 4096).
111
+ *
112
+ * @param {ArrayBuffer} arrayBuffer The raw .pbf tile binary
113
+ * @returns {DecodedMVT}
114
+ * @ignore
115
+ */
116
+ function decodeMVT(arrayBuffer) {
117
+ const bytes = new Uint8Array(arrayBuffer);
118
+ const layers = [];
119
+ let pos = 0;
120
+
121
+ while (pos < bytes.length) {
122
+ const tag = readTag(bytes, pos, bytes.length);
123
+ const fieldNumber = tag.fieldNumber;
124
+ const wireType = tag.wireType;
125
+ pos = tag.newPos;
126
+
127
+ // Tile.layers = field 3, wire type 2 (length-delimited)
128
+ if (fieldNumber === TileField.LAYERS && wireType === 2) {
129
+ const layerLength = readVarintLength(bytes, pos, bytes.length);
130
+ pos = layerLength.newPos;
131
+ const layerEnd = advanceByLength(
132
+ pos,
133
+ layerLength.value,
134
+ bytes.length,
135
+ "layer",
136
+ );
137
+ layers.push(decodeLayer(bytes, pos, layerEnd));
138
+ pos = layerEnd;
139
+ } else {
140
+ pos = skipField(bytes, pos, wireType, bytes.length);
141
+ }
142
+ }
143
+
144
+ return { layers };
145
+ }
146
+
147
+ /**
148
+ * @param {Uint8Array} bytes
149
+ * @param {number} start
150
+ * @param {number} end
151
+ * @returns {MVTLayer}
152
+ * @ignore
153
+ */
154
+ function decodeLayer(bytes, start, end) {
155
+ let pos = start;
156
+ let name = "";
157
+ let extent = 4096;
158
+ /** @type {string[]} */
159
+ const keys = [];
160
+ /** @type {Array.<string|number|boolean|bigint|undefined>} */
161
+ const values = [];
162
+ const rawFeatures = [];
163
+
164
+ while (pos < end) {
165
+ const tag = readTag(bytes, pos, end);
166
+ const fieldNumber = tag.fieldNumber;
167
+ const wireType = tag.wireType;
168
+ pos = tag.newPos;
169
+
170
+ if (fieldNumber === LayerField.NAME && wireType === 2) {
171
+ // name
172
+ const length = readVarintLength(bytes, pos, end);
173
+ pos = length.newPos;
174
+ const stringEnd = advanceByLength(pos, length.value, end, "layer name");
175
+ name = readString(bytes, pos, length.value);
176
+ pos = stringEnd;
177
+ } else if (fieldNumber === LayerField.FEATURES && wireType === 2) {
178
+ // feature
179
+ const length = readVarintLength(bytes, pos, end);
180
+ pos = length.newPos;
181
+ const featureEnd = advanceByLength(pos, length.value, end, "feature");
182
+ rawFeatures.push({ start: pos, end: featureEnd });
183
+ pos = featureEnd;
184
+ } else if (fieldNumber === LayerField.KEYS && wireType === 2) {
185
+ // key
186
+ const length = readVarintLength(bytes, pos, end);
187
+ pos = length.newPos;
188
+ const stringEnd = advanceByLength(pos, length.value, end, "key");
189
+ keys.push(readString(bytes, pos, length.value));
190
+ pos = stringEnd;
191
+ } else if (fieldNumber === LayerField.VALUES && wireType === 2) {
192
+ // value
193
+ const length = readVarintLength(bytes, pos, end);
194
+ pos = length.newPos;
195
+ const valueEnd = advanceByLength(pos, length.value, end, "value");
196
+ const value = decodeValue(bytes, pos, valueEnd);
197
+ values.push(value);
198
+ pos = valueEnd;
199
+ } else if (fieldNumber === LayerField.EXTENT && wireType === 0) {
200
+ // extent
201
+ const value = readVarint32(bytes, pos, end);
202
+ extent = value.value;
203
+ pos = value.newPos;
204
+ } else {
205
+ pos = skipField(bytes, pos, wireType, end);
206
+ }
207
+ }
208
+
209
+ const features = rawFeatures.map(({ start: featureStart, end: featureEnd }) =>
210
+ decodeFeature(bytes, featureStart, featureEnd, keys, values),
211
+ );
212
+
213
+ return { name, extent, features };
214
+ }
215
+
216
+ /**
217
+ * @param {Uint8Array} bytes
218
+ * @param {number} start
219
+ * @param {number} end
220
+ * @param {string[]} keys
221
+ * @param {Array.<string|number|boolean|bigint|undefined>} values
222
+ * @returns {MVTFeature}
223
+ * @ignore
224
+ */
225
+ function decodeFeature(bytes, start, end, keys, values) {
226
+ let pos = start;
227
+ let geomType = GeomType.UNKNOWN;
228
+ const tags = [];
229
+ const geometryCommands = [];
230
+
231
+ while (pos < end) {
232
+ const tag = readTag(bytes, pos, end);
233
+ const fieldNumber = tag.fieldNumber;
234
+ const wireType = tag.wireType;
235
+ pos = tag.newPos;
236
+
237
+ if (fieldNumber === FeatureField.TYPE && wireType === 0) {
238
+ // geometry type
239
+ const value = readVarint32(bytes, pos, end);
240
+ geomType = value.value;
241
+ pos = value.newPos;
242
+ } else if (fieldNumber === FeatureField.TAGS && wireType === 2) {
243
+ // tags (packed uint32)
244
+ const length = readVarintLength(bytes, pos, end);
245
+ pos = length.newPos;
246
+ const tagEnd = advanceByLength(pos, length.value, end, "feature tags");
247
+ while (pos < tagEnd) {
248
+ const value = readVarint32(bytes, pos, tagEnd);
249
+ tags.push(value.value);
250
+ pos = value.newPos;
251
+ }
252
+ } else if (fieldNumber === FeatureField.GEOMETRY && wireType === 2) {
253
+ // geometry (packed uint32 commands)
254
+ const length = readVarintLength(bytes, pos, end);
255
+ pos = length.newPos;
256
+ const geometryEnd = advanceByLength(
257
+ pos,
258
+ length.value,
259
+ end,
260
+ "feature geometry",
261
+ );
262
+ while (pos < geometryEnd) {
263
+ const value = readVarint32(bytes, pos, geometryEnd);
264
+ geometryCommands.push(value.value);
265
+ pos = value.newPos;
266
+ }
267
+ } else {
268
+ pos = skipField(bytes, pos, wireType, end);
269
+ }
270
+ }
271
+
272
+ // Build properties from tags
273
+ /** @type {Record<string, string|number|boolean|bigint>} */
274
+ const properties = {};
275
+ for (let i = 0; i < tags.length - 1; i += 2) {
276
+ const key = keys[tags[i]];
277
+ const value = values[tags[i + 1]];
278
+ if (typeof key !== "string" || value === undefined) {
279
+ continue;
280
+ }
281
+ properties[key] = value;
282
+ }
283
+
284
+ const geometry = decodeGeometry(geomType, geometryCommands);
285
+
286
+ return {
287
+ type: /** @type {"Point"|"LineString"|"Polygon"|"Unknown"} */ (
288
+ geomTypeName[geomType] ?? "Unknown"
289
+ ),
290
+ geometry,
291
+ properties,
292
+ };
293
+ }
294
+
295
+ /**
296
+ * Decode MVT geometry commands into coordinate arrays.
297
+ * @param {number} geomType
298
+ * @param {number[]} cmds
299
+ * @returns {*}
300
+ * @ignore
301
+ */
302
+ function decodeGeometry(geomType, cmds) {
303
+ let i = 0;
304
+ let x = 0;
305
+ let y = 0;
306
+
307
+ if (geomType === GeomType.POINT) {
308
+ const points = [];
309
+ while (i < cmds.length) {
310
+ const cmd = cmds[i++];
311
+ const cmdId = cmd & 0x7;
312
+ const count = cmd >> 3;
313
+ if (cmdId === 1) {
314
+ // MoveTo
315
+ for (let c = 0; c < count; c++) {
316
+ x += zigzag(cmds[i++]);
317
+ y += zigzag(cmds[i++]);
318
+ points.push({ x, y });
319
+ }
320
+ }
321
+ }
322
+ return points;
323
+ }
324
+
325
+ if (geomType === GeomType.LINESTRING) {
326
+ const lines = [];
327
+ let current = null;
328
+ while (i < cmds.length) {
329
+ const cmd = cmds[i++];
330
+ const cmdId = cmd & 0x7;
331
+ const count = cmd >> 3;
332
+ if (cmdId === 1) {
333
+ // MoveTo - start new line
334
+ if (current !== null) {
335
+ lines.push(current);
336
+ }
337
+ current = [];
338
+ x += zigzag(cmds[i++]);
339
+ y += zigzag(cmds[i++]);
340
+ current.push({ x, y });
341
+ } else if (cmdId === 2) {
342
+ // LineTo
343
+ for (let c = 0; c < count; c++) {
344
+ x += zigzag(cmds[i++]);
345
+ y += zigzag(cmds[i++]);
346
+ current.push({ x, y });
347
+ }
348
+ }
349
+ }
350
+ if (current !== null) {
351
+ lines.push(current);
352
+ }
353
+ return lines;
354
+ }
355
+
356
+ if (geomType === GeomType.POLYGON) {
357
+ const rings = [];
358
+ let current = null;
359
+ while (i < cmds.length) {
360
+ const cmd = cmds[i++];
361
+ const cmdId = cmd & 0x7;
362
+ const count = cmd >> 3;
363
+ if (cmdId === 1) {
364
+ // MoveTo - start ring
365
+ if (current !== null) {
366
+ rings.push(current);
367
+ }
368
+ current = [];
369
+ x += zigzag(cmds[i++]);
370
+ y += zigzag(cmds[i++]);
371
+ current.push({ x, y });
372
+ } else if (cmdId === 2) {
373
+ // LineTo
374
+ for (let c = 0; c < count; c++) {
375
+ x += zigzag(cmds[i++]);
376
+ y += zigzag(cmds[i++]);
377
+ current.push({ x, y });
378
+ }
379
+ } else if (cmdId === 7) {
380
+ // ClosePath
381
+ if (current !== null && current.length > 0) {
382
+ current.push({ x: current[0].x, y: current[0].y });
383
+ rings.push(current);
384
+ current = null;
385
+ }
386
+ }
387
+ }
388
+ if (current !== null) {
389
+ rings.push(current);
390
+ }
391
+ return rings;
392
+ }
393
+
394
+ return [];
395
+ }
396
+
397
+ /**
398
+ * @param {Uint8Array} bytes
399
+ * @param {number} start
400
+ * @param {number} end
401
+ * @returns {string|number|boolean|bigint|undefined}
402
+ * @ignore
403
+ */
404
+ function decodeValue(bytes, start, end) {
405
+ let pos = start;
406
+ while (pos < end) {
407
+ const tag = readTag(bytes, pos, end);
408
+ const fieldNumber = tag.fieldNumber;
409
+ const wireType = tag.wireType;
410
+ pos = tag.newPos;
411
+ if (fieldNumber === ValueField.STRING && wireType === 2) {
412
+ const length = readVarintLength(bytes, pos, end);
413
+ pos = length.newPos;
414
+ const stringEnd = advanceByLength(pos, length.value, end, "string value");
415
+ return readString(bytes, pos, stringEnd - pos);
416
+ } else if (fieldNumber === ValueField.FLOAT && wireType === 5) {
417
+ // float
418
+ advanceByLength(pos, 4, end, "float value");
419
+ const v = new DataView(
420
+ bytes.buffer,
421
+ bytes.byteOffset + pos,
422
+ 4,
423
+ ).getFloat32(0, true);
424
+ return v;
425
+ } else if (fieldNumber === ValueField.DOUBLE && wireType === 1) {
426
+ // double
427
+ advanceByLength(pos, 8, end, "double value");
428
+ const v = new DataView(
429
+ bytes.buffer,
430
+ bytes.byteOffset + pos,
431
+ 8,
432
+ ).getFloat64(0, true);
433
+ return v;
434
+ } else if (fieldNumber === ValueField.INT64 && wireType === 0) {
435
+ const value = readBigVarint(bytes, pos, end);
436
+ return toSafeNumber(value.value);
437
+ } else if (fieldNumber === ValueField.UINT64 && wireType === 0) {
438
+ const value = readBigVarint(bytes, pos, end);
439
+ return toSafeNumber(value.value);
440
+ } else if (fieldNumber === ValueField.SINT64 && wireType === 0) {
441
+ const value = readBigVarint(bytes, pos, end);
442
+ return toSafeNumber(zigzagBigInt(value.value));
443
+ } else if (fieldNumber === ValueField.BOOL && wireType === 0) {
444
+ const value = readVarint32(bytes, pos, end);
445
+ return value.value !== 0;
446
+ }
447
+ pos = skipField(bytes, pos, wireType, end);
448
+ }
449
+ return undefined;
450
+ }
451
+
452
+ /**
453
+ * @param {Uint8Array} bytes
454
+ * @param {number} pos
455
+ * @param {number} limit
456
+ * @returns {ReadTagResult}
457
+ * @ignore
458
+ */
459
+ function readTag(bytes, pos, limit) {
460
+ const value = readVarint32(bytes, pos, limit);
461
+ return {
462
+ fieldNumber: value.value >>> 3,
463
+ wireType: value.value & 0x7,
464
+ newPos: value.newPos,
465
+ };
466
+ }
467
+
468
+ /**
469
+ * @param {Uint8Array} bytes
470
+ * @param {number} pos
471
+ * @param {number} limit
472
+ * @returns {ReadVarintResult}
473
+ * @ignore
474
+ */
475
+ function readVarint32(bytes, pos, limit) {
476
+ const value = readBigVarint(bytes, pos, limit, 5);
477
+ if (value.value > 0xffffffffn) {
478
+ throw new RuntimeError("Invalid MVT uint32 varint.");
479
+ }
480
+ return {
481
+ value: Number(value.value),
482
+ newPos: value.newPos,
483
+ };
484
+ }
485
+
486
+ /**
487
+ * @param {Uint8Array} bytes
488
+ * @param {number} pos
489
+ * @param {number} limit
490
+ * @returns {ReadVarintResult}
491
+ * @ignore
492
+ */
493
+ function readVarintLength(bytes, pos, limit) {
494
+ const value = readBigVarint(bytes, pos, limit);
495
+ if (value.value > BigInt(Number.MAX_SAFE_INTEGER)) {
496
+ throw new RuntimeError("Invalid MVT length varint.");
497
+ }
498
+ return {
499
+ value: Number(value.value),
500
+ newPos: value.newPos,
501
+ };
502
+ }
503
+
504
+ /**
505
+ * @param {Uint8Array} bytes
506
+ * @param {number} pos
507
+ * @param {number} limit
508
+ * @param {number} [maxBytes=10]
509
+ * @returns {ReadBigVarintResult}
510
+ * @ignore
511
+ */
512
+ function readBigVarint(bytes, pos, limit, maxBytes) {
513
+ let result = 0n;
514
+ let shift = 0n;
515
+ let byteCount = 0;
516
+ const byteLimit = maxBytes ?? 10;
517
+
518
+ while (true) {
519
+ if (pos >= limit || pos >= bytes.length) {
520
+ throw new RuntimeError("Invalid MVT: truncated varint.");
521
+ }
522
+ const byte = bytes[pos++];
523
+ result |= BigInt(byte & 0x7f) << shift;
524
+ byteCount++;
525
+ if ((byte & 0x80) === 0) {
526
+ break;
527
+ }
528
+ if (byteCount >= byteLimit) {
529
+ throw new RuntimeError("Invalid MVT: varint is too long.");
530
+ }
531
+ shift += 7n;
532
+ }
533
+
534
+ return {
535
+ value: result,
536
+ newPos: pos,
537
+ };
538
+ }
539
+
540
+ /**
541
+ * @param {Uint8Array} bytes
542
+ * @param {number} pos
543
+ * @param {number} len
544
+ * @returns {string}
545
+ * @ignore
546
+ */
547
+ function readString(bytes, pos, len) {
548
+ const end = advanceByLength(pos, len, bytes.length, "string");
549
+ return textDecoder.decode(bytes.subarray(pos, end));
550
+ }
551
+
552
+ /**
553
+ * @param {number} pos
554
+ * @param {number} length
555
+ * @param {number} limit
556
+ * @param {string} fieldName
557
+ * @returns {number}
558
+ * @ignore
559
+ */
560
+ function advanceByLength(pos, length, limit, fieldName) {
561
+ if (!Number.isFinite(length) || length < 0) {
562
+ throw new RuntimeError(`Invalid MVT ${fieldName}: invalid length.`);
563
+ }
564
+ const end = pos + length;
565
+ if (!Number.isFinite(end) || end < pos || end > limit) {
566
+ throw new RuntimeError(
567
+ `Invalid MVT ${fieldName}: length exceeds available bytes.`,
568
+ );
569
+ }
570
+ return end;
571
+ }
572
+
573
+ /**
574
+ * @param {Uint8Array} bytes
575
+ * @param {number} pos
576
+ * @param {number} wireType
577
+ * @param {number} limit
578
+ * @returns {number} newPos
579
+ * @ignore
580
+ */
581
+ function skipField(bytes, pos, wireType, limit) {
582
+ if (wireType === 0) {
583
+ return readBigVarint(bytes, pos, limit).newPos;
584
+ } else if (wireType === 1) {
585
+ return advanceByLength(pos, 8, limit, "fixed64 field");
586
+ } else if (wireType === 2) {
587
+ const length = readVarintLength(bytes, pos, limit);
588
+ return advanceByLength(
589
+ length.newPos,
590
+ length.value,
591
+ limit,
592
+ "length-delimited field",
593
+ );
594
+ } else if (wireType === 5) {
595
+ return advanceByLength(pos, 4, limit, "fixed32 field");
596
+ }
597
+ throw new RuntimeError(`Unsupported protobuf wire type: ${wireType}`);
598
+ }
599
+
600
+ /**
601
+ * Decode a zigzag-encoded signed integer.
602
+ * @param {number} n
603
+ * @returns {number}
604
+ * @ignore
605
+ */
606
+ function zigzag(n) {
607
+ return (n >>> 1) ^ -(n & 1);
608
+ }
609
+
610
+ /**
611
+ * @param {bigint} n
612
+ * @returns {bigint}
613
+ * @ignore
614
+ */
615
+ function zigzagBigInt(n) {
616
+ return (n >> 1n) ^ -(n & 1n);
617
+ }
618
+
619
+ /**
620
+ * @param {bigint} value
621
+ * @returns {number|bigint}
622
+ * @ignore
623
+ */
624
+ function toSafeNumber(value) {
625
+ if (
626
+ value <= BigInt(Number.MAX_SAFE_INTEGER) &&
627
+ value >= BigInt(Number.MIN_SAFE_INTEGER)
628
+ ) {
629
+ return Number(value);
630
+ }
631
+ return value;
632
+ }
633
+
634
+ export default decodeMVT;