@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.
- package/Build/Workers/{chunk-GPIGURCG.js → chunk-3VFEWOBI.js} +7 -7
- package/Build/Workers/{chunk-BTX2NL3P.js → chunk-424RNO3D.js} +18 -18
- package/Build/Workers/{chunk-HSVQATK2.js → chunk-4MGMYHOO.js} +6 -6
- package/Build/Workers/{chunk-FIBS5S7R.js → chunk-4S7IE3LB.js} +2 -2
- package/Build/Workers/{chunk-A7ZBMVFS.js → chunk-52JDLOEM.js} +14 -14
- package/Build/Workers/{chunk-ZCCIIBZT.js → chunk-54I6Y66F.js} +6 -6
- package/Build/Workers/{chunk-J647NNZW.js → chunk-6YEE6JDR.js} +6 -6
- package/Build/Workers/{chunk-HVMG6AG4.js → chunk-7J2HKPRH.js} +9 -9
- package/Build/Workers/{chunk-K6NFIRFB.js → chunk-7WM2PX4V.js} +5 -5
- package/Build/Workers/{chunk-3LSD7OOA.js → chunk-ACXQXN46.js} +16 -16
- package/Build/Workers/{chunk-CZ23Y3RM.js → chunk-AYKR4VBR.js} +2 -2
- package/Build/Workers/{chunk-4MTRQFJP.js → chunk-C6J67V5A.js} +1 -1
- package/Build/Workers/{chunk-WTQGE7Q6.js → chunk-C6KNZ7T4.js} +17 -17
- package/Build/Workers/{chunk-AWFZHD2B.js → chunk-CFQP6LYM.js} +4 -4
- package/Build/Workers/{chunk-ST2UWDUU.js → chunk-CXOYE2WM.js} +5 -5
- package/Build/Workers/{chunk-H2A4USJR.js → chunk-CZEYZU4N.js} +10 -10
- package/Build/Workers/{chunk-DFEI5MAV.js → chunk-DBOEKL43.js} +7 -7
- package/Build/Workers/{chunk-A7A433MD.js → chunk-DDWSZVMY.js} +5 -5
- package/Build/Workers/{chunk-J7KQEKPK.js → chunk-DOBXCNC3.js} +13 -13
- package/Build/Workers/{chunk-URUCCIPS.js → chunk-E7VQ76KE.js} +6 -6
- package/Build/Workers/{chunk-ZAPOS52G.js → chunk-EBSIOBXY.js} +8 -8
- package/Build/Workers/{chunk-3VDDRF2E.js → chunk-EF2QYXGA.js} +14 -14
- package/Build/Workers/{chunk-WN6P5UDH.js → chunk-EPYXRCDB.js} +12 -12
- package/Build/Workers/{chunk-EZARA5FJ.js → chunk-F6QDY6HU.js} +13 -13
- package/Build/Workers/{chunk-GL7DNVUS.js → chunk-FRQZECAO.js} +5 -5
- package/Build/Workers/{chunk-VQKLRBIK.js → chunk-G7PXZRVF.js} +7 -7
- package/Build/Workers/{chunk-4QQXGTCE.js → chunk-INUEEEQA.js} +8 -8
- package/Build/Workers/{chunk-ITD2IN7N.js → chunk-IRBKFCEJ.js} +2 -2
- package/Build/Workers/{chunk-6SDGQI27.js → chunk-IYOUHCZB.js} +1 -1
- package/Build/Workers/{chunk-DYT5NR6P.js → chunk-J6BWOHUF.js} +3 -3
- package/Build/Workers/{chunk-4GF4MVPY.js → chunk-KFSTQKNM.js} +7 -7
- package/Build/Workers/{chunk-4XXHJI6Y.js → chunk-KKOSKAZB.js} +17 -17
- package/Build/Workers/{chunk-WC57YYBN.js → chunk-KSSWJIZW.js} +2 -2
- package/Build/Workers/{chunk-5T6QQAJW.js → chunk-M3B5JKSM.js} +1 -1
- package/Build/Workers/{chunk-QO2CGXMP.js → chunk-MPZHGZU6.js} +6 -6
- package/Build/Workers/{chunk-WUBKZFF6.js → chunk-MYP774IS.js} +9 -9
- package/Build/Workers/{chunk-WNN5D4W3.js → chunk-O3EA5HS7.js} +10 -10
- package/Build/Workers/{chunk-77RL3MBD.js → chunk-P3CK7MCY.js} +25 -4
- package/Build/Workers/{chunk-QXNQQYPV.js → chunk-Q3PY526V.js} +8 -8
- package/Build/Workers/{chunk-CKQP3DSS.js → chunk-QN67VG36.js} +6 -6
- package/Build/Workers/{chunk-ACFFCHHZ.js → chunk-QRWGUWI6.js} +11 -11
- package/Build/Workers/{chunk-LH5SF3XV.js → chunk-S4MCOY6I.js} +5 -5
- package/Build/Workers/{chunk-FVLVVOBQ.js → chunk-SMQZZOW6.js} +10 -10
- package/Build/Workers/{chunk-TA777BGS.js → chunk-TKKIREQ6.js} +1 -1
- package/Build/Workers/{chunk-AEAVLYPS.js → chunk-U3ZA64U7.js} +2 -2
- package/Build/Workers/{chunk-7LSFAEWF.js → chunk-UA25D5MX.js} +10 -10
- package/Build/Workers/{chunk-J3OFS2RD.js → chunk-UOOIQ3KX.js} +12 -12
- package/Build/Workers/{chunk-ND3NTTOF.js → chunk-V7VQKN6N.js} +6 -6
- package/Build/Workers/{chunk-I3A6DXYZ.js → chunk-VQYETPWC.js} +4 -4
- package/Build/Workers/{chunk-35H3UBIO.js → chunk-VWV2IJRB.js} +11 -11
- package/Build/Workers/{chunk-QSDY4NS7.js → chunk-XZMBNNDX.js} +9 -9
- package/Build/Workers/{chunk-TAI4HLII.js → chunk-Y57HREW5.js} +4 -4
- package/Build/Workers/{chunk-3TKLDHV3.js → chunk-Y5BF6AFU.js} +2 -2
- package/Build/Workers/{chunk-3XY3MVPG.js → chunk-YLY7NKAB.js} +4 -4
- package/Build/Workers/{chunk-BVAIWR7O.js → chunk-ZK3CF7ZD.js} +12 -12
- package/Build/Workers/{chunk-DH26SNAB.js → chunk-ZP7JMQV4.js} +1 -1
- package/Build/Workers/{chunk-3RFFPH4M.js → chunk-ZZ46LWL6.js} +1 -1
- package/Build/Workers/combineGeometry.js +24 -24
- package/Build/Workers/createBoxGeometry.js +18 -18
- package/Build/Workers/createBoxOutlineGeometry.js +16 -16
- package/Build/Workers/createCircleGeometry.js +26 -26
- package/Build/Workers/createCircleOutlineGeometry.js +19 -19
- package/Build/Workers/createCoplanarPolygonGeometry.js +33 -33
- package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +31 -31
- package/Build/Workers/createCorridorGeometry.js +29 -29
- package/Build/Workers/createCorridorOutlineGeometry.js +28 -28
- package/Build/Workers/createCylinderGeometry.js +20 -20
- package/Build/Workers/createCylinderOutlineGeometry.js +18 -18
- package/Build/Workers/createEllipseGeometry.js +26 -26
- package/Build/Workers/createEllipseOutlineGeometry.js +19 -19
- package/Build/Workers/createEllipsoidGeometry.js +19 -19
- package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -18
- package/Build/Workers/createFrustumGeometry.js +18 -18
- package/Build/Workers/createFrustumOutlineGeometry.js +18 -18
- package/Build/Workers/createGeometry.js +24 -24
- package/Build/Workers/createGroundPolylineGeometry.js +22 -22
- package/Build/Workers/createPlaneGeometry.js +16 -16
- package/Build/Workers/createPlaneOutlineGeometry.js +15 -15
- package/Build/Workers/createPolygonGeometry.js +32 -32
- package/Build/Workers/createPolygonOutlineGeometry.js +30 -30
- package/Build/Workers/createPolylineGeometry.js +25 -25
- package/Build/Workers/createPolylineVolumeGeometry.js +31 -31
- package/Build/Workers/createPolylineVolumeOutlineGeometry.js +27 -27
- package/Build/Workers/createRectangleGeometry.js +27 -27
- package/Build/Workers/createRectangleOutlineGeometry.js +20 -20
- package/Build/Workers/createSimplePolylineGeometry.js +23 -23
- package/Build/Workers/createSphereGeometry.js +19 -19
- package/Build/Workers/createSphereOutlineGeometry.js +18 -18
- package/Build/Workers/createTaskProcessorWorker.js +3 -3
- package/Build/Workers/createVectorTileClampedPolylines.js +14 -14
- package/Build/Workers/createVectorTileGeometries.js +24 -24
- package/Build/Workers/createVectorTilePoints.js +13 -13
- package/Build/Workers/createVectorTilePolygons.js +22 -22
- package/Build/Workers/createVectorTilePolylines.js +14 -14
- package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +25 -25
- package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +22 -22
- package/Build/Workers/createVerticesFromHeightmap.js +22 -22
- package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +20 -20
- package/Build/Workers/createWallGeometry.js +24 -24
- package/Build/Workers/createWallOutlineGeometry.js +23 -23
- package/Build/Workers/decodeDraco.js +10 -10
- package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
- package/Build/Workers/decodeI3S.js +10 -10
- package/Build/Workers/gaussianSplatSorter.js +4 -4
- package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
- package/Build/Workers/incrementallyBuildTerrainPicker.js +10 -10
- package/Build/Workers/transcodeKTX2.js +6 -6
- package/Build/Workers/transferTypedArrayTest.js +1 -1
- package/Build/Workers/upsampleQuantizedTerrainMesh.js +22 -22
- package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +25 -25
- package/Source/Core/Cartesian2.js +1 -1
- package/Source/Core/Cartesian3.js +1 -1
- package/Source/Core/Cartesian4.js +1 -1
- package/Source/Core/ComponentDatatype.js +35 -0
- package/Source/Core/Ion.js +1 -1
- package/Source/Core/MapProjection.js +1 -0
- package/Source/Core/Matrix2.js +1 -1
- package/Source/Core/Matrix3.js +1 -1
- package/Source/Core/Matrix4.js +1 -1
- package/Source/Core/Resource.js +1 -1
- package/Source/Core/ScreenSpaceEventHandler.js +51 -41
- package/Source/Core/createColorRamp.js +37 -0
- package/Source/Core/globalTypes.js +25 -0
- package/Source/Renderer/Pass.js +3 -2
- package/Source/Renderer/createUniform.js +346 -239
- package/Source/Renderer/createUniformArray.js +494 -381
- package/Source/Scene/ArcGisMapService.js +1 -1
- package/Source/Scene/BufferPoint.js +1 -0
- package/Source/Scene/BufferPointCollection.js +14 -1
- package/Source/Scene/BufferPolygon.js +3 -2
- package/Source/Scene/BufferPolygonCollection.js +10 -0
- package/Source/Scene/BufferPolyline.js +1 -0
- package/Source/Scene/BufferPolylineCollection.js +2 -0
- package/Source/Scene/BufferPrimitiveCollection.js +79 -28
- package/Source/Scene/CameraEventAggregator.js +30 -18
- package/Source/Scene/Cesium3DTile.js +54 -1
- package/Source/Scene/Cesium3DTileContent.js +195 -254
- package/Source/Scene/Cesium3DTileContentFactory.js +10 -2
- package/Source/Scene/Cesium3DTileset.js +45 -5
- package/Source/Scene/Composite3DTileContent.js +254 -292
- package/Source/Scene/EdgeDisplayMode.js +50 -0
- package/Source/Scene/Empty3DTileContent.js +100 -132
- package/Source/Scene/GaussianSplat3DTileContent.js +436 -478
- package/Source/Scene/GeoJsonPrimitive.js +874 -0
- package/Source/Scene/Geometry3DTileContent.js +151 -185
- package/Source/Scene/GltfLoader.js +109 -0
- package/Source/Scene/Implicit3DTileContent.js +179 -214
- package/Source/Scene/MVTDataProvider.js +147 -0
- package/Source/Scene/Model/EdgeVisibilityPipelineStage.js +79 -311
- package/Source/Scene/Model/Model.js +34 -0
- package/Source/Scene/Model/Model3DTileContent.js +424 -458
- package/Source/Scene/Model/ModelDrawCommand.js +31 -3
- package/Source/Scene/Model/ModelUtility.js +4 -0
- package/Source/Scene/Model/createVectorTileBuffersFromModelComponents.js +466 -150
- package/Source/Scene/ModelComponents.js +39 -1
- package/Source/Scene/Multiple3DTileContent.js +291 -334
- package/Source/Scene/Scene.js +26 -0
- package/Source/Scene/Tileset3DTileContent.js +113 -146
- package/Source/Scene/UrlTemplate3DTilesDataProvider.js +499 -0
- package/Source/Scene/Vector3DTileContent.js +205 -234
- package/Source/Scene/VectorGltf3DTileContent.js +85 -36
- package/Source/Scene/VoxelPrimitive.js +159 -175
- package/Source/Scene/VoxelProvider.js +64 -91
- package/Source/Scene/buildVectorGltfFromMVT.js +1059 -0
- package/Source/Scene/buildVoxelCustomShader.js +199 -0
- package/Source/Scene/decodeMVT.js +634 -0
- package/Source/Scene/renderBufferPointCollection.js +110 -64
- package/Source/Scene/renderBufferPolygonCollection.js +102 -55
- package/Source/Scene/renderBufferPolylineCollection.js +365 -166
- package/Source/Shaders/BufferPointMaterialFS.glsl +1 -0
- package/Source/Shaders/BufferPointMaterialFS.js +1 -0
- package/Source/Shaders/BufferPointMaterialVS.glsl +19 -9
- package/Source/Shaders/BufferPointMaterialVS.js +20 -10
- package/Source/Shaders/BufferPolygonMaterialVS.glsl +13 -4
- package/Source/Shaders/BufferPolygonMaterialVS.js +14 -5
- package/Source/Shaders/BufferPolylineMaterialVS.glsl +16 -2
- package/Source/Shaders/BufferPolylineMaterialVS.js +17 -3
- package/Source/Shaders/Builtin/Constants/passCesium3DTileEdgesDirect.glsl +9 -0
- package/Source/Shaders/Builtin/Constants/passCesium3DTileEdgesDirect.js +11 -0
- package/Source/Shaders/Builtin/Constants/passOverlay.glsl +1 -1
- package/Source/Shaders/Builtin/Constants/passOverlay.js +1 -1
- package/Source/Shaders/Builtin/CzmBuiltins.js +2 -0
- package/Source/Shaders/Model/EdgeVisibilityStageVS.glsl +0 -1
- package/Source/Shaders/Model/EdgeVisibilityStageVS.js +0 -1
- package/index.d.ts +253 -35
- package/index.js +71 -62
- 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;
|