@loaders.gl/tiles 4.0.0-beta.2 → 4.0.0-beta.4

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 (126) hide show
  1. package/dist/constants.js.map +1 -0
  2. package/dist/dist.dev.js +7777 -0
  3. package/dist/index.cjs +2537 -0
  4. package/dist/index.js +10 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/{esm/tileset → tileset}/format-3d-tiles/tileset-3d-traverser.js +2 -2
  7. package/dist/tileset/format-3d-tiles/tileset-3d-traverser.js.map +1 -0
  8. package/dist/{esm/tileset → tileset}/format-i3s/i3s-pending-tiles-register.js +1 -2
  9. package/dist/tileset/format-i3s/i3s-pending-tiles-register.js.map +1 -0
  10. package/dist/{esm/tileset → tileset}/format-i3s/i3s-tile-manager.js +3 -4
  11. package/dist/tileset/format-i3s/i3s-tile-manager.js.map +1 -0
  12. package/dist/{esm/tileset → tileset}/format-i3s/i3s-tileset-traverser.js +7 -8
  13. package/dist/tileset/format-i3s/i3s-tileset-traverser.js.map +1 -0
  14. package/dist/tileset/helpers/3d-tiles-options.js.map +1 -0
  15. package/dist/tileset/helpers/bounding-volume.d.ts +1 -1
  16. package/dist/tileset/helpers/bounding-volume.d.ts.map +1 -1
  17. package/dist/{esm/tileset → tileset}/helpers/bounding-volume.js +16 -6
  18. package/dist/tileset/helpers/bounding-volume.js.map +1 -0
  19. package/dist/tileset/helpers/frame-state.js.map +1 -0
  20. package/dist/tileset/helpers/i3s-lod.js.map +1 -0
  21. package/dist/tileset/helpers/tiles-3d-lod.js.map +1 -0
  22. package/dist/tileset/helpers/transform-utils.js.map +1 -0
  23. package/dist/{esm/tileset → tileset}/helpers/zoom.js +2 -2
  24. package/dist/tileset/helpers/zoom.js.map +1 -0
  25. package/dist/tileset/tile-3d.d.ts.map +1 -1
  26. package/dist/{esm/tileset → tileset}/tile-3d.js +55 -56
  27. package/dist/tileset/tile-3d.js.map +1 -0
  28. package/dist/tileset/tileset-3d.d.ts.map +1 -1
  29. package/dist/{esm/tileset → tileset}/tileset-3d.js +64 -62
  30. package/dist/tileset/tileset-3d.js.map +1 -0
  31. package/dist/{esm/tileset → tileset}/tileset-cache.js +4 -5
  32. package/dist/tileset/tileset-cache.js.map +1 -0
  33. package/dist/{esm/tileset → tileset}/tileset-traverser.js +12 -13
  34. package/dist/tileset/tileset-traverser.js.map +1 -0
  35. package/dist/types.js.map +1 -0
  36. package/dist/utils/doubly-linked-list-node.js +11 -0
  37. package/dist/utils/doubly-linked-list-node.js.map +1 -0
  38. package/dist/{esm/utils → utils}/doubly-linked-list.js +4 -5
  39. package/dist/utils/doubly-linked-list.js.map +1 -0
  40. package/dist/{esm/utils → utils}/managed-array.js +3 -4
  41. package/dist/utils/managed-array.js.map +1 -0
  42. package/package.json +21 -13
  43. package/src/tileset/helpers/bounding-volume.ts +53 -24
  44. package/src/tileset/helpers/zoom.ts +5 -5
  45. package/src/tileset/tile-3d.ts +1 -1
  46. package/src/tileset/tileset-3d.ts +6 -9
  47. package/dist/bundle.d.ts +0 -2
  48. package/dist/bundle.d.ts.map +0 -1
  49. package/dist/dist.min.js +0 -9231
  50. package/dist/es5/bundle.js +0 -6
  51. package/dist/es5/bundle.js.map +0 -1
  52. package/dist/es5/constants.js +0 -48
  53. package/dist/es5/constants.js.map +0 -1
  54. package/dist/es5/index.js +0 -93
  55. package/dist/es5/index.js.map +0 -1
  56. package/dist/es5/tileset/format-3d-tiles/tileset-3d-traverser.js +0 -70
  57. package/dist/es5/tileset/format-3d-tiles/tileset-3d-traverser.js.map +0 -1
  58. package/dist/es5/tileset/format-i3s/i3s-pending-tiles-register.js +0 -45
  59. package/dist/es5/tileset/format-i3s/i3s-pending-tiles-register.js.map +0 -1
  60. package/dist/es5/tileset/format-i3s/i3s-tile-manager.js +0 -84
  61. package/dist/es5/tileset/format-i3s/i3s-tile-manager.js.map +0 -1
  62. package/dist/es5/tileset/format-i3s/i3s-tileset-traverser.js +0 -143
  63. package/dist/es5/tileset/format-i3s/i3s-tileset-traverser.js.map +0 -1
  64. package/dist/es5/tileset/helpers/3d-tiles-options.js +0 -12
  65. package/dist/es5/tileset/helpers/3d-tiles-options.js.map +0 -1
  66. package/dist/es5/tileset/helpers/bounding-volume.js +0 -176
  67. package/dist/es5/tileset/helpers/bounding-volume.js.map +0 -1
  68. package/dist/es5/tileset/helpers/frame-state.js +0 -129
  69. package/dist/es5/tileset/helpers/frame-state.js.map +0 -1
  70. package/dist/es5/tileset/helpers/i3s-lod.js +0 -60
  71. package/dist/es5/tileset/helpers/i3s-lod.js.map +0 -1
  72. package/dist/es5/tileset/helpers/tiles-3d-lod.js +0 -103
  73. package/dist/es5/tileset/helpers/tiles-3d-lod.js.map +0 -1
  74. package/dist/es5/tileset/helpers/transform-utils.js +0 -50
  75. package/dist/es5/tileset/helpers/transform-utils.js.map +0 -1
  76. package/dist/es5/tileset/helpers/zoom.js +0 -63
  77. package/dist/es5/tileset/helpers/zoom.js.map +0 -1
  78. package/dist/es5/tileset/tile-3d.js +0 -536
  79. package/dist/es5/tileset/tile-3d.js.map +0 -1
  80. package/dist/es5/tileset/tileset-3d.js +0 -859
  81. package/dist/es5/tileset/tileset-3d.js.map +0 -1
  82. package/dist/es5/tileset/tileset-cache.js +0 -82
  83. package/dist/es5/tileset/tileset-cache.js.map +0 -1
  84. package/dist/es5/tileset/tileset-traverser.js +0 -321
  85. package/dist/es5/tileset/tileset-traverser.js.map +0 -1
  86. package/dist/es5/types.js +0 -2
  87. package/dist/es5/types.js.map +0 -1
  88. package/dist/es5/utils/doubly-linked-list-node.js +0 -21
  89. package/dist/es5/utils/doubly-linked-list-node.js.map +0 -1
  90. package/dist/es5/utils/doubly-linked-list.js +0 -88
  91. package/dist/es5/utils/doubly-linked-list.js.map +0 -1
  92. package/dist/es5/utils/managed-array.js +0 -126
  93. package/dist/es5/utils/managed-array.js.map +0 -1
  94. package/dist/esm/bundle.js +0 -4
  95. package/dist/esm/bundle.js.map +0 -1
  96. package/dist/esm/constants.js.map +0 -1
  97. package/dist/esm/index.js +0 -10
  98. package/dist/esm/index.js.map +0 -1
  99. package/dist/esm/tileset/format-3d-tiles/tileset-3d-traverser.js.map +0 -1
  100. package/dist/esm/tileset/format-i3s/i3s-pending-tiles-register.js.map +0 -1
  101. package/dist/esm/tileset/format-i3s/i3s-tile-manager.js.map +0 -1
  102. package/dist/esm/tileset/format-i3s/i3s-tileset-traverser.js.map +0 -1
  103. package/dist/esm/tileset/helpers/3d-tiles-options.js.map +0 -1
  104. package/dist/esm/tileset/helpers/bounding-volume.js.map +0 -1
  105. package/dist/esm/tileset/helpers/frame-state.js.map +0 -1
  106. package/dist/esm/tileset/helpers/i3s-lod.js.map +0 -1
  107. package/dist/esm/tileset/helpers/tiles-3d-lod.js.map +0 -1
  108. package/dist/esm/tileset/helpers/transform-utils.js.map +0 -1
  109. package/dist/esm/tileset/helpers/zoom.js.map +0 -1
  110. package/dist/esm/tileset/tile-3d.js.map +0 -1
  111. package/dist/esm/tileset/tileset-3d.js.map +0 -1
  112. package/dist/esm/tileset/tileset-cache.js.map +0 -1
  113. package/dist/esm/tileset/tileset-traverser.js.map +0 -1
  114. package/dist/esm/types.js.map +0 -1
  115. package/dist/esm/utils/doubly-linked-list-node.js +0 -12
  116. package/dist/esm/utils/doubly-linked-list-node.js.map +0 -1
  117. package/dist/esm/utils/doubly-linked-list.js.map +0 -1
  118. package/dist/esm/utils/managed-array.js.map +0 -1
  119. package/src/bundle.ts +0 -4
  120. /package/dist/{esm/constants.js → constants.js} +0 -0
  121. /package/dist/{esm/tileset → tileset}/helpers/3d-tiles-options.js +0 -0
  122. /package/dist/{esm/tileset → tileset}/helpers/frame-state.js +0 -0
  123. /package/dist/{esm/tileset → tileset}/helpers/i3s-lod.js +0 -0
  124. /package/dist/{esm/tileset → tileset}/helpers/tiles-3d-lod.js +0 -0
  125. /package/dist/{esm/tileset → tileset}/helpers/transform-utils.js +0 -0
  126. /package/dist/{esm/types.js → types.js} +0 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,2537 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ LOD_METRIC_TYPE: () => LOD_METRIC_TYPE,
24
+ TILESET_TYPE: () => TILESET_TYPE,
25
+ TILE_CONTENT_STATE: () => TILE_CONTENT_STATE,
26
+ TILE_REFINEMENT: () => TILE_REFINEMENT,
27
+ TILE_TYPE: () => TILE_TYPE,
28
+ Tile3D: () => Tile3D,
29
+ Tileset3D: () => Tileset3D,
30
+ TilesetCache: () => TilesetCache,
31
+ TilesetTraverser: () => TilesetTraverser,
32
+ calculateTransformProps: () => calculateTransformProps,
33
+ createBoundingVolume: () => createBoundingVolume,
34
+ getFrameState: () => getFrameState,
35
+ getLodStatus: () => getLodStatus
36
+ });
37
+ module.exports = __toCommonJS(src_exports);
38
+
39
+ // src/tileset/tileset-3d.ts
40
+ var import_core10 = require("@math.gl/core");
41
+ var import_geospatial6 = require("@math.gl/geospatial");
42
+ var import_stats = require("@probe.gl/stats");
43
+ var import_loader_utils4 = require("@loaders.gl/loader-utils");
44
+
45
+ // src/utils/doubly-linked-list-node.ts
46
+ var DoublyLinkedListNode = class {
47
+ constructor(item, previous, next) {
48
+ this.item = item;
49
+ this.previous = previous;
50
+ this.next = next;
51
+ }
52
+ };
53
+
54
+ // src/utils/doubly-linked-list.ts
55
+ var DoublyLinkedList = class {
56
+ constructor() {
57
+ this.head = null;
58
+ this.tail = null;
59
+ this._length = 0;
60
+ }
61
+ get length() {
62
+ return this._length;
63
+ }
64
+ /**
65
+ * Adds the item to the end of the list
66
+ * @param {*} [item]
67
+ * @return {DoublyLinkedListNode}
68
+ */
69
+ add(item) {
70
+ const node = new DoublyLinkedListNode(item, this.tail, null);
71
+ if (this.tail) {
72
+ this.tail.next = node;
73
+ this.tail = node;
74
+ } else {
75
+ this.head = node;
76
+ this.tail = node;
77
+ }
78
+ ++this._length;
79
+ return node;
80
+ }
81
+ /**
82
+ * Removes the given node from the list
83
+ * @param {DoublyLinkedListNode} node
84
+ */
85
+ remove(node) {
86
+ if (!node) {
87
+ return;
88
+ }
89
+ if (node.previous && node.next) {
90
+ node.previous.next = node.next;
91
+ node.next.previous = node.previous;
92
+ } else if (node.previous) {
93
+ node.previous.next = null;
94
+ this.tail = node.previous;
95
+ } else if (node.next) {
96
+ node.next.previous = null;
97
+ this.head = node.next;
98
+ } else {
99
+ this.head = null;
100
+ this.tail = null;
101
+ }
102
+ node.next = null;
103
+ node.previous = null;
104
+ --this._length;
105
+ }
106
+ /**
107
+ * Moves nextNode after node
108
+ * @param {DoublyLinkedListNode} node
109
+ * @param {DoublyLinkedListNode} nextNode
110
+ */
111
+ splice(node, nextNode) {
112
+ if (node === nextNode) {
113
+ return;
114
+ }
115
+ this.remove(nextNode);
116
+ this._insert(node, nextNode);
117
+ }
118
+ _insert(node, nextNode) {
119
+ const oldNodeNext = node.next;
120
+ node.next = nextNode;
121
+ if (this.tail === node) {
122
+ this.tail = nextNode;
123
+ } else {
124
+ oldNodeNext.previous = nextNode;
125
+ }
126
+ nextNode.next = oldNodeNext;
127
+ nextNode.previous = node;
128
+ ++this._length;
129
+ }
130
+ };
131
+
132
+ // src/tileset/tileset-cache.ts
133
+ var TilesetCache = class {
134
+ constructor() {
135
+ this._list = new DoublyLinkedList();
136
+ this._sentinel = this._list.add("sentinel");
137
+ this._trimTiles = false;
138
+ }
139
+ reset() {
140
+ this._list.splice(this._list.tail, this._sentinel);
141
+ }
142
+ touch(tile) {
143
+ const node = tile._cacheNode;
144
+ if (node) {
145
+ this._list.splice(this._sentinel, node);
146
+ }
147
+ }
148
+ add(tileset, tile, addCallback) {
149
+ if (!tile._cacheNode) {
150
+ tile._cacheNode = this._list.add(tile);
151
+ if (addCallback) {
152
+ addCallback(tileset, tile);
153
+ }
154
+ }
155
+ }
156
+ unloadTile(tileset, tile, unloadCallback) {
157
+ const node = tile._cacheNode;
158
+ if (!node) {
159
+ return;
160
+ }
161
+ this._list.remove(node);
162
+ tile._cacheNode = null;
163
+ if (unloadCallback) {
164
+ unloadCallback(tileset, tile);
165
+ }
166
+ }
167
+ unloadTiles(tileset, unloadCallback) {
168
+ const trimTiles = this._trimTiles;
169
+ this._trimTiles = false;
170
+ const list = this._list;
171
+ const maximumMemoryUsageInBytes = tileset.maximumMemoryUsage * 1024 * 1024;
172
+ const sentinel = this._sentinel;
173
+ let node = list.head;
174
+ while (node !== sentinel && (tileset.gpuMemoryUsageInBytes > maximumMemoryUsageInBytes || trimTiles)) {
175
+ const tile = node.item;
176
+ node = node.next;
177
+ this.unloadTile(tileset, tile, unloadCallback);
178
+ }
179
+ }
180
+ trim() {
181
+ this._trimTiles = true;
182
+ }
183
+ };
184
+
185
+ // src/tileset/helpers/transform-utils.ts
186
+ var import_geospatial = require("@math.gl/geospatial");
187
+ var import_core = require("@math.gl/core");
188
+ var import_loader_utils = require("@loaders.gl/loader-utils");
189
+ function calculateTransformProps(tileHeader, tile) {
190
+ (0, import_loader_utils.assert)(tileHeader);
191
+ (0, import_loader_utils.assert)(tile);
192
+ const { rtcCenter, gltfUpAxis } = tile;
193
+ const {
194
+ computedTransform,
195
+ boundingVolume: { center }
196
+ } = tileHeader;
197
+ let modelMatrix = new import_core.Matrix4(computedTransform);
198
+ if (rtcCenter) {
199
+ modelMatrix.translate(rtcCenter);
200
+ }
201
+ switch (gltfUpAxis) {
202
+ case "Z":
203
+ break;
204
+ case "Y":
205
+ const rotationY = new import_core.Matrix4().rotateX(Math.PI / 2);
206
+ modelMatrix = modelMatrix.multiplyRight(rotationY);
207
+ break;
208
+ case "X":
209
+ const rotationX = new import_core.Matrix4().rotateY(-Math.PI / 2);
210
+ modelMatrix = modelMatrix.multiplyRight(rotationX);
211
+ break;
212
+ default:
213
+ break;
214
+ }
215
+ if (tile.isQuantized) {
216
+ modelMatrix.translate(tile.quantizedVolumeOffset).scale(tile.quantizedVolumeScale);
217
+ }
218
+ const cartesianOrigin = new import_core.Vector3(center);
219
+ tile.cartesianModelMatrix = modelMatrix;
220
+ tile.cartesianOrigin = cartesianOrigin;
221
+ const cartographicOrigin = import_geospatial.Ellipsoid.WGS84.cartesianToCartographic(
222
+ cartesianOrigin,
223
+ new import_core.Vector3()
224
+ );
225
+ const fromFixedFrameMatrix = import_geospatial.Ellipsoid.WGS84.eastNorthUpToFixedFrame(cartesianOrigin);
226
+ const toFixedFrameMatrix = fromFixedFrameMatrix.invert();
227
+ tile.cartographicModelMatrix = toFixedFrameMatrix.multiplyRight(modelMatrix);
228
+ tile.cartographicOrigin = cartographicOrigin;
229
+ if (!tile.coordinateSystem) {
230
+ tile.modelMatrix = tile.cartographicModelMatrix;
231
+ }
232
+ }
233
+
234
+ // src/tileset/helpers/frame-state.ts
235
+ var import_core2 = require("@math.gl/core");
236
+ var import_culling = require("@math.gl/culling");
237
+ var import_geospatial2 = require("@math.gl/geospatial");
238
+ var scratchVector = new import_core2.Vector3();
239
+ var scratchPosition = new import_core2.Vector3();
240
+ var cullingVolume = new import_culling.CullingVolume([
241
+ new import_culling.Plane(),
242
+ new import_culling.Plane(),
243
+ new import_culling.Plane(),
244
+ new import_culling.Plane(),
245
+ new import_culling.Plane(),
246
+ new import_culling.Plane()
247
+ ]);
248
+ function getFrameState(viewport, frameNumber) {
249
+ const { cameraDirection, cameraUp, height } = viewport;
250
+ const { metersPerUnit } = viewport.distanceScales;
251
+ const viewportCenterCartesian = worldToCartesian(viewport, viewport.center);
252
+ const enuToFixedTransform = import_geospatial2.Ellipsoid.WGS84.eastNorthUpToFixedFrame(viewportCenterCartesian);
253
+ const cameraPositionCartographic = viewport.unprojectPosition(viewport.cameraPosition);
254
+ const cameraPositionCartesian2 = import_geospatial2.Ellipsoid.WGS84.cartographicToCartesian(
255
+ cameraPositionCartographic,
256
+ new import_core2.Vector3()
257
+ );
258
+ const cameraDirectionCartesian = new import_core2.Vector3(
259
+ // @ts-ignore
260
+ enuToFixedTransform.transformAsVector(new import_core2.Vector3(cameraDirection).scale(metersPerUnit))
261
+ ).normalize();
262
+ const cameraUpCartesian = new import_core2.Vector3(
263
+ // @ts-ignore
264
+ enuToFixedTransform.transformAsVector(new import_core2.Vector3(cameraUp).scale(metersPerUnit))
265
+ ).normalize();
266
+ commonSpacePlanesToWGS84(viewport);
267
+ const ViewportClass = viewport.constructor;
268
+ const { longitude, latitude, width, bearing, zoom } = viewport;
269
+ const topDownViewport = new ViewportClass({
270
+ longitude,
271
+ latitude,
272
+ height,
273
+ width,
274
+ bearing,
275
+ zoom,
276
+ pitch: 0
277
+ });
278
+ return {
279
+ camera: {
280
+ position: cameraPositionCartesian2,
281
+ direction: cameraDirectionCartesian,
282
+ up: cameraUpCartesian
283
+ },
284
+ viewport,
285
+ topDownViewport,
286
+ height,
287
+ cullingVolume,
288
+ frameNumber,
289
+ // TODO: This can be the same between updates, what number is unique for between updates?
290
+ sseDenominator: 1.15
291
+ // Assumes fovy = 60 degrees
292
+ };
293
+ }
294
+ function limitSelectedTiles(tiles, frameState, maximumTilesSelected) {
295
+ if (maximumTilesSelected === 0 || tiles.length <= maximumTilesSelected) {
296
+ return [tiles, []];
297
+ }
298
+ const tuples = [];
299
+ const { longitude: viewportLongitude, latitude: viewportLatitude } = frameState.viewport;
300
+ for (const [index, tile] of tiles.entries()) {
301
+ const [longitude, latitude] = tile.header.mbs;
302
+ const deltaLon = Math.abs(viewportLongitude - longitude);
303
+ const deltaLat = Math.abs(viewportLatitude - latitude);
304
+ const distance = Math.sqrt(deltaLat * deltaLat + deltaLon * deltaLon);
305
+ tuples.push([index, distance]);
306
+ }
307
+ const tuplesSorted = tuples.sort((a, b) => a[1] - b[1]);
308
+ const selectedTiles = [];
309
+ for (let i = 0; i < maximumTilesSelected; i++) {
310
+ selectedTiles.push(tiles[tuplesSorted[i][0]]);
311
+ }
312
+ const unselectedTiles = [];
313
+ for (let i = maximumTilesSelected; i < tuplesSorted.length; i++) {
314
+ unselectedTiles.push(tiles[tuplesSorted[i][0]]);
315
+ }
316
+ return [selectedTiles, unselectedTiles];
317
+ }
318
+ function commonSpacePlanesToWGS84(viewport) {
319
+ const frustumPlanes = viewport.getFrustumPlanes();
320
+ const nearCenterCommon = closestPointOnPlane(frustumPlanes.near, viewport.cameraPosition);
321
+ const nearCenterCartesian = worldToCartesian(viewport, nearCenterCommon);
322
+ const cameraCartesian = worldToCartesian(viewport, viewport.cameraPosition, scratchPosition);
323
+ let i = 0;
324
+ cullingVolume.planes[i++].fromPointNormal(
325
+ nearCenterCartesian,
326
+ scratchVector.copy(nearCenterCartesian).subtract(cameraCartesian)
327
+ );
328
+ for (const dir in frustumPlanes) {
329
+ if (dir === "near") {
330
+ continue;
331
+ }
332
+ const plane = frustumPlanes[dir];
333
+ const posCommon = closestPointOnPlane(plane, nearCenterCommon, scratchPosition);
334
+ const cartesianPos = worldToCartesian(viewport, posCommon, scratchPosition);
335
+ cullingVolume.planes[i++].fromPointNormal(
336
+ cartesianPos,
337
+ // Want the normal to point into the frustum since that's what culling expects
338
+ scratchVector.copy(nearCenterCartesian).subtract(cartesianPos)
339
+ );
340
+ }
341
+ }
342
+ function closestPointOnPlane(plane, refPoint, out = new import_core2.Vector3()) {
343
+ const distanceToRef = plane.normal.dot(refPoint);
344
+ out.copy(plane.normal).scale(plane.distance - distanceToRef).add(refPoint);
345
+ return out;
346
+ }
347
+ function worldToCartesian(viewport, point, out = new import_core2.Vector3()) {
348
+ const cartographicPos = viewport.unprojectPosition(point);
349
+ return import_geospatial2.Ellipsoid.WGS84.cartographicToCartesian(cartographicPos, out);
350
+ }
351
+
352
+ // src/tileset/helpers/zoom.ts
353
+ var import_core3 = require("@math.gl/core");
354
+ var import_culling2 = require("@math.gl/culling");
355
+ var import_geospatial3 = require("@math.gl/geospatial");
356
+ var WGS84_RADIUS_X = 6378137;
357
+ var WGS84_RADIUS_Y = 6378137;
358
+ var WGS84_RADIUS_Z = 6356752314245179e-9;
359
+ var scratchVector2 = new import_core3.Vector3();
360
+ function getZoomFromBoundingVolume(boundingVolume, cartorgraphicCenter) {
361
+ if (boundingVolume instanceof import_culling2.OrientedBoundingBox) {
362
+ const { halfAxes } = boundingVolume;
363
+ const obbSize = getObbSize(halfAxes);
364
+ return Math.log2(WGS84_RADIUS_Z / (obbSize + cartorgraphicCenter[2]));
365
+ } else if (boundingVolume instanceof import_culling2.BoundingSphere) {
366
+ const { radius } = boundingVolume;
367
+ return Math.log2(WGS84_RADIUS_Z / (radius + cartorgraphicCenter[2]));
368
+ } else if (boundingVolume.width && boundingVolume.height) {
369
+ const { width, height } = boundingVolume;
370
+ const zoomX = Math.log2(WGS84_RADIUS_X / width);
371
+ const zoomY = Math.log2(WGS84_RADIUS_Y / height);
372
+ return (zoomX + zoomY) / 2;
373
+ }
374
+ return 1;
375
+ }
376
+ function getZoomFromFullExtent(fullExtent, cartorgraphicCenter, cartesianCenter) {
377
+ import_geospatial3.Ellipsoid.WGS84.cartographicToCartesian(
378
+ [fullExtent.xmax, fullExtent.ymax, fullExtent.zmax],
379
+ scratchVector2
380
+ );
381
+ const extentSize = Math.sqrt(
382
+ Math.pow(scratchVector2[0] - cartesianCenter[0], 2) + Math.pow(scratchVector2[1] - cartesianCenter[1], 2) + Math.pow(scratchVector2[2] - cartesianCenter[2], 2)
383
+ );
384
+ return Math.log2(WGS84_RADIUS_Z / (extentSize + cartorgraphicCenter[2]));
385
+ }
386
+ function getZoomFromExtent(extent, cartorgraphicCenter, cartesianCenter) {
387
+ const [xmin, ymin, xmax, ymax] = extent;
388
+ return getZoomFromFullExtent(
389
+ { xmin, xmax, ymin, ymax, zmin: 0, zmax: 0 },
390
+ cartorgraphicCenter,
391
+ cartesianCenter
392
+ );
393
+ }
394
+ function getObbSize(halfAxes) {
395
+ halfAxes.getColumn(0, scratchVector2);
396
+ const axeY = halfAxes.getColumn(1);
397
+ const axeZ = halfAxes.getColumn(2);
398
+ const farthestVertex = scratchVector2.add(axeY).add(axeZ);
399
+ const size = farthestVertex.len();
400
+ return size;
401
+ }
402
+
403
+ // src/tileset/tile-3d.ts
404
+ var import_core7 = require("@math.gl/core");
405
+ var import_culling4 = require("@math.gl/culling");
406
+ var import_core8 = require("@loaders.gl/core");
407
+
408
+ // src/constants.ts
409
+ var TILE_CONTENT_STATE = {
410
+ UNLOADED: 0,
411
+ // Has never been requested
412
+ LOADING: 1,
413
+ // Is waiting on a pending request
414
+ PROCESSING: 2,
415
+ // Request received. Contents are being processed for rendering. Depending on the content, it might make its own requests for external data.
416
+ READY: 3,
417
+ // Ready to render.
418
+ EXPIRED: 4,
419
+ // Is expired and will be unloaded once new content is loaded.
420
+ FAILED: 5
421
+ // Request failed.
422
+ };
423
+ var TILE_REFINEMENT = /* @__PURE__ */ ((TILE_REFINEMENT2) => {
424
+ TILE_REFINEMENT2[TILE_REFINEMENT2["ADD"] = 1] = "ADD";
425
+ TILE_REFINEMENT2[TILE_REFINEMENT2["REPLACE"] = 2] = "REPLACE";
426
+ return TILE_REFINEMENT2;
427
+ })(TILE_REFINEMENT || {});
428
+ var TILE_TYPE = /* @__PURE__ */ ((TILE_TYPE2) => {
429
+ TILE_TYPE2["EMPTY"] = "empty";
430
+ TILE_TYPE2["SCENEGRAPH"] = "scenegraph";
431
+ TILE_TYPE2["POINTCLOUD"] = "pointcloud";
432
+ TILE_TYPE2["MESH"] = "mesh";
433
+ return TILE_TYPE2;
434
+ })(TILE_TYPE || {});
435
+ var TILESET_TYPE = /* @__PURE__ */ ((TILESET_TYPE2) => {
436
+ TILESET_TYPE2["I3S"] = "I3S";
437
+ TILESET_TYPE2["TILES3D"] = "TILES3D";
438
+ return TILESET_TYPE2;
439
+ })(TILESET_TYPE || {});
440
+ var LOD_METRIC_TYPE = /* @__PURE__ */ ((LOD_METRIC_TYPE2) => {
441
+ LOD_METRIC_TYPE2["GEOMETRIC_ERROR"] = "geometricError";
442
+ LOD_METRIC_TYPE2["MAX_SCREEN_THRESHOLD"] = "maxScreenThreshold";
443
+ return LOD_METRIC_TYPE2;
444
+ })(LOD_METRIC_TYPE || {});
445
+ var TILE3D_OPTIMIZATION_HINT = {
446
+ NOT_COMPUTED: -1,
447
+ USE_OPTIMIZATION: 1,
448
+ SKIP_OPTIMIZATION: 0
449
+ };
450
+
451
+ // src/tileset/helpers/bounding-volume.ts
452
+ var import_core4 = require("@math.gl/core");
453
+ var import_culling3 = require("@math.gl/culling");
454
+ var import_geospatial4 = require("@math.gl/geospatial");
455
+ var import_loader_utils2 = require("@loaders.gl/loader-utils");
456
+ function defined(x) {
457
+ return x !== void 0 && x !== null;
458
+ }
459
+ var scratchPoint = new import_core4.Vector3();
460
+ var scratchScale = new import_core4.Vector3();
461
+ var scratchNorthWest = new import_core4.Vector3();
462
+ var scratchSouthEast = new import_core4.Vector3();
463
+ var scratchCenter = new import_core4.Vector3();
464
+ var scratchXAxis = new import_core4.Vector3();
465
+ var scratchYAxis = new import_core4.Vector3();
466
+ var scratchZAxis = new import_core4.Vector3();
467
+ function createBoundingVolume(boundingVolumeHeader, transform, result) {
468
+ (0, import_loader_utils2.assert)(boundingVolumeHeader, "3D Tile: boundingVolume must be defined");
469
+ if (boundingVolumeHeader.box) {
470
+ return createBox(boundingVolumeHeader.box, transform, result);
471
+ }
472
+ if (boundingVolumeHeader.region) {
473
+ return createObbFromRegion(boundingVolumeHeader.region);
474
+ }
475
+ if (boundingVolumeHeader.sphere) {
476
+ return createSphere(boundingVolumeHeader.sphere, transform, result);
477
+ }
478
+ throw new Error("3D Tile: boundingVolume must contain a sphere, region, or box");
479
+ }
480
+ function getCartographicBounds(boundingVolumeHeader, boundingVolume) {
481
+ if (boundingVolumeHeader.box) {
482
+ return orientedBoundingBoxToCartographicBounds(boundingVolume);
483
+ }
484
+ if (boundingVolumeHeader.region) {
485
+ const [west, south, east, north, minHeight, maxHeight] = boundingVolumeHeader.region;
486
+ return [
487
+ [(0, import_core4.degrees)(west), (0, import_core4.degrees)(south), minHeight],
488
+ [(0, import_core4.degrees)(east), (0, import_core4.degrees)(north), maxHeight]
489
+ ];
490
+ }
491
+ if (boundingVolumeHeader.sphere) {
492
+ return boundingSphereToCartographicBounds(boundingVolume);
493
+ }
494
+ throw new Error("Unkown boundingVolume type");
495
+ }
496
+ function createBox(box, transform, result) {
497
+ const center = new import_core4.Vector3(box[0], box[1], box[2]);
498
+ transform.transform(center, center);
499
+ let origin = [];
500
+ if (box.length === 10) {
501
+ const halfSize = box.slice(3, 6);
502
+ const quaternion = new import_core4.Quaternion();
503
+ quaternion.fromArray(box, 6);
504
+ const x = new import_core4.Vector3([1, 0, 0]);
505
+ const y = new import_core4.Vector3([0, 1, 0]);
506
+ const z = new import_core4.Vector3([0, 0, 1]);
507
+ x.transformByQuaternion(quaternion);
508
+ x.scale(halfSize[0]);
509
+ y.transformByQuaternion(quaternion);
510
+ y.scale(halfSize[1]);
511
+ z.transformByQuaternion(quaternion);
512
+ z.scale(halfSize[2]);
513
+ origin = [...x.toArray(), ...y.toArray(), ...z.toArray()];
514
+ } else {
515
+ origin = [...box.slice(3, 6), ...box.slice(6, 9), ...box.slice(9, 12)];
516
+ }
517
+ const xAxis = transform.transformAsVector(origin.slice(0, 3));
518
+ const yAxis = transform.transformAsVector(origin.slice(3, 6));
519
+ const zAxis = transform.transformAsVector(origin.slice(6, 9));
520
+ const halfAxes = new import_core4.Matrix3([
521
+ xAxis[0],
522
+ xAxis[1],
523
+ xAxis[2],
524
+ yAxis[0],
525
+ yAxis[1],
526
+ yAxis[2],
527
+ zAxis[0],
528
+ zAxis[1],
529
+ zAxis[2]
530
+ ]);
531
+ if (defined(result)) {
532
+ result.center = center;
533
+ result.halfAxes = halfAxes;
534
+ return result;
535
+ }
536
+ return new import_culling3.OrientedBoundingBox(center, halfAxes);
537
+ }
538
+ function createSphere(sphere, transform, result) {
539
+ const center = new import_core4.Vector3(sphere[0], sphere[1], sphere[2]);
540
+ transform.transform(center, center);
541
+ const scale = transform.getScale(scratchScale);
542
+ const uniformScale = Math.max(Math.max(scale[0], scale[1]), scale[2]);
543
+ const radius = sphere[3] * uniformScale;
544
+ if (defined(result)) {
545
+ result.center = center;
546
+ result.radius = radius;
547
+ return result;
548
+ }
549
+ return new import_culling3.BoundingSphere(center, radius);
550
+ }
551
+ function createObbFromRegion(region) {
552
+ const [west, south, east, north, minHeight, maxHeight] = region;
553
+ const northWest = import_geospatial4.Ellipsoid.WGS84.cartographicToCartesian(
554
+ [(0, import_core4.degrees)(west), (0, import_core4.degrees)(north), minHeight],
555
+ scratchNorthWest
556
+ );
557
+ const southEast = import_geospatial4.Ellipsoid.WGS84.cartographicToCartesian(
558
+ [(0, import_core4.degrees)(east), (0, import_core4.degrees)(south), maxHeight],
559
+ scratchSouthEast
560
+ );
561
+ const centerInCartesian = new import_core4.Vector3().addVectors(northWest, southEast).multiplyByScalar(0.5);
562
+ import_geospatial4.Ellipsoid.WGS84.cartesianToCartographic(centerInCartesian, scratchCenter);
563
+ import_geospatial4.Ellipsoid.WGS84.cartographicToCartesian(
564
+ [(0, import_core4.degrees)(east), scratchCenter[1], scratchCenter[2]],
565
+ scratchXAxis
566
+ );
567
+ import_geospatial4.Ellipsoid.WGS84.cartographicToCartesian(
568
+ [scratchCenter[0], (0, import_core4.degrees)(north), scratchCenter[2]],
569
+ scratchYAxis
570
+ );
571
+ import_geospatial4.Ellipsoid.WGS84.cartographicToCartesian(
572
+ [scratchCenter[0], scratchCenter[1], maxHeight],
573
+ scratchZAxis
574
+ );
575
+ return createBox(
576
+ [
577
+ ...centerInCartesian,
578
+ ...scratchXAxis.subtract(centerInCartesian),
579
+ ...scratchYAxis.subtract(centerInCartesian),
580
+ ...scratchZAxis.subtract(centerInCartesian)
581
+ ],
582
+ new import_core4.Matrix4()
583
+ );
584
+ }
585
+ function orientedBoundingBoxToCartographicBounds(boundingVolume) {
586
+ const result = emptyCartographicBounds();
587
+ const { halfAxes } = boundingVolume;
588
+ const xAxis = new import_core4.Vector3(halfAxes.getColumn(0));
589
+ const yAxis = new import_core4.Vector3(halfAxes.getColumn(1));
590
+ const zAxis = new import_core4.Vector3(halfAxes.getColumn(2));
591
+ for (let x = 0; x < 2; x++) {
592
+ for (let y = 0; y < 2; y++) {
593
+ for (let z = 0; z < 2; z++) {
594
+ scratchPoint.copy(boundingVolume.center);
595
+ scratchPoint.add(xAxis);
596
+ scratchPoint.add(yAxis);
597
+ scratchPoint.add(zAxis);
598
+ addToCartographicBounds(result, scratchPoint);
599
+ zAxis.negate();
600
+ }
601
+ yAxis.negate();
602
+ }
603
+ xAxis.negate();
604
+ }
605
+ return result;
606
+ }
607
+ function boundingSphereToCartographicBounds(boundingVolume) {
608
+ const result = emptyCartographicBounds();
609
+ const { center, radius } = boundingVolume;
610
+ const point = import_geospatial4.Ellipsoid.WGS84.scaleToGeodeticSurface(center, scratchPoint);
611
+ let zAxis;
612
+ if (point) {
613
+ zAxis = import_geospatial4.Ellipsoid.WGS84.geodeticSurfaceNormal(point);
614
+ } else {
615
+ zAxis = new import_core4.Vector3(0, 0, 1);
616
+ }
617
+ let xAxis = new import_core4.Vector3(zAxis[2], -zAxis[1], 0);
618
+ if (xAxis.len() > 0) {
619
+ xAxis.normalize();
620
+ } else {
621
+ xAxis = new import_core4.Vector3(0, 1, 0);
622
+ }
623
+ const yAxis = xAxis.clone().cross(zAxis);
624
+ for (const axis of [xAxis, yAxis, zAxis]) {
625
+ scratchScale.copy(axis).scale(radius);
626
+ for (let dir = 0; dir < 2; dir++) {
627
+ scratchPoint.copy(center);
628
+ scratchPoint.add(scratchScale);
629
+ addToCartographicBounds(result, scratchPoint);
630
+ scratchScale.negate();
631
+ }
632
+ }
633
+ return result;
634
+ }
635
+ function emptyCartographicBounds() {
636
+ return [
637
+ [Infinity, Infinity, Infinity],
638
+ [-Infinity, -Infinity, -Infinity]
639
+ ];
640
+ }
641
+ function addToCartographicBounds(target, cartesian) {
642
+ import_geospatial4.Ellipsoid.WGS84.cartesianToCartographic(cartesian, scratchPoint);
643
+ target[0][0] = Math.min(target[0][0], scratchPoint[0]);
644
+ target[0][1] = Math.min(target[0][1], scratchPoint[1]);
645
+ target[0][2] = Math.min(target[0][2], scratchPoint[2]);
646
+ target[1][0] = Math.max(target[1][0], scratchPoint[0]);
647
+ target[1][1] = Math.max(target[1][1], scratchPoint[1]);
648
+ target[1][2] = Math.max(target[1][2], scratchPoint[2]);
649
+ }
650
+
651
+ // src/tileset/helpers/tiles-3d-lod.ts
652
+ var import_core5 = require("@math.gl/core");
653
+ var scratchPositionNormal = new import_core5.Vector3();
654
+ var scratchCartographic = new import_core5.Vector3();
655
+ var scratchMatrix = new import_core5.Matrix4();
656
+ var scratchCenter2 = new import_core5.Vector3();
657
+ var scratchPosition2 = new import_core5.Vector3();
658
+ var scratchDirection = new import_core5.Vector3();
659
+ function fog(distanceToCamera, density) {
660
+ const scalar = distanceToCamera * density;
661
+ return 1 - Math.exp(-(scalar * scalar));
662
+ }
663
+ function getDynamicScreenSpaceError(tileset, distanceToCamera) {
664
+ if (tileset.dynamicScreenSpaceError && tileset.dynamicScreenSpaceErrorComputedDensity) {
665
+ const density = tileset.dynamicScreenSpaceErrorComputedDensity;
666
+ const factor = tileset.dynamicScreenSpaceErrorFactor;
667
+ const dynamicError = fog(distanceToCamera, density) * factor;
668
+ return dynamicError;
669
+ }
670
+ return 0;
671
+ }
672
+ function getTiles3DScreenSpaceError(tile, frameState, useParentLodMetric) {
673
+ const tileset = tile.tileset;
674
+ const parentLodMetricValue = tile.parent && tile.parent.lodMetricValue || tile.lodMetricValue;
675
+ const lodMetricValue = useParentLodMetric ? parentLodMetricValue : tile.lodMetricValue;
676
+ if (lodMetricValue === 0) {
677
+ return 0;
678
+ }
679
+ const distance = Math.max(tile._distanceToCamera, 1e-7);
680
+ const { height, sseDenominator } = frameState;
681
+ const { viewDistanceScale } = tileset.options;
682
+ let error = lodMetricValue * height * (viewDistanceScale || 1) / (distance * sseDenominator);
683
+ error -= getDynamicScreenSpaceError(tileset, distance);
684
+ return error;
685
+ }
686
+
687
+ // src/tileset/helpers/i3s-lod.ts
688
+ var import_core6 = require("@math.gl/core");
689
+ var import_geospatial5 = require("@math.gl/geospatial");
690
+ var cameraPositionCartesian = new import_core6.Vector3();
691
+ var toEye = new import_core6.Vector3();
692
+ var cameraPositionEnu = new import_core6.Vector3();
693
+ var extraVertexEnu = new import_core6.Vector3();
694
+ var projectedOriginVector = new import_core6.Vector3();
695
+ var enuToCartesianMatrix = new import_core6.Matrix4();
696
+ var cartesianToEnuMatrix = new import_core6.Matrix4();
697
+ function getLodStatus(tile, frameState) {
698
+ if (tile.lodMetricValue === 0 || isNaN(tile.lodMetricValue)) {
699
+ return "DIG";
700
+ }
701
+ const screenSize = 2 * getProjectedRadius(tile, frameState);
702
+ if (screenSize < 2) {
703
+ return "OUT";
704
+ }
705
+ if (!tile.header.children || screenSize <= tile.lodMetricValue) {
706
+ return "DRAW";
707
+ } else if (tile.header.children) {
708
+ return "DIG";
709
+ }
710
+ return "OUT";
711
+ }
712
+ function getProjectedRadius(tile, frameState) {
713
+ const { topDownViewport: viewport } = frameState;
714
+ const mbsLat = tile.header.mbs[1];
715
+ const mbsLon = tile.header.mbs[0];
716
+ const mbsZ = tile.header.mbs[2];
717
+ const mbsR = tile.header.mbs[3];
718
+ const mbsCenterCartesian = [...tile.boundingVolume.center];
719
+ const cameraPositionCartographic = viewport.unprojectPosition(viewport.cameraPosition);
720
+ import_geospatial5.Ellipsoid.WGS84.cartographicToCartesian(cameraPositionCartographic, cameraPositionCartesian);
721
+ toEye.copy(cameraPositionCartesian).subtract(mbsCenterCartesian).normalize();
722
+ import_geospatial5.Ellipsoid.WGS84.eastNorthUpToFixedFrame(mbsCenterCartesian, enuToCartesianMatrix);
723
+ cartesianToEnuMatrix.copy(enuToCartesianMatrix).invert();
724
+ cameraPositionEnu.copy(cameraPositionCartesian).transform(cartesianToEnuMatrix);
725
+ const projection = Math.sqrt(
726
+ cameraPositionEnu[0] * cameraPositionEnu[0] + cameraPositionEnu[1] * cameraPositionEnu[1]
727
+ );
728
+ const extraZ = projection * projection / cameraPositionEnu[2];
729
+ extraVertexEnu.copy([cameraPositionEnu[0], cameraPositionEnu[1], extraZ]);
730
+ const extraVertexCartesian = extraVertexEnu.transform(enuToCartesianMatrix);
731
+ const extraVectorCartesian = extraVertexCartesian.subtract(mbsCenterCartesian).normalize();
732
+ const radiusVector = toEye.cross(extraVectorCartesian).normalize().scale(mbsR);
733
+ const sphereMbsBorderVertexCartesian = radiusVector.add(mbsCenterCartesian);
734
+ const sphereMbsBorderVertexCartographic = import_geospatial5.Ellipsoid.WGS84.cartesianToCartographic(
735
+ sphereMbsBorderVertexCartesian
736
+ );
737
+ const projectedOrigin = viewport.project([mbsLon, mbsLat, mbsZ]);
738
+ const projectedMbsBorderVertex = viewport.project(
739
+ sphereMbsBorderVertexCartographic
740
+ );
741
+ const projectedRadius = projectedOriginVector.copy(projectedOrigin).subtract(projectedMbsBorderVertex).magnitude();
742
+ return projectedRadius;
743
+ }
744
+
745
+ // src/tileset/helpers/3d-tiles-options.ts
746
+ function get3dTilesOptions(tileset) {
747
+ return {
748
+ assetGltfUpAxis: tileset.asset && tileset.asset.gltfUpAxis || "Y"
749
+ };
750
+ }
751
+
752
+ // src/utils/managed-array.ts
753
+ var import_loader_utils3 = require("@loaders.gl/loader-utils");
754
+ var ManagedArray = class {
755
+ constructor(length = 0) {
756
+ this._map = /* @__PURE__ */ new Map();
757
+ this._array = new Array(length);
758
+ this._length = length;
759
+ }
760
+ /**
761
+ * Gets or sets the length of the array.
762
+ * If the set length is greater than the length of the internal array, the internal array is resized.
763
+ *
764
+ * @memberof ManagedArray.prototype
765
+ * @type Number
766
+ */
767
+ get length() {
768
+ return this._length;
769
+ }
770
+ set length(length) {
771
+ this._length = length;
772
+ if (length > this._array.length) {
773
+ this._array.length = length;
774
+ }
775
+ }
776
+ /**
777
+ * Gets the internal array.
778
+ *
779
+ * @memberof ManagedArray.prototype
780
+ * @type Array
781
+ * @readonly
782
+ */
783
+ get values() {
784
+ return this._array;
785
+ }
786
+ /**
787
+ * Gets the element at an index.
788
+ *
789
+ * @param {Number} index The index to get.
790
+ */
791
+ get(index) {
792
+ (0, import_loader_utils3.assert)(index < this._array.length);
793
+ return this._array[index];
794
+ }
795
+ /**
796
+ * Sets the element at an index. Resizes the array if index is greater than the length of the array.
797
+ *
798
+ * @param {Number} index The index to set.
799
+ * @param {*} element The element to set at index.
800
+ */
801
+ set(index, element) {
802
+ (0, import_loader_utils3.assert)(index >= 0);
803
+ if (index >= this.length) {
804
+ this.length = index + 1;
805
+ }
806
+ if (this._map.has(this._array[index])) {
807
+ this._map.delete(this._array[index]);
808
+ }
809
+ this._array[index] = element;
810
+ this._map.set(element, index);
811
+ }
812
+ delete(element) {
813
+ const index = this._map.get(element);
814
+ if (index >= 0) {
815
+ this._array.splice(index, 1);
816
+ this._map.delete(element);
817
+ this.length--;
818
+ }
819
+ }
820
+ /**
821
+ * Returns the last element in the array without modifying the array.
822
+ *
823
+ * @returns {*} The last element in the array.
824
+ */
825
+ peek() {
826
+ return this._array[this._length - 1];
827
+ }
828
+ /**
829
+ * Push an element into the array.
830
+ *
831
+ * @param {*} element The element to push.
832
+ */
833
+ push(element) {
834
+ if (!this._map.has(element)) {
835
+ const index = this.length++;
836
+ this._array[index] = element;
837
+ this._map.set(element, index);
838
+ }
839
+ }
840
+ /**
841
+ * Pop an element from the array.
842
+ *
843
+ * @returns {*} The last element in the array.
844
+ */
845
+ pop() {
846
+ const element = this._array[--this.length];
847
+ this._map.delete(element);
848
+ return element;
849
+ }
850
+ /**
851
+ * Resize the internal array if length > _array.length.
852
+ *
853
+ * @param {Number} length The length.
854
+ */
855
+ reserve(length) {
856
+ (0, import_loader_utils3.assert)(length >= 0);
857
+ if (length > this._array.length) {
858
+ this._array.length = length;
859
+ }
860
+ }
861
+ /**
862
+ * Resize the array.
863
+ *
864
+ * @param {Number} length The length.
865
+ */
866
+ resize(length) {
867
+ (0, import_loader_utils3.assert)(length >= 0);
868
+ this.length = length;
869
+ }
870
+ /**
871
+ * Trim the internal array to the specified length. Defaults to the current length.
872
+ *
873
+ * @param {Number} [length] The length.
874
+ */
875
+ trim(length) {
876
+ if (length === null || length === void 0) {
877
+ length = this.length;
878
+ }
879
+ this._array.length = length;
880
+ }
881
+ reset() {
882
+ this._array = [];
883
+ this._map = /* @__PURE__ */ new Map();
884
+ this._length = 0;
885
+ }
886
+ find(target) {
887
+ return this._map.has(target);
888
+ }
889
+ };
890
+
891
+ // src/tileset/tileset-traverser.ts
892
+ var DEFAULT_PROPS = {
893
+ loadSiblings: false,
894
+ skipLevelOfDetail: false,
895
+ maximumScreenSpaceError: 2,
896
+ updateTransforms: true,
897
+ onTraversalEnd: () => {
898
+ },
899
+ viewportTraversersMap: {},
900
+ basePath: ""
901
+ };
902
+ var TilesetTraverser = class {
903
+ // TODO nested props
904
+ constructor(options) {
905
+ // fulfill in traverse call
906
+ this.root = null;
907
+ // tiles should be rendered
908
+ this.selectedTiles = {};
909
+ // tiles should be loaded from server
910
+ this.requestedTiles = {};
911
+ // tiles does not have render content
912
+ this.emptyTiles = {};
913
+ this.lastUpdate = new Date().getTime();
914
+ this.updateDebounceTime = 1e3;
915
+ /** temporary storage to hold the traversed tiles during a traversal */
916
+ this._traversalStack = new ManagedArray();
917
+ this._emptyTraversalStack = new ManagedArray();
918
+ /** set in every traverse cycle */
919
+ this._frameNumber = null;
920
+ this.options = { ...DEFAULT_PROPS, ...options };
921
+ }
922
+ // RESULT
923
+ traversalFinished(frameState) {
924
+ return true;
925
+ }
926
+ // tiles should be visible
927
+ traverse(root, frameState, options) {
928
+ this.root = root;
929
+ this.options = { ...this.options, ...options };
930
+ this.reset();
931
+ this.updateTile(root, frameState);
932
+ this._frameNumber = frameState.frameNumber;
933
+ this.executeTraversal(root, frameState);
934
+ }
935
+ reset() {
936
+ this.requestedTiles = {};
937
+ this.selectedTiles = {};
938
+ this.emptyTiles = {};
939
+ this._traversalStack.reset();
940
+ this._emptyTraversalStack.reset();
941
+ }
942
+ /**
943
+ * Execute traverse
944
+ * Depth-first traversal that traverses all visible tiles and marks tiles for selection.
945
+ * If skipLevelOfDetail is off then a tile does not refine until all children are loaded.
946
+ * This is the traditional replacement refinement approach and is called the base traversal.
947
+ * Tiles that have a greater screen space error than the base screen space error are part of the base traversal,
948
+ * all other tiles are part of the skip traversal. The skip traversal allows for skipping levels of the tree
949
+ * and rendering children and parent tiles simultaneously.
950
+ */
951
+ /* eslint-disable-next-line complexity, max-statements */
952
+ executeTraversal(root, frameState) {
953
+ const stack = this._traversalStack;
954
+ root._selectionDepth = 1;
955
+ stack.push(root);
956
+ while (stack.length > 0) {
957
+ const tile = stack.pop();
958
+ let shouldRefine = false;
959
+ if (this.canTraverse(tile, frameState)) {
960
+ this.updateChildTiles(tile, frameState);
961
+ shouldRefine = this.updateAndPushChildren(
962
+ tile,
963
+ frameState,
964
+ stack,
965
+ tile.hasRenderContent ? tile._selectionDepth + 1 : tile._selectionDepth
966
+ );
967
+ }
968
+ const parent = tile.parent;
969
+ const parentRefines = Boolean(!parent || parent._shouldRefine);
970
+ const stoppedRefining = !shouldRefine;
971
+ if (!tile.hasRenderContent) {
972
+ this.emptyTiles[tile.id] = tile;
973
+ this.loadTile(tile, frameState);
974
+ if (stoppedRefining) {
975
+ this.selectTile(tile, frameState);
976
+ }
977
+ } else if (tile.refine === 1 /* ADD */) {
978
+ this.loadTile(tile, frameState);
979
+ this.selectTile(tile, frameState);
980
+ } else if (tile.refine === 2 /* REPLACE */) {
981
+ this.loadTile(tile, frameState);
982
+ if (stoppedRefining) {
983
+ this.selectTile(tile, frameState);
984
+ }
985
+ }
986
+ this.touchTile(tile, frameState);
987
+ tile._shouldRefine = shouldRefine && parentRefines;
988
+ }
989
+ const newTime = new Date().getTime();
990
+ if (this.traversalFinished(frameState) || newTime - this.lastUpdate > this.updateDebounceTime) {
991
+ this.lastUpdate = newTime;
992
+ this.options.onTraversalEnd(frameState);
993
+ }
994
+ }
995
+ updateChildTiles(tile, frameState) {
996
+ const children = tile.children;
997
+ for (const child of children) {
998
+ this.updateTile(child, frameState);
999
+ }
1000
+ }
1001
+ /* eslint-disable complexity, max-statements */
1002
+ updateAndPushChildren(tile, frameState, stack, depth) {
1003
+ const { loadSiblings, skipLevelOfDetail } = this.options;
1004
+ const children = tile.children;
1005
+ children.sort(this.compareDistanceToCamera.bind(this));
1006
+ const checkRefines = tile.refine === 2 /* REPLACE */ && tile.hasRenderContent && !skipLevelOfDetail;
1007
+ let hasVisibleChild = false;
1008
+ let refines = true;
1009
+ for (const child of children) {
1010
+ child._selectionDepth = depth;
1011
+ if (child.isVisibleAndInRequestVolume) {
1012
+ if (stack.find(child)) {
1013
+ stack.delete(child);
1014
+ }
1015
+ stack.push(child);
1016
+ hasVisibleChild = true;
1017
+ } else if (checkRefines || loadSiblings) {
1018
+ this.loadTile(child, frameState);
1019
+ this.touchTile(child, frameState);
1020
+ }
1021
+ if (checkRefines) {
1022
+ let childRefines;
1023
+ if (!child._inRequestVolume) {
1024
+ childRefines = false;
1025
+ } else if (!child.hasRenderContent) {
1026
+ childRefines = this.executeEmptyTraversal(child, frameState);
1027
+ } else {
1028
+ childRefines = child.contentAvailable;
1029
+ }
1030
+ refines = refines && childRefines;
1031
+ if (!refines) {
1032
+ return false;
1033
+ }
1034
+ }
1035
+ }
1036
+ if (!hasVisibleChild) {
1037
+ refines = false;
1038
+ }
1039
+ return refines;
1040
+ }
1041
+ /* eslint-enable complexity, max-statements */
1042
+ updateTile(tile, frameState) {
1043
+ this.updateTileVisibility(tile, frameState);
1044
+ }
1045
+ // tile to render in the browser
1046
+ selectTile(tile, frameState) {
1047
+ if (this.shouldSelectTile(tile)) {
1048
+ tile._selectedFrame = frameState.frameNumber;
1049
+ this.selectedTiles[tile.id] = tile;
1050
+ }
1051
+ }
1052
+ // tile to load from server
1053
+ loadTile(tile, frameState) {
1054
+ if (this.shouldLoadTile(tile)) {
1055
+ tile._requestedFrame = frameState.frameNumber;
1056
+ tile._priority = tile._getPriority();
1057
+ this.requestedTiles[tile.id] = tile;
1058
+ }
1059
+ }
1060
+ // cache tile
1061
+ touchTile(tile, frameState) {
1062
+ tile.tileset._cache.touch(tile);
1063
+ tile._touchedFrame = frameState.frameNumber;
1064
+ }
1065
+ // tile should be visible
1066
+ // tile should have children
1067
+ // tile LoD (level of detail) is not sufficient under current viewport
1068
+ canTraverse(tile, frameState, useParentMetric = false, ignoreVisibility = false) {
1069
+ if (!tile.hasChildren) {
1070
+ return false;
1071
+ }
1072
+ if (tile.hasTilesetContent) {
1073
+ return !tile.contentExpired;
1074
+ }
1075
+ if (!ignoreVisibility && !tile.isVisibleAndInRequestVolume) {
1076
+ return false;
1077
+ }
1078
+ return this.shouldRefine(tile, frameState, useParentMetric);
1079
+ }
1080
+ shouldLoadTile(tile) {
1081
+ return tile.hasUnloadedContent || tile.contentExpired;
1082
+ }
1083
+ shouldSelectTile(tile) {
1084
+ return tile.contentAvailable && !this.options.skipLevelOfDetail;
1085
+ }
1086
+ /** Decide if tile LoD (level of detail) is not sufficient under current viewport */
1087
+ shouldRefine(tile, frameState, useParentMetric = false) {
1088
+ let screenSpaceError = tile._screenSpaceError;
1089
+ if (useParentMetric) {
1090
+ screenSpaceError = tile.getScreenSpaceError(frameState, true);
1091
+ }
1092
+ return screenSpaceError > this.options.maximumScreenSpaceError;
1093
+ }
1094
+ updateTileVisibility(tile, frameState) {
1095
+ const viewportIds = [];
1096
+ if (this.options.viewportTraversersMap) {
1097
+ for (const key in this.options.viewportTraversersMap) {
1098
+ const value = this.options.viewportTraversersMap[key];
1099
+ if (value === frameState.viewport.id) {
1100
+ viewportIds.push(key);
1101
+ }
1102
+ }
1103
+ } else {
1104
+ viewportIds.push(frameState.viewport.id);
1105
+ }
1106
+ tile.updateVisibility(frameState, viewportIds);
1107
+ }
1108
+ // UTILITIES
1109
+ compareDistanceToCamera(b, a) {
1110
+ return b._distanceToCamera - a._distanceToCamera;
1111
+ }
1112
+ anyChildrenVisible(tile, frameState) {
1113
+ let anyVisible = false;
1114
+ for (const child of tile.children) {
1115
+ child.updateVisibility(frameState);
1116
+ anyVisible = anyVisible || child.isVisibleAndInRequestVolume;
1117
+ }
1118
+ return anyVisible;
1119
+ }
1120
+ // Depth-first traversal that checks if all nearest descendants with content are loaded.
1121
+ // Ignores visibility.
1122
+ executeEmptyTraversal(root, frameState) {
1123
+ let allDescendantsLoaded = true;
1124
+ const stack = this._emptyTraversalStack;
1125
+ stack.push(root);
1126
+ while (stack.length > 0 && allDescendantsLoaded) {
1127
+ const tile = stack.pop();
1128
+ this.updateTile(tile, frameState);
1129
+ if (!tile.isVisibleAndInRequestVolume) {
1130
+ this.loadTile(tile, frameState);
1131
+ }
1132
+ this.touchTile(tile, frameState);
1133
+ const traverse = !tile.hasRenderContent && this.canTraverse(tile, frameState, false, true);
1134
+ if (traverse) {
1135
+ const children = tile.children;
1136
+ for (const child of children) {
1137
+ if (stack.find(child)) {
1138
+ stack.delete(child);
1139
+ }
1140
+ stack.push(child);
1141
+ }
1142
+ } else if (!tile.contentAvailable && !tile.hasEmptyContent) {
1143
+ allDescendantsLoaded = false;
1144
+ }
1145
+ }
1146
+ return allDescendantsLoaded;
1147
+ }
1148
+ };
1149
+
1150
+ // src/tileset/tile-3d.ts
1151
+ var scratchVector3 = new import_core7.Vector3();
1152
+ function defined2(x) {
1153
+ return x !== void 0 && x !== null;
1154
+ }
1155
+ var Tile3D = class {
1156
+ // TODO i3s specific, needs to remove
1157
+ /**
1158
+ * @constructs
1159
+ * Create a Tile3D instance
1160
+ * @param tileset - Tileset3D instance
1161
+ * @param header - tile header - JSON loaded from a dataset
1162
+ * @param parentHeader - parent Tile3D instance
1163
+ * @param extendedId - optional ID to separate copies of a tile for different viewports.
1164
+ * const extendedId = `${tile.id}-${frameState.viewport.id}`;
1165
+ */
1166
+ // eslint-disable-next-line max-statements
1167
+ constructor(tileset, header, parentHeader, extendedId = "") {
1168
+ /** Different refinement algorithms used by I3S and 3D tiles */
1169
+ this.lodMetricType = "geometricError";
1170
+ /** The error, in meters, introduced if this tile is rendered and its children are not. */
1171
+ this.lodMetricValue = 0;
1172
+ /** @todo math.gl is not exporting BoundingVolume base type? */
1173
+ this.boundingVolume = null;
1174
+ /**
1175
+ * The tile's content. This represents the actual tile's payload,
1176
+ * not the content's metadata in the tileset JSON file.
1177
+ */
1178
+ this.content = null;
1179
+ this.contentState = TILE_CONTENT_STATE.UNLOADED;
1180
+ this.gpuMemoryUsageInBytes = 0;
1181
+ /** The tile's children - an array of Tile3D objects. */
1182
+ this.children = [];
1183
+ this.depth = 0;
1184
+ this.viewportIds = [];
1185
+ this.transform = new import_core7.Matrix4();
1186
+ this.extensions = null;
1187
+ /** TODO Cesium 3d tiles specific */
1188
+ this.implicitTiling = null;
1189
+ /** Container to store application specific data */
1190
+ this.userData = {};
1191
+ this.hasEmptyContent = false;
1192
+ this.hasTilesetContent = false;
1193
+ this.traverser = new TilesetTraverser({});
1194
+ /** Used by TilesetCache */
1195
+ this._cacheNode = null;
1196
+ this._frameNumber = null;
1197
+ // TODO Cesium 3d tiles specific
1198
+ this._expireDate = null;
1199
+ this._expiredContent = null;
1200
+ this._boundingBox = void 0;
1201
+ /** updated every frame for tree traversal and rendering optimizations: */
1202
+ this._distanceToCamera = 0;
1203
+ this._screenSpaceError = 0;
1204
+ this._visible = void 0;
1205
+ this._initialTransform = new import_core7.Matrix4();
1206
+ // Used by traverser, cannot be marked private
1207
+ this._priority = 0;
1208
+ this._selectedFrame = 0;
1209
+ this._requestedFrame = 0;
1210
+ this._selectionDepth = 0;
1211
+ this._touchedFrame = 0;
1212
+ this._centerZDepth = 0;
1213
+ this._shouldRefine = false;
1214
+ this._stackLength = 0;
1215
+ this._visitedFrame = 0;
1216
+ this._inRequestVolume = false;
1217
+ this._lodJudge = null;
1218
+ this.header = header;
1219
+ this.tileset = tileset;
1220
+ this.id = extendedId || header.id;
1221
+ this.url = header.url;
1222
+ this.parent = parentHeader;
1223
+ this.refine = this._getRefine(header.refine);
1224
+ this.type = header.type;
1225
+ this.contentUrl = header.contentUrl;
1226
+ this._initializeLodMetric(header);
1227
+ this._initializeTransforms(header);
1228
+ this._initializeBoundingVolumes(header);
1229
+ this._initializeContent(header);
1230
+ this._initializeRenderingState(header);
1231
+ Object.seal(this);
1232
+ }
1233
+ destroy() {
1234
+ this.header = null;
1235
+ }
1236
+ isDestroyed() {
1237
+ return this.header === null;
1238
+ }
1239
+ get selected() {
1240
+ return this._selectedFrame === this.tileset._frameNumber;
1241
+ }
1242
+ get isVisible() {
1243
+ return this._visible;
1244
+ }
1245
+ get isVisibleAndInRequestVolume() {
1246
+ return this._visible && this._inRequestVolume;
1247
+ }
1248
+ /** Returns true if tile is not an empty tile and not an external tileset */
1249
+ get hasRenderContent() {
1250
+ return !this.hasEmptyContent && !this.hasTilesetContent;
1251
+ }
1252
+ /** Returns true if tile has children */
1253
+ get hasChildren() {
1254
+ return this.children.length > 0 || this.header.children && this.header.children.length > 0;
1255
+ }
1256
+ /**
1257
+ * Determines if the tile's content is ready. This is automatically `true` for
1258
+ * tiles with empty content.
1259
+ */
1260
+ get contentReady() {
1261
+ return this.contentState === TILE_CONTENT_STATE.READY || this.hasEmptyContent;
1262
+ }
1263
+ /**
1264
+ * Determines if the tile has available content to render. `true` if the tile's
1265
+ * content is ready or if it has expired content this renders while new content loads; otherwise,
1266
+ */
1267
+ get contentAvailable() {
1268
+ return Boolean(
1269
+ this.contentReady && this.hasRenderContent || this._expiredContent && !this.contentFailed
1270
+ );
1271
+ }
1272
+ /** Returns true if tile has renderable content but it's unloaded */
1273
+ get hasUnloadedContent() {
1274
+ return this.hasRenderContent && this.contentUnloaded;
1275
+ }
1276
+ /**
1277
+ * Determines if the tile's content has not be requested. `true` if tile's
1278
+ * content has not be requested; otherwise, `false`.
1279
+ */
1280
+ get contentUnloaded() {
1281
+ return this.contentState === TILE_CONTENT_STATE.UNLOADED;
1282
+ }
1283
+ /**
1284
+ * Determines if the tile's content is expired. `true` if tile's
1285
+ * content is expired; otherwise, `false`.
1286
+ */
1287
+ get contentExpired() {
1288
+ return this.contentState === TILE_CONTENT_STATE.EXPIRED;
1289
+ }
1290
+ // Determines if the tile's content failed to load. `true` if the tile's
1291
+ // content failed to load; otherwise, `false`.
1292
+ get contentFailed() {
1293
+ return this.contentState === TILE_CONTENT_STATE.FAILED;
1294
+ }
1295
+ /**
1296
+ * Distance from the tile's bounding volume center to the camera
1297
+ */
1298
+ get distanceToCamera() {
1299
+ return this._distanceToCamera;
1300
+ }
1301
+ /**
1302
+ * Screen space error for LOD selection
1303
+ */
1304
+ get screenSpaceError() {
1305
+ return this._screenSpaceError;
1306
+ }
1307
+ /**
1308
+ * Get bounding box in cartographic coordinates
1309
+ * @returns [min, max] each in [longitude, latitude, altitude]
1310
+ */
1311
+ get boundingBox() {
1312
+ if (!this._boundingBox) {
1313
+ this._boundingBox = getCartographicBounds(this.header.boundingVolume, this.boundingVolume);
1314
+ }
1315
+ return this._boundingBox;
1316
+ }
1317
+ /** Get the tile's screen space error. */
1318
+ getScreenSpaceError(frameState, useParentLodMetric) {
1319
+ switch (this.tileset.type) {
1320
+ case "I3S" /* I3S */:
1321
+ return getProjectedRadius(this, frameState);
1322
+ case "TILES3D" /* TILES3D */:
1323
+ return getTiles3DScreenSpaceError(this, frameState, useParentLodMetric);
1324
+ default:
1325
+ throw new Error("Unsupported tileset type");
1326
+ }
1327
+ }
1328
+ /**
1329
+ * Make tile unselected than means it won't be shown
1330
+ * but it can be still loaded in memory
1331
+ */
1332
+ unselect() {
1333
+ this._selectedFrame = 0;
1334
+ }
1335
+ /**
1336
+ * Memory usage of tile on GPU
1337
+ */
1338
+ _getGpuMemoryUsageInBytes() {
1339
+ return this.content.gpuMemoryUsageInBytes || this.content.byteLength || 0;
1340
+ }
1341
+ /*
1342
+ * If skipLevelOfDetail is off try to load child tiles as soon as possible so that their parent can refine sooner.
1343
+ * Tiles are prioritized by screen space error.
1344
+ */
1345
+ // eslint-disable-next-line complexity
1346
+ _getPriority() {
1347
+ const traverser = this.tileset._traverser;
1348
+ const { skipLevelOfDetail } = traverser.options;
1349
+ const maySkipTile = this.refine === 1 /* ADD */ || skipLevelOfDetail;
1350
+ if (maySkipTile && !this.isVisible && this._visible !== void 0) {
1351
+ return -1;
1352
+ }
1353
+ if (this.tileset._frameNumber - this._touchedFrame >= 1) {
1354
+ return -1;
1355
+ }
1356
+ if (this.contentState === TILE_CONTENT_STATE.UNLOADED) {
1357
+ return -1;
1358
+ }
1359
+ const parent = this.parent;
1360
+ const useParentScreenSpaceError = parent && (!maySkipTile || this._screenSpaceError === 0 || parent.hasTilesetContent);
1361
+ const screenSpaceError = useParentScreenSpaceError ? parent._screenSpaceError : this._screenSpaceError;
1362
+ const rootScreenSpaceError = traverser.root ? traverser.root._screenSpaceError : 0;
1363
+ return Math.max(rootScreenSpaceError - screenSpaceError, 0);
1364
+ }
1365
+ /**
1366
+ * Requests the tile's content.
1367
+ * The request may not be made if the Request Scheduler can't prioritize it.
1368
+ */
1369
+ // eslint-disable-next-line max-statements, complexity
1370
+ async loadContent() {
1371
+ if (this.hasEmptyContent) {
1372
+ return false;
1373
+ }
1374
+ if (this.content) {
1375
+ return true;
1376
+ }
1377
+ const expired = this.contentExpired;
1378
+ if (expired) {
1379
+ this._expireDate = null;
1380
+ }
1381
+ this.contentState = TILE_CONTENT_STATE.LOADING;
1382
+ const requestToken = await this.tileset._requestScheduler.scheduleRequest(
1383
+ this.id,
1384
+ this._getPriority.bind(this)
1385
+ );
1386
+ if (!requestToken) {
1387
+ this.contentState = TILE_CONTENT_STATE.UNLOADED;
1388
+ return false;
1389
+ }
1390
+ try {
1391
+ const contentUrl = this.tileset.getTileUrl(this.contentUrl);
1392
+ const loader = this.tileset.loader;
1393
+ const options = {
1394
+ ...this.tileset.loadOptions,
1395
+ [loader.id]: {
1396
+ // @ts-expect-error
1397
+ ...this.tileset.loadOptions[loader.id],
1398
+ isTileset: this.type === "json",
1399
+ ...this._getLoaderSpecificOptions(loader.id)
1400
+ }
1401
+ };
1402
+ this.content = await (0, import_core8.load)(contentUrl, loader, options);
1403
+ if (this.tileset.options.contentLoader) {
1404
+ await this.tileset.options.contentLoader(this);
1405
+ }
1406
+ if (this._isTileset()) {
1407
+ this.tileset._initializeTileHeaders(this.content, this);
1408
+ }
1409
+ this.contentState = TILE_CONTENT_STATE.READY;
1410
+ this._onContentLoaded();
1411
+ return true;
1412
+ } catch (error) {
1413
+ this.contentState = TILE_CONTENT_STATE.FAILED;
1414
+ throw error;
1415
+ } finally {
1416
+ requestToken.done();
1417
+ }
1418
+ }
1419
+ // Unloads the tile's content.
1420
+ unloadContent() {
1421
+ if (this.content && this.content.destroy) {
1422
+ this.content.destroy();
1423
+ }
1424
+ this.content = null;
1425
+ if (this.header.content && this.header.content.destroy) {
1426
+ this.header.content.destroy();
1427
+ }
1428
+ this.header.content = null;
1429
+ this.contentState = TILE_CONTENT_STATE.UNLOADED;
1430
+ return true;
1431
+ }
1432
+ /**
1433
+ * Update the tile's visibility
1434
+ * @param {Object} frameState - frame state for tile culling
1435
+ * @param {string[]} viewportIds - a list of viewport ids that show this tile
1436
+ * @return {void}
1437
+ */
1438
+ updateVisibility(frameState, viewportIds) {
1439
+ if (this._frameNumber === frameState.frameNumber) {
1440
+ return;
1441
+ }
1442
+ const parent = this.parent;
1443
+ const parentVisibilityPlaneMask = parent ? parent._visibilityPlaneMask : import_culling4.CullingVolume.MASK_INDETERMINATE;
1444
+ if (this.tileset._traverser.options.updateTransforms) {
1445
+ const parentTransform = parent ? parent.computedTransform : this.tileset.modelMatrix;
1446
+ this._updateTransform(parentTransform);
1447
+ }
1448
+ this._distanceToCamera = this.distanceToTile(frameState);
1449
+ this._screenSpaceError = this.getScreenSpaceError(frameState, false);
1450
+ this._visibilityPlaneMask = this.visibility(frameState, parentVisibilityPlaneMask);
1451
+ this._visible = this._visibilityPlaneMask !== import_culling4.CullingVolume.MASK_OUTSIDE;
1452
+ this._inRequestVolume = this.insideViewerRequestVolume(frameState);
1453
+ this._frameNumber = frameState.frameNumber;
1454
+ this.viewportIds = viewportIds;
1455
+ }
1456
+ // Determines whether the tile's bounding volume intersects the culling volume.
1457
+ // @param {FrameState} frameState The frame state.
1458
+ // @param {Number} parentVisibilityPlaneMask The parent's plane mask to speed up the visibility check.
1459
+ // @returns {Number} A plane mask as described above in {@link CullingVolume#computeVisibilityWithPlaneMask}.
1460
+ visibility(frameState, parentVisibilityPlaneMask) {
1461
+ const { cullingVolume: cullingVolume2 } = frameState;
1462
+ const { boundingVolume } = this;
1463
+ return cullingVolume2.computeVisibilityWithPlaneMask(boundingVolume, parentVisibilityPlaneMask);
1464
+ }
1465
+ // Assuming the tile's bounding volume intersects the culling volume, determines
1466
+ // whether the tile's content's bounding volume intersects the culling volume.
1467
+ // @param {FrameState} frameState The frame state.
1468
+ // @returns {Intersect} The result of the intersection: the tile's content is completely outside, completely inside, or intersecting the culling volume.
1469
+ contentVisibility() {
1470
+ return true;
1471
+ }
1472
+ /**
1473
+ * Computes the (potentially approximate) distance from the closest point of the tile's bounding volume to the camera.
1474
+ * @param frameState The frame state.
1475
+ * @returns {Number} The distance, in meters, or zero if the camera is inside the bounding volume.
1476
+ */
1477
+ distanceToTile(frameState) {
1478
+ const boundingVolume = this.boundingVolume;
1479
+ return Math.sqrt(Math.max(boundingVolume.distanceSquaredTo(frameState.camera.position), 0));
1480
+ }
1481
+ /**
1482
+ * Computes the tile's camera-space z-depth.
1483
+ * @param frameState The frame state.
1484
+ * @returns The distance, in meters.
1485
+ */
1486
+ cameraSpaceZDepth({ camera }) {
1487
+ const boundingVolume = this.boundingVolume;
1488
+ scratchVector3.subVectors(boundingVolume.center, camera.position);
1489
+ return camera.direction.dot(scratchVector3);
1490
+ }
1491
+ /**
1492
+ * Checks if the camera is inside the viewer request volume.
1493
+ * @param {FrameState} frameState The frame state.
1494
+ * @returns {Boolean} Whether the camera is inside the volume.
1495
+ */
1496
+ insideViewerRequestVolume(frameState) {
1497
+ const viewerRequestVolume = this._viewerRequestVolume;
1498
+ return !viewerRequestVolume || viewerRequestVolume.distanceSquaredTo(frameState.camera.position) <= 0;
1499
+ }
1500
+ // TODO Cesium specific
1501
+ // Update whether the tile has expired.
1502
+ updateExpiration() {
1503
+ if (defined2(this._expireDate) && this.contentReady && !this.hasEmptyContent) {
1504
+ const now = Date.now();
1505
+ if (Date.lessThan(this._expireDate, now)) {
1506
+ this.contentState = TILE_CONTENT_STATE.EXPIRED;
1507
+ this._expiredContent = this.content;
1508
+ }
1509
+ }
1510
+ }
1511
+ get extras() {
1512
+ return this.header.extras;
1513
+ }
1514
+ // INTERNAL METHODS
1515
+ _initializeLodMetric(header) {
1516
+ if ("lodMetricType" in header) {
1517
+ this.lodMetricType = header.lodMetricType;
1518
+ } else {
1519
+ this.lodMetricType = this.parent && this.parent.lodMetricType || this.tileset.lodMetricType;
1520
+ console.warn(`3D Tile: Required prop lodMetricType is undefined. Using parent lodMetricType`);
1521
+ }
1522
+ if ("lodMetricValue" in header) {
1523
+ this.lodMetricValue = header.lodMetricValue;
1524
+ } else {
1525
+ this.lodMetricValue = this.parent && this.parent.lodMetricValue || this.tileset.lodMetricValue;
1526
+ console.warn(
1527
+ "3D Tile: Required prop lodMetricValue is undefined. Using parent lodMetricValue"
1528
+ );
1529
+ }
1530
+ }
1531
+ _initializeTransforms(tileHeader) {
1532
+ this.transform = tileHeader.transform ? new import_core7.Matrix4(tileHeader.transform) : new import_core7.Matrix4();
1533
+ const parent = this.parent;
1534
+ const tileset = this.tileset;
1535
+ const parentTransform = parent && parent.computedTransform ? parent.computedTransform.clone() : tileset.modelMatrix.clone();
1536
+ this.computedTransform = new import_core7.Matrix4(parentTransform).multiplyRight(this.transform);
1537
+ const parentInitialTransform = parent && parent._initialTransform ? parent._initialTransform.clone() : new import_core7.Matrix4();
1538
+ this._initialTransform = new import_core7.Matrix4(parentInitialTransform).multiplyRight(this.transform);
1539
+ }
1540
+ _initializeBoundingVolumes(tileHeader) {
1541
+ this._contentBoundingVolume = null;
1542
+ this._viewerRequestVolume = null;
1543
+ this._updateBoundingVolume(tileHeader);
1544
+ }
1545
+ _initializeContent(tileHeader) {
1546
+ this.content = { _tileset: this.tileset, _tile: this };
1547
+ this.hasEmptyContent = true;
1548
+ this.contentState = TILE_CONTENT_STATE.UNLOADED;
1549
+ this.hasTilesetContent = false;
1550
+ if (tileHeader.contentUrl) {
1551
+ this.content = null;
1552
+ this.hasEmptyContent = false;
1553
+ }
1554
+ }
1555
+ // TODO - remove anything not related to basic visibility detection
1556
+ _initializeRenderingState(header) {
1557
+ this.depth = header.level || (this.parent ? this.parent.depth + 1 : 0);
1558
+ this._shouldRefine = false;
1559
+ this._distanceToCamera = 0;
1560
+ this._centerZDepth = 0;
1561
+ this._screenSpaceError = 0;
1562
+ this._visibilityPlaneMask = import_culling4.CullingVolume.MASK_INDETERMINATE;
1563
+ this._visible = void 0;
1564
+ this._inRequestVolume = false;
1565
+ this._stackLength = 0;
1566
+ this._selectionDepth = 0;
1567
+ this._frameNumber = 0;
1568
+ this._touchedFrame = 0;
1569
+ this._visitedFrame = 0;
1570
+ this._selectedFrame = 0;
1571
+ this._requestedFrame = 0;
1572
+ this._priority = 0;
1573
+ }
1574
+ _getRefine(refine) {
1575
+ return refine || this.parent && this.parent.refine || 2 /* REPLACE */;
1576
+ }
1577
+ _isTileset() {
1578
+ return this.contentUrl.indexOf(".json") !== -1;
1579
+ }
1580
+ _onContentLoaded() {
1581
+ switch (this.content && this.content.type) {
1582
+ case "vctr":
1583
+ case "geom":
1584
+ this.tileset._traverser.disableSkipLevelOfDetail = true;
1585
+ break;
1586
+ default:
1587
+ }
1588
+ if (this._isTileset()) {
1589
+ this.hasTilesetContent = true;
1590
+ } else {
1591
+ this.gpuMemoryUsageInBytes = this._getGpuMemoryUsageInBytes();
1592
+ }
1593
+ }
1594
+ _updateBoundingVolume(header) {
1595
+ this.boundingVolume = createBoundingVolume(
1596
+ header.boundingVolume,
1597
+ this.computedTransform,
1598
+ this.boundingVolume
1599
+ );
1600
+ const content = header.content;
1601
+ if (!content) {
1602
+ return;
1603
+ }
1604
+ if (content.boundingVolume) {
1605
+ this._contentBoundingVolume = createBoundingVolume(
1606
+ content.boundingVolume,
1607
+ this.computedTransform,
1608
+ this._contentBoundingVolume
1609
+ );
1610
+ }
1611
+ if (header.viewerRequestVolume) {
1612
+ this._viewerRequestVolume = createBoundingVolume(
1613
+ header.viewerRequestVolume,
1614
+ this.computedTransform,
1615
+ this._viewerRequestVolume
1616
+ );
1617
+ }
1618
+ }
1619
+ // Update the tile's transform. The transform is applied to the tile's bounding volumes.
1620
+ _updateTransform(parentTransform = new import_core7.Matrix4()) {
1621
+ const computedTransform = parentTransform.clone().multiplyRight(this.transform);
1622
+ const didTransformChange = !computedTransform.equals(this.computedTransform);
1623
+ if (!didTransformChange) {
1624
+ return;
1625
+ }
1626
+ this.computedTransform = computedTransform;
1627
+ this._updateBoundingVolume(this.header);
1628
+ }
1629
+ // Get options which are applicable only for the particular loader
1630
+ _getLoaderSpecificOptions(loaderId) {
1631
+ switch (loaderId) {
1632
+ case "i3s":
1633
+ return {
1634
+ ...this.tileset.options.i3s,
1635
+ _tileOptions: {
1636
+ attributeUrls: this.header.attributeUrls,
1637
+ textureUrl: this.header.textureUrl,
1638
+ textureFormat: this.header.textureFormat,
1639
+ textureLoaderOptions: this.header.textureLoaderOptions,
1640
+ materialDefinition: this.header.materialDefinition,
1641
+ isDracoGeometry: this.header.isDracoGeometry,
1642
+ mbs: this.header.mbs
1643
+ },
1644
+ _tilesetOptions: {
1645
+ store: this.tileset.tileset.store,
1646
+ attributeStorageInfo: this.tileset.tileset.attributeStorageInfo,
1647
+ fields: this.tileset.tileset.fields
1648
+ },
1649
+ isTileHeader: false
1650
+ };
1651
+ case "3d-tiles":
1652
+ case "cesium-ion":
1653
+ default:
1654
+ return get3dTilesOptions(this.tileset.tileset);
1655
+ }
1656
+ }
1657
+ };
1658
+
1659
+ // src/tileset/format-3d-tiles/tileset-3d-traverser.ts
1660
+ var Tileset3DTraverser = class extends TilesetTraverser {
1661
+ compareDistanceToCamera(a, b) {
1662
+ return b._distanceToCamera === 0 && a._distanceToCamera === 0 ? b._centerZDepth - a._centerZDepth : b._distanceToCamera - a._distanceToCamera;
1663
+ }
1664
+ updateTileVisibility(tile, frameState) {
1665
+ super.updateTileVisibility(tile, frameState);
1666
+ if (!tile.isVisibleAndInRequestVolume) {
1667
+ return;
1668
+ }
1669
+ const hasChildren = tile.children.length > 0;
1670
+ if (tile.hasTilesetContent && hasChildren) {
1671
+ const firstChild = tile.children[0];
1672
+ this.updateTileVisibility(firstChild, frameState);
1673
+ tile._visible = firstChild._visible;
1674
+ return;
1675
+ }
1676
+ if (this.meetsScreenSpaceErrorEarly(tile, frameState)) {
1677
+ tile._visible = false;
1678
+ return;
1679
+ }
1680
+ const replace = tile.refine === 2 /* REPLACE */;
1681
+ const useOptimization = tile._optimChildrenWithinParent === TILE3D_OPTIMIZATION_HINT.USE_OPTIMIZATION;
1682
+ if (replace && useOptimization && hasChildren) {
1683
+ if (!this.anyChildrenVisible(tile, frameState)) {
1684
+ tile._visible = false;
1685
+ return;
1686
+ }
1687
+ }
1688
+ }
1689
+ meetsScreenSpaceErrorEarly(tile, frameState) {
1690
+ const { parent } = tile;
1691
+ if (!parent || parent.hasTilesetContent || parent.refine !== 1 /* ADD */) {
1692
+ return false;
1693
+ }
1694
+ return !this.shouldRefine(tile, frameState, true);
1695
+ }
1696
+ };
1697
+
1698
+ // src/tileset/format-i3s/i3s-tileset-traverser.ts
1699
+ var import_core9 = require("@loaders.gl/core");
1700
+
1701
+ // src/tileset/format-i3s/i3s-pending-tiles-register.ts
1702
+ var I3SPendingTilesRegister = class {
1703
+ constructor() {
1704
+ this.frameNumberMap = /* @__PURE__ */ new Map();
1705
+ }
1706
+ /**
1707
+ * Register a new pending tile header for the particular frameNumber
1708
+ * @param viewportId
1709
+ * @param frameNumber
1710
+ */
1711
+ register(viewportId, frameNumber) {
1712
+ const viewportMap = this.frameNumberMap.get(viewportId) || /* @__PURE__ */ new Map();
1713
+ const oldCount = viewportMap.get(frameNumber) || 0;
1714
+ viewportMap.set(frameNumber, oldCount + 1);
1715
+ this.frameNumberMap.set(viewportId, viewportMap);
1716
+ }
1717
+ /**
1718
+ * Deregister a pending tile header for the particular frameNumber
1719
+ * @param viewportId
1720
+ * @param frameNumber
1721
+ */
1722
+ deregister(viewportId, frameNumber) {
1723
+ const viewportMap = this.frameNumberMap.get(viewportId);
1724
+ if (!viewportMap) {
1725
+ return;
1726
+ }
1727
+ const oldCount = viewportMap.get(frameNumber) || 1;
1728
+ viewportMap.set(frameNumber, oldCount - 1);
1729
+ }
1730
+ /**
1731
+ * Check is there are no pending tile headers registered for the particular frameNumber
1732
+ * @param viewportId
1733
+ * @param frameNumber
1734
+ * @returns
1735
+ */
1736
+ isZero(viewportId, frameNumber) {
1737
+ var _a;
1738
+ const count = ((_a = this.frameNumberMap.get(viewportId)) == null ? void 0 : _a.get(frameNumber)) || 0;
1739
+ return count === 0;
1740
+ }
1741
+ };
1742
+
1743
+ // src/tileset/format-i3s/i3s-tile-manager.ts
1744
+ var STATUS = {
1745
+ REQUESTED: "REQUESTED",
1746
+ COMPLETED: "COMPLETED",
1747
+ ERROR: "ERROR"
1748
+ };
1749
+ var I3STileManager = class {
1750
+ constructor() {
1751
+ this.pendingTilesRegister = new I3SPendingTilesRegister();
1752
+ this._statusMap = {};
1753
+ }
1754
+ /**
1755
+ * Add request to map
1756
+ * @param request - node metadata request
1757
+ * @param key - unique key
1758
+ * @param callback - callback after request completed
1759
+ * @param frameState - frameState data
1760
+ */
1761
+ add(request, key, callback, frameState) {
1762
+ if (!this._statusMap[key]) {
1763
+ const {
1764
+ frameNumber,
1765
+ viewport: { id }
1766
+ } = frameState;
1767
+ this._statusMap[key] = { request, callback, key, frameState, status: STATUS.REQUESTED };
1768
+ this.pendingTilesRegister.register(id, frameNumber);
1769
+ request().then((data) => {
1770
+ this._statusMap[key].status = STATUS.COMPLETED;
1771
+ const {
1772
+ frameNumber: actualFrameNumber,
1773
+ viewport: { id: id2 }
1774
+ } = this._statusMap[key].frameState;
1775
+ this.pendingTilesRegister.deregister(id2, actualFrameNumber);
1776
+ this._statusMap[key].callback(data, frameState);
1777
+ }).catch((error) => {
1778
+ this._statusMap[key].status = STATUS.ERROR;
1779
+ const {
1780
+ frameNumber: actualFrameNumber,
1781
+ viewport: { id: id2 }
1782
+ } = this._statusMap[key].frameState;
1783
+ this.pendingTilesRegister.deregister(id2, actualFrameNumber);
1784
+ callback(error);
1785
+ });
1786
+ }
1787
+ }
1788
+ /**
1789
+ * Update request if it is still actual for the new frameState
1790
+ * @param key - unique key
1791
+ * @param frameState - frameState data
1792
+ */
1793
+ update(key, frameState) {
1794
+ if (this._statusMap[key]) {
1795
+ const {
1796
+ frameNumber,
1797
+ viewport: { id }
1798
+ } = this._statusMap[key].frameState;
1799
+ this.pendingTilesRegister.deregister(id, frameNumber);
1800
+ const {
1801
+ frameNumber: newFrameNumber,
1802
+ viewport: { id: newViewportId }
1803
+ } = frameState;
1804
+ this.pendingTilesRegister.register(newViewportId, newFrameNumber);
1805
+ this._statusMap[key].frameState = frameState;
1806
+ }
1807
+ }
1808
+ /**
1809
+ * Find request in the map
1810
+ * @param key - unique key
1811
+ * @returns
1812
+ */
1813
+ find(key) {
1814
+ return this._statusMap[key];
1815
+ }
1816
+ /**
1817
+ * Check it there are pending tile headers for the particular frameNumber
1818
+ * @param viewportId
1819
+ * @param frameNumber
1820
+ * @returns
1821
+ */
1822
+ hasPendingTiles(viewportId, frameNumber) {
1823
+ return !this.pendingTilesRegister.isZero(viewportId, frameNumber);
1824
+ }
1825
+ };
1826
+
1827
+ // src/tileset/format-i3s/i3s-tileset-traverser.ts
1828
+ var I3STilesetTraverser = class extends TilesetTraverser {
1829
+ constructor(options) {
1830
+ super(options);
1831
+ this._tileManager = new I3STileManager();
1832
+ }
1833
+ /**
1834
+ * Check if there are no penging tile header requests,
1835
+ * that means the traversal is finished and we can call
1836
+ * following-up callbacks.
1837
+ */
1838
+ traversalFinished(frameState) {
1839
+ return !this._tileManager.hasPendingTiles(frameState.viewport.id, this._frameNumber || 0);
1840
+ }
1841
+ shouldRefine(tile, frameState) {
1842
+ tile._lodJudge = getLodStatus(tile, frameState);
1843
+ return tile._lodJudge === "DIG";
1844
+ }
1845
+ updateChildTiles(tile, frameState) {
1846
+ const children = tile.header.children || [];
1847
+ const childTiles = tile.children;
1848
+ const tileset = tile.tileset;
1849
+ for (const child of children) {
1850
+ const extendedId = `${child.id}-${frameState.viewport.id}`;
1851
+ const childTile = childTiles && childTiles.find((t) => t.id === extendedId);
1852
+ if (!childTile) {
1853
+ let request = () => this._loadTile(child.id, tileset);
1854
+ const cachedRequest = this._tileManager.find(extendedId);
1855
+ if (!cachedRequest) {
1856
+ if (tileset.tileset.nodePages) {
1857
+ request = () => tileset.tileset.nodePagesTile.formTileFromNodePages(child.id);
1858
+ }
1859
+ this._tileManager.add(
1860
+ request,
1861
+ extendedId,
1862
+ (header) => this._onTileLoad(header, tile, extendedId),
1863
+ frameState
1864
+ );
1865
+ } else {
1866
+ this._tileManager.update(extendedId, frameState);
1867
+ }
1868
+ } else if (childTile) {
1869
+ this.updateTile(childTile, frameState);
1870
+ }
1871
+ }
1872
+ return false;
1873
+ }
1874
+ async _loadTile(nodeId, tileset) {
1875
+ const { loader } = tileset;
1876
+ const nodeUrl = tileset.getTileUrl(`${tileset.url}/nodes/${nodeId}`);
1877
+ const options = {
1878
+ ...tileset.loadOptions,
1879
+ i3s: {
1880
+ ...tileset.loadOptions.i3s,
1881
+ isTileHeader: true
1882
+ }
1883
+ };
1884
+ return await (0, import_core9.load)(nodeUrl, loader, options);
1885
+ }
1886
+ /**
1887
+ * The callback to init Tile3D instance after loading the tile JSON
1888
+ * @param {Object} header - the tile JSON from a dataset
1889
+ * @param {Tile3D} tile - the parent Tile3D instance
1890
+ * @param {string} extendedId - optional ID to separate copies of a tile for different viewports.
1891
+ * const extendedId = `${tile.id}-${frameState.viewport.id}`;
1892
+ * @return {void}
1893
+ */
1894
+ _onTileLoad(header, tile, extendedId) {
1895
+ const childTile = new Tile3D(tile.tileset, header, tile, extendedId);
1896
+ tile.children.push(childTile);
1897
+ const frameState = this._tileManager.find(childTile.id).frameState;
1898
+ this.updateTile(childTile, frameState);
1899
+ if (this._frameNumber === frameState.frameNumber && (this.traversalFinished(frameState) || new Date().getTime() - this.lastUpdate > this.updateDebounceTime)) {
1900
+ this.executeTraversal(childTile, frameState);
1901
+ }
1902
+ }
1903
+ };
1904
+
1905
+ // src/tileset/tileset-3d.ts
1906
+ var DEFAULT_PROPS2 = {
1907
+ description: "",
1908
+ ellipsoid: import_geospatial6.Ellipsoid.WGS84,
1909
+ modelMatrix: new import_core10.Matrix4(),
1910
+ throttleRequests: true,
1911
+ maxRequests: 64,
1912
+ maximumMemoryUsage: 32,
1913
+ maximumTilesSelected: 0,
1914
+ debounceTime: 0,
1915
+ onTileLoad: () => {
1916
+ },
1917
+ onTileUnload: () => {
1918
+ },
1919
+ onTileError: () => {
1920
+ },
1921
+ onTraversalComplete: (selectedTiles) => selectedTiles,
1922
+ contentLoader: void 0,
1923
+ viewDistanceScale: 1,
1924
+ maximumScreenSpaceError: 8,
1925
+ loadTiles: true,
1926
+ updateTransforms: true,
1927
+ viewportTraversersMap: null,
1928
+ loadOptions: { fetch: {} },
1929
+ attributions: [],
1930
+ basePath: "",
1931
+ i3s: {}
1932
+ };
1933
+ var TILES_TOTAL = "Tiles In Tileset(s)";
1934
+ var TILES_IN_MEMORY = "Tiles In Memory";
1935
+ var TILES_IN_VIEW = "Tiles In View";
1936
+ var TILES_RENDERABLE = "Tiles To Render";
1937
+ var TILES_LOADED = "Tiles Loaded";
1938
+ var TILES_LOADING = "Tiles Loading";
1939
+ var TILES_UNLOADED = "Tiles Unloaded";
1940
+ var TILES_LOAD_FAILED = "Failed Tile Loads";
1941
+ var POINTS_COUNT = "Points/Vertices";
1942
+ var TILES_GPU_MEMORY = "Tile Memory Use";
1943
+ var Tileset3D = class {
1944
+ /**
1945
+ * Create a new Tileset3D
1946
+ * @param json
1947
+ * @param props
1948
+ */
1949
+ // eslint-disable-next-line max-statements
1950
+ constructor(tileset, options) {
1951
+ this.root = null;
1952
+ this.roots = {};
1953
+ /** @todo any->unknown */
1954
+ this.asset = {};
1955
+ // Metadata for the entire tileset
1956
+ this.description = "";
1957
+ this.extras = null;
1958
+ this.attributions = {};
1959
+ this.credits = {};
1960
+ /** flags that contain information about data types in nested tiles */
1961
+ this.contentFormats = { draco: false, meshopt: false, dds: false, ktx2: false };
1962
+ // view props
1963
+ this.cartographicCenter = null;
1964
+ this.cartesianCenter = null;
1965
+ this.zoom = 1;
1966
+ this.boundingVolume = null;
1967
+ /** Updated based on the camera position and direction */
1968
+ this.dynamicScreenSpaceErrorComputedDensity = 0;
1969
+ // METRICS
1970
+ /**
1971
+ * The maximum amount of GPU memory (in MB) that may be used to cache tiles
1972
+ * Tiles not in view are unloaded to enforce private
1973
+ */
1974
+ this.maximumMemoryUsage = 32;
1975
+ /** The total amount of GPU memory in bytes used by the tileset. */
1976
+ this.gpuMemoryUsageInBytes = 0;
1977
+ /** Update tracker. increase in each update cycle. */
1978
+ this._frameNumber = 0;
1979
+ this._queryParams = {};
1980
+ this._extensionsUsed = [];
1981
+ this._tiles = {};
1982
+ /** counter for tracking tiles requests */
1983
+ this._pendingCount = 0;
1984
+ /** Hold traversal results */
1985
+ this.selectedTiles = [];
1986
+ // TRAVERSAL
1987
+ this.traverseCounter = 0;
1988
+ this.geometricError = 0;
1989
+ this.lastUpdatedVieports = null;
1990
+ this._requestedTiles = [];
1991
+ this._emptyTiles = [];
1992
+ this.frameStateData = {};
1993
+ this._cache = new TilesetCache();
1994
+ // Promise tracking
1995
+ this.updatePromise = null;
1996
+ this.options = { ...DEFAULT_PROPS2, ...options };
1997
+ this.tileset = tileset;
1998
+ this.loader = tileset.loader;
1999
+ this.type = tileset.type;
2000
+ this.url = tileset.url;
2001
+ this.basePath = tileset.basePath || import_loader_utils4.path.dirname(this.url);
2002
+ this.modelMatrix = this.options.modelMatrix;
2003
+ this.ellipsoid = this.options.ellipsoid;
2004
+ this.lodMetricType = tileset.lodMetricType;
2005
+ this.lodMetricValue = tileset.lodMetricValue;
2006
+ this.refine = tileset.root.refine;
2007
+ this.loadOptions = this.options.loadOptions || {};
2008
+ this._traverser = this._initializeTraverser();
2009
+ this._requestScheduler = new import_loader_utils4.RequestScheduler({
2010
+ throttleRequests: this.options.throttleRequests,
2011
+ maxRequests: this.options.maxRequests
2012
+ });
2013
+ this.stats = new import_stats.Stats({ id: this.url });
2014
+ this._initializeStats();
2015
+ this.tilesetInitializationPromise = this._initializeTileSet(tileset);
2016
+ }
2017
+ /** Release resources */
2018
+ destroy() {
2019
+ this._destroy();
2020
+ }
2021
+ /** Is the tileset loaded (update needs to have been called at least once) */
2022
+ isLoaded() {
2023
+ return this._pendingCount === 0 && this._frameNumber !== 0 && this._requestedTiles.length === 0;
2024
+ }
2025
+ get tiles() {
2026
+ return Object.values(this._tiles);
2027
+ }
2028
+ get frameNumber() {
2029
+ return this._frameNumber;
2030
+ }
2031
+ get queryParams() {
2032
+ return new URLSearchParams(this._queryParams).toString();
2033
+ }
2034
+ setProps(props) {
2035
+ this.options = { ...this.options, ...props };
2036
+ }
2037
+ /** @deprecated */
2038
+ setOptions(options) {
2039
+ this.options = { ...this.options, ...options };
2040
+ }
2041
+ /**
2042
+ * Return a loadable tile url for a specific tile subpath
2043
+ * @param tilePath a tile subpath
2044
+ */
2045
+ getTileUrl(tilePath) {
2046
+ const isDataUrl = tilePath.startsWith("data:");
2047
+ if (isDataUrl) {
2048
+ return tilePath;
2049
+ }
2050
+ let tileUrl = tilePath;
2051
+ if (this.queryParams.length) {
2052
+ tileUrl = `${tilePath}${tilePath.includes("?") ? "&" : "?"}${this.queryParams}`;
2053
+ }
2054
+ return tileUrl;
2055
+ }
2056
+ // TODO CESIUM specific
2057
+ hasExtension(extensionName) {
2058
+ return Boolean(this._extensionsUsed.indexOf(extensionName) > -1);
2059
+ }
2060
+ /**
2061
+ * Update visible tiles relying on a list of viewports
2062
+ * @param viewports - list of viewports
2063
+ * @deprecated
2064
+ */
2065
+ update(viewports = null) {
2066
+ this.tilesetInitializationPromise.then(() => {
2067
+ if (!viewports && this.lastUpdatedVieports) {
2068
+ viewports = this.lastUpdatedVieports;
2069
+ } else {
2070
+ this.lastUpdatedVieports = viewports;
2071
+ }
2072
+ if (viewports) {
2073
+ this.doUpdate(viewports);
2074
+ }
2075
+ });
2076
+ }
2077
+ /**
2078
+ * Update visible tiles relying on a list of viewports.
2079
+ * Do it with debounce delay to prevent update spam
2080
+ * @param viewports viewports
2081
+ * @returns Promise of new frameNumber
2082
+ */
2083
+ async selectTiles(viewports = null) {
2084
+ await this.tilesetInitializationPromise;
2085
+ if (viewports) {
2086
+ this.lastUpdatedVieports = viewports;
2087
+ }
2088
+ if (!this.updatePromise) {
2089
+ this.updatePromise = new Promise((resolve) => {
2090
+ setTimeout(() => {
2091
+ if (this.lastUpdatedVieports) {
2092
+ this.doUpdate(this.lastUpdatedVieports);
2093
+ }
2094
+ resolve(this._frameNumber);
2095
+ this.updatePromise = null;
2096
+ }, this.options.debounceTime);
2097
+ });
2098
+ }
2099
+ return this.updatePromise;
2100
+ }
2101
+ /**
2102
+ * Update visible tiles relying on a list of viewports
2103
+ * @param viewports viewports
2104
+ */
2105
+ // eslint-disable-next-line max-statements, complexity
2106
+ doUpdate(viewports) {
2107
+ if ("loadTiles" in this.options && !this.options.loadTiles) {
2108
+ return;
2109
+ }
2110
+ if (this.traverseCounter > 0) {
2111
+ return;
2112
+ }
2113
+ const preparedViewports = viewports instanceof Array ? viewports : [viewports];
2114
+ this._cache.reset();
2115
+ this._frameNumber++;
2116
+ this.traverseCounter = preparedViewports.length;
2117
+ const viewportsToTraverse = [];
2118
+ for (const viewport of preparedViewports) {
2119
+ const id = viewport.id;
2120
+ if (this._needTraverse(id)) {
2121
+ viewportsToTraverse.push(id);
2122
+ } else {
2123
+ this.traverseCounter--;
2124
+ }
2125
+ }
2126
+ for (const viewport of preparedViewports) {
2127
+ const id = viewport.id;
2128
+ if (!this.roots[id]) {
2129
+ this.roots[id] = this._initializeTileHeaders(this.tileset, null);
2130
+ }
2131
+ if (!viewportsToTraverse.includes(id)) {
2132
+ continue;
2133
+ }
2134
+ const frameState = getFrameState(viewport, this._frameNumber);
2135
+ this._traverser.traverse(this.roots[id], frameState, this.options);
2136
+ }
2137
+ }
2138
+ /**
2139
+ * Check if traversal is needed for particular viewport
2140
+ * @param {string} viewportId - id of a viewport
2141
+ * @return {boolean}
2142
+ */
2143
+ _needTraverse(viewportId) {
2144
+ let traverserId = viewportId;
2145
+ if (this.options.viewportTraversersMap) {
2146
+ traverserId = this.options.viewportTraversersMap[viewportId];
2147
+ }
2148
+ if (traverserId !== viewportId) {
2149
+ return false;
2150
+ }
2151
+ return true;
2152
+ }
2153
+ /**
2154
+ * The callback to post-process tiles after traversal procedure
2155
+ * @param frameState - frame state for tile culling
2156
+ */
2157
+ _onTraversalEnd(frameState) {
2158
+ const id = frameState.viewport.id;
2159
+ if (!this.frameStateData[id]) {
2160
+ this.frameStateData[id] = { selectedTiles: [], _requestedTiles: [], _emptyTiles: [] };
2161
+ }
2162
+ const currentFrameStateData = this.frameStateData[id];
2163
+ const selectedTiles = Object.values(this._traverser.selectedTiles);
2164
+ const [filteredSelectedTiles, unselectedTiles] = limitSelectedTiles(
2165
+ selectedTiles,
2166
+ frameState,
2167
+ this.options.maximumTilesSelected
2168
+ );
2169
+ currentFrameStateData.selectedTiles = filteredSelectedTiles;
2170
+ for (const tile of unselectedTiles) {
2171
+ tile.unselect();
2172
+ }
2173
+ currentFrameStateData._requestedTiles = Object.values(this._traverser.requestedTiles);
2174
+ currentFrameStateData._emptyTiles = Object.values(this._traverser.emptyTiles);
2175
+ this.traverseCounter--;
2176
+ if (this.traverseCounter > 0) {
2177
+ return;
2178
+ }
2179
+ this._updateTiles();
2180
+ }
2181
+ /**
2182
+ * Update tiles relying on data from all traversers
2183
+ */
2184
+ _updateTiles() {
2185
+ this.selectedTiles = [];
2186
+ this._requestedTiles = [];
2187
+ this._emptyTiles = [];
2188
+ for (const frameStateKey in this.frameStateData) {
2189
+ const frameStateDataValue = this.frameStateData[frameStateKey];
2190
+ this.selectedTiles = this.selectedTiles.concat(frameStateDataValue.selectedTiles);
2191
+ this._requestedTiles = this._requestedTiles.concat(frameStateDataValue._requestedTiles);
2192
+ this._emptyTiles = this._emptyTiles.concat(frameStateDataValue._emptyTiles);
2193
+ }
2194
+ this.selectedTiles = this.options.onTraversalComplete(this.selectedTiles);
2195
+ for (const tile of this.selectedTiles) {
2196
+ this._tiles[tile.id] = tile;
2197
+ }
2198
+ this._loadTiles();
2199
+ this._unloadTiles();
2200
+ this._updateStats();
2201
+ }
2202
+ _tilesChanged(oldSelectedTiles, selectedTiles) {
2203
+ if (oldSelectedTiles.length !== selectedTiles.length) {
2204
+ return true;
2205
+ }
2206
+ const set1 = new Set(oldSelectedTiles.map((t) => t.id));
2207
+ const set2 = new Set(selectedTiles.map((t) => t.id));
2208
+ let changed = oldSelectedTiles.filter((x) => !set2.has(x.id)).length > 0;
2209
+ changed = changed || selectedTiles.filter((x) => !set1.has(x.id)).length > 0;
2210
+ return changed;
2211
+ }
2212
+ _loadTiles() {
2213
+ for (const tile of this._requestedTiles) {
2214
+ if (tile.contentUnloaded) {
2215
+ this._loadTile(tile);
2216
+ }
2217
+ }
2218
+ }
2219
+ _unloadTiles() {
2220
+ this._cache.unloadTiles(this, (tileset, tile) => tileset._unloadTile(tile));
2221
+ }
2222
+ _updateStats() {
2223
+ let tilesRenderable = 0;
2224
+ let pointsRenderable = 0;
2225
+ for (const tile of this.selectedTiles) {
2226
+ if (tile.contentAvailable && tile.content) {
2227
+ tilesRenderable++;
2228
+ if (tile.content.pointCount) {
2229
+ pointsRenderable += tile.content.pointCount;
2230
+ } else {
2231
+ pointsRenderable += tile.content.vertexCount;
2232
+ }
2233
+ }
2234
+ }
2235
+ this.stats.get(TILES_IN_VIEW).count = this.selectedTiles.length;
2236
+ this.stats.get(TILES_RENDERABLE).count = tilesRenderable;
2237
+ this.stats.get(POINTS_COUNT).count = pointsRenderable;
2238
+ }
2239
+ async _initializeTileSet(tilesetJson) {
2240
+ if (this.type === "I3S" /* I3S */) {
2241
+ this.calculateViewPropsI3S();
2242
+ tilesetJson.root = await tilesetJson.root;
2243
+ }
2244
+ this.root = this._initializeTileHeaders(tilesetJson, null);
2245
+ if (this.type === "TILES3D" /* TILES3D */) {
2246
+ this._initializeTiles3DTileset(tilesetJson);
2247
+ this.calculateViewPropsTiles3D();
2248
+ }
2249
+ if (this.type === "I3S" /* I3S */) {
2250
+ this._initializeI3STileset();
2251
+ }
2252
+ }
2253
+ /**
2254
+ * Called during initialize Tileset to initialize the tileset's cartographic center (longitude, latitude) and zoom.
2255
+ * These metrics help apps center view on tileset
2256
+ * For I3S there is extent (<1.8 version) or fullExtent (>=1.8 version) to calculate view props
2257
+ * @returns
2258
+ */
2259
+ calculateViewPropsI3S() {
2260
+ var _a;
2261
+ const fullExtent = this.tileset.fullExtent;
2262
+ if (fullExtent) {
2263
+ const { xmin, xmax, ymin, ymax, zmin, zmax } = fullExtent;
2264
+ this.cartographicCenter = new import_core10.Vector3(
2265
+ xmin + (xmax - xmin) / 2,
2266
+ ymin + (ymax - ymin) / 2,
2267
+ zmin + (zmax - zmin) / 2
2268
+ );
2269
+ this.cartesianCenter = new import_core10.Vector3();
2270
+ import_geospatial6.Ellipsoid.WGS84.cartographicToCartesian(this.cartographicCenter, this.cartesianCenter);
2271
+ this.zoom = getZoomFromFullExtent(fullExtent, this.cartographicCenter, this.cartesianCenter);
2272
+ return;
2273
+ }
2274
+ const extent = (_a = this.tileset.store) == null ? void 0 : _a.extent;
2275
+ if (extent) {
2276
+ const [xmin, ymin, xmax, ymax] = extent;
2277
+ this.cartographicCenter = new import_core10.Vector3(xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2, 0);
2278
+ this.cartesianCenter = new import_core10.Vector3();
2279
+ import_geospatial6.Ellipsoid.WGS84.cartographicToCartesian(this.cartographicCenter, this.cartesianCenter);
2280
+ this.zoom = getZoomFromExtent(extent, this.cartographicCenter, this.cartesianCenter);
2281
+ return;
2282
+ }
2283
+ console.warn("Extent is not defined in the tileset header");
2284
+ this.cartographicCenter = new import_core10.Vector3();
2285
+ this.zoom = 1;
2286
+ return;
2287
+ }
2288
+ /**
2289
+ * Called during initialize Tileset to initialize the tileset's cartographic center (longitude, latitude) and zoom.
2290
+ * These metrics help apps center view on tileset.
2291
+ * For 3DTiles the root tile data is used to calculate view props.
2292
+ * @returns
2293
+ */
2294
+ calculateViewPropsTiles3D() {
2295
+ const root = this.root;
2296
+ const { center } = root.boundingVolume;
2297
+ if (!center) {
2298
+ console.warn("center was not pre-calculated for the root tile");
2299
+ this.cartographicCenter = new import_core10.Vector3();
2300
+ this.zoom = 1;
2301
+ return;
2302
+ }
2303
+ if (center[0] !== 0 || center[1] !== 0 || center[2] !== 0) {
2304
+ this.cartographicCenter = new import_core10.Vector3();
2305
+ import_geospatial6.Ellipsoid.WGS84.cartesianToCartographic(center, this.cartographicCenter);
2306
+ } else {
2307
+ this.cartographicCenter = new import_core10.Vector3(0, 0, -import_geospatial6.Ellipsoid.WGS84.radii[0]);
2308
+ }
2309
+ this.cartesianCenter = center;
2310
+ this.zoom = getZoomFromBoundingVolume(root.boundingVolume, this.cartographicCenter);
2311
+ }
2312
+ _initializeStats() {
2313
+ this.stats.get(TILES_TOTAL);
2314
+ this.stats.get(TILES_LOADING);
2315
+ this.stats.get(TILES_IN_MEMORY);
2316
+ this.stats.get(TILES_IN_VIEW);
2317
+ this.stats.get(TILES_RENDERABLE);
2318
+ this.stats.get(TILES_LOADED);
2319
+ this.stats.get(TILES_UNLOADED);
2320
+ this.stats.get(TILES_LOAD_FAILED);
2321
+ this.stats.get(POINTS_COUNT);
2322
+ this.stats.get(TILES_GPU_MEMORY, "memory");
2323
+ }
2324
+ // Installs the main tileset JSON file or a tileset JSON file referenced from a tile.
2325
+ // eslint-disable-next-line max-statements
2326
+ _initializeTileHeaders(tilesetJson, parentTileHeader) {
2327
+ var _a;
2328
+ const rootTile = new Tile3D(this, tilesetJson.root, parentTileHeader);
2329
+ if (parentTileHeader) {
2330
+ parentTileHeader.children.push(rootTile);
2331
+ rootTile.depth = parentTileHeader.depth + 1;
2332
+ }
2333
+ if (this.type === "TILES3D" /* TILES3D */) {
2334
+ const stack = [];
2335
+ stack.push(rootTile);
2336
+ while (stack.length > 0) {
2337
+ const tile = stack.pop();
2338
+ this.stats.get(TILES_TOTAL).incrementCount();
2339
+ const children = tile.header.children || [];
2340
+ for (const childHeader of children) {
2341
+ const childTile = new Tile3D(this, childHeader, tile);
2342
+ if ((_a = childTile.contentUrl) == null ? void 0 : _a.includes("?session=")) {
2343
+ const url = new URL(childTile.contentUrl);
2344
+ const session = url.searchParams.get("session");
2345
+ if (session) {
2346
+ this._queryParams.session = session;
2347
+ }
2348
+ }
2349
+ tile.children.push(childTile);
2350
+ childTile.depth = tile.depth + 1;
2351
+ stack.push(childTile);
2352
+ }
2353
+ }
2354
+ }
2355
+ return rootTile;
2356
+ }
2357
+ _initializeTraverser() {
2358
+ let TraverserClass;
2359
+ const type = this.type;
2360
+ switch (type) {
2361
+ case "TILES3D" /* TILES3D */:
2362
+ TraverserClass = Tileset3DTraverser;
2363
+ break;
2364
+ case "I3S" /* I3S */:
2365
+ TraverserClass = I3STilesetTraverser;
2366
+ break;
2367
+ default:
2368
+ TraverserClass = TilesetTraverser;
2369
+ }
2370
+ return new TraverserClass({
2371
+ basePath: this.basePath,
2372
+ onTraversalEnd: this._onTraversalEnd.bind(this)
2373
+ });
2374
+ }
2375
+ _destroyTileHeaders(parentTile) {
2376
+ this._destroySubtree(parentTile);
2377
+ }
2378
+ async _loadTile(tile) {
2379
+ let loaded;
2380
+ try {
2381
+ this._onStartTileLoading();
2382
+ loaded = await tile.loadContent();
2383
+ } catch (error) {
2384
+ this._onTileLoadError(tile, error instanceof Error ? error : new Error("load failed"));
2385
+ } finally {
2386
+ this._onEndTileLoading();
2387
+ this._onTileLoad(tile, loaded);
2388
+ }
2389
+ }
2390
+ _onTileLoadError(tile, error) {
2391
+ this.stats.get(TILES_LOAD_FAILED).incrementCount();
2392
+ const message = error.message || error.toString();
2393
+ const url = tile.url;
2394
+ console.error(`A 3D tile failed to load: ${tile.url} ${message}`);
2395
+ this.options.onTileError(tile, message, url);
2396
+ }
2397
+ _onTileLoad(tile, loaded) {
2398
+ var _a, _b;
2399
+ if (!loaded) {
2400
+ return;
2401
+ }
2402
+ if (this.type === "I3S" /* I3S */) {
2403
+ const nodesInNodePages = ((_b = (_a = this.tileset) == null ? void 0 : _a.nodePagesTile) == null ? void 0 : _b.nodesInNodePages) || 0;
2404
+ this.stats.get(TILES_TOTAL).reset();
2405
+ this.stats.get(TILES_TOTAL).addCount(nodesInNodePages);
2406
+ }
2407
+ if (tile && tile.content) {
2408
+ calculateTransformProps(tile, tile.content);
2409
+ }
2410
+ this.updateContentTypes(tile);
2411
+ this._addTileToCache(tile);
2412
+ this.options.onTileLoad(tile);
2413
+ }
2414
+ /**
2415
+ * Update information about data types in nested tiles
2416
+ * @param tile instance of a nested Tile3D
2417
+ */
2418
+ updateContentTypes(tile) {
2419
+ var _a;
2420
+ if (this.type === "I3S" /* I3S */) {
2421
+ if (tile.header.isDracoGeometry) {
2422
+ this.contentFormats.draco = true;
2423
+ }
2424
+ switch (tile.header.textureFormat) {
2425
+ case "dds":
2426
+ this.contentFormats.dds = true;
2427
+ break;
2428
+ case "ktx2":
2429
+ this.contentFormats.ktx2 = true;
2430
+ break;
2431
+ default:
2432
+ }
2433
+ } else if (this.type === "TILES3D" /* TILES3D */) {
2434
+ const { extensionsRemoved = [] } = ((_a = tile.content) == null ? void 0 : _a.gltf) || {};
2435
+ if (extensionsRemoved.includes("KHR_draco_mesh_compression")) {
2436
+ this.contentFormats.draco = true;
2437
+ }
2438
+ if (extensionsRemoved.includes("EXT_meshopt_compression")) {
2439
+ this.contentFormats.meshopt = true;
2440
+ }
2441
+ if (extensionsRemoved.includes("KHR_texture_basisu")) {
2442
+ this.contentFormats.ktx2 = true;
2443
+ }
2444
+ }
2445
+ }
2446
+ _onStartTileLoading() {
2447
+ this._pendingCount++;
2448
+ this.stats.get(TILES_LOADING).incrementCount();
2449
+ }
2450
+ _onEndTileLoading() {
2451
+ this._pendingCount--;
2452
+ this.stats.get(TILES_LOADING).decrementCount();
2453
+ }
2454
+ _addTileToCache(tile) {
2455
+ this._cache.add(this, tile, (tileset) => tileset._updateCacheStats(tile));
2456
+ }
2457
+ _updateCacheStats(tile) {
2458
+ this.stats.get(TILES_LOADED).incrementCount();
2459
+ this.stats.get(TILES_IN_MEMORY).incrementCount();
2460
+ this.gpuMemoryUsageInBytes += tile.gpuMemoryUsageInBytes || 0;
2461
+ this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
2462
+ }
2463
+ _unloadTile(tile) {
2464
+ this.gpuMemoryUsageInBytes -= tile.gpuMemoryUsageInBytes || 0;
2465
+ this.stats.get(TILES_IN_MEMORY).decrementCount();
2466
+ this.stats.get(TILES_UNLOADED).incrementCount();
2467
+ this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
2468
+ this.options.onTileUnload(tile);
2469
+ tile.unloadContent();
2470
+ }
2471
+ // Traverse the tree and destroy all tiles
2472
+ _destroy() {
2473
+ const stack = [];
2474
+ if (this.root) {
2475
+ stack.push(this.root);
2476
+ }
2477
+ while (stack.length > 0) {
2478
+ const tile = stack.pop();
2479
+ for (const child of tile.children) {
2480
+ stack.push(child);
2481
+ }
2482
+ this._destroyTile(tile);
2483
+ }
2484
+ this.root = null;
2485
+ }
2486
+ // Traverse the tree and destroy all sub tiles
2487
+ _destroySubtree(tile) {
2488
+ const root = tile;
2489
+ const stack = [];
2490
+ stack.push(root);
2491
+ while (stack.length > 0) {
2492
+ tile = stack.pop();
2493
+ for (const child of tile.children) {
2494
+ stack.push(child);
2495
+ }
2496
+ if (tile !== root) {
2497
+ this._destroyTile(tile);
2498
+ }
2499
+ }
2500
+ root.children = [];
2501
+ }
2502
+ _destroyTile(tile) {
2503
+ this._cache.unloadTile(this, tile);
2504
+ this._unloadTile(tile);
2505
+ tile.destroy();
2506
+ }
2507
+ _initializeTiles3DTileset(tilesetJson) {
2508
+ if (tilesetJson.queryString) {
2509
+ const searchParams = new URLSearchParams(tilesetJson.queryString);
2510
+ const queryParams = Object.fromEntries(searchParams.entries());
2511
+ this._queryParams = { ...this._queryParams, ...queryParams };
2512
+ }
2513
+ this.asset = tilesetJson.asset;
2514
+ if (!this.asset) {
2515
+ throw new Error("Tileset must have an asset property.");
2516
+ }
2517
+ if (this.asset.version !== "0.0" && this.asset.version !== "1.0" && this.asset.version !== "1.1") {
2518
+ throw new Error("The tileset must be 3D Tiles version either 0.0 or 1.0 or 1.1.");
2519
+ }
2520
+ if ("tilesetVersion" in this.asset) {
2521
+ this._queryParams.v = this.asset.tilesetVersion;
2522
+ }
2523
+ this.credits = {
2524
+ attributions: this.options.attributions || []
2525
+ };
2526
+ this.description = this.options.description || "";
2527
+ this.properties = tilesetJson.properties;
2528
+ this.geometricError = tilesetJson.geometricError;
2529
+ this._extensionsUsed = tilesetJson.extensionsUsed || [];
2530
+ this.extras = tilesetJson.extras;
2531
+ }
2532
+ _initializeI3STileset() {
2533
+ if (this.loadOptions.i3s && "token" in this.loadOptions.i3s) {
2534
+ this._queryParams.token = this.loadOptions.i3s.token;
2535
+ }
2536
+ }
2537
+ };