@loaders.gl/tiles 5.0.0-alpha.10 → 5.0.0-alpha.12

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 (80) hide show
  1. package/dist/dist.dev.js +37183 -19131
  2. package/dist/dist.min.js +22 -3
  3. package/dist/index.cjs +620 -2027
  4. package/dist/index.cjs.map +4 -3
  5. package/dist/index.d.ts +3 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/point-cloud-tile-source-loader-types.d.ts +31 -0
  10. package/dist/point-cloud-tile-source-loader-types.d.ts.map +1 -0
  11. package/dist/point-cloud-tile-source-loader-types.js +34 -0
  12. package/dist/point-cloud-tile-source-loader-types.js.map +1 -0
  13. package/dist/point-cloud-tile-source-loader.cjs +81 -0
  14. package/dist/point-cloud-tile-source-loader.cjs.map +7 -0
  15. package/dist/point-cloud-tile-source-loader.d.ts +27 -0
  16. package/dist/point-cloud-tile-source-loader.d.ts.map +1 -0
  17. package/dist/point-cloud-tile-source-loader.js +17 -0
  18. package/dist/point-cloud-tile-source-loader.js.map +1 -0
  19. package/dist/point-cloud-tile-source-types.d.ts +15 -0
  20. package/dist/point-cloud-tile-source-types.d.ts.map +1 -0
  21. package/dist/point-cloud-tile-source-types.js +5 -0
  22. package/dist/point-cloud-tile-source-types.js.map +1 -0
  23. package/dist/point-cloud-tile-source.cjs +105 -0
  24. package/dist/point-cloud-tile-source.cjs.map +7 -0
  25. package/dist/point-cloud-tile-source.d.ts +36 -0
  26. package/dist/point-cloud-tile-source.d.ts.map +1 -0
  27. package/dist/point-cloud-tile-source.js +84 -0
  28. package/dist/point-cloud-tile-source.js.map +1 -0
  29. package/dist/spatial/i3s-spatial-transformer.d.ts +16 -0
  30. package/dist/spatial/i3s-spatial-transformer.d.ts.map +1 -1
  31. package/dist/spatial/i3s-spatial-transformer.js +45 -0
  32. package/dist/spatial/i3s-spatial-transformer.js.map +1 -1
  33. package/dist/spatial/spatial-coordinate-transformer.d.ts +3 -1
  34. package/dist/spatial/spatial-coordinate-transformer.d.ts.map +1 -1
  35. package/dist/spatial/spatial-coordinate-transformer.js +25 -9
  36. package/dist/spatial/spatial-coordinate-transformer.js.map +1 -1
  37. package/dist/spatial/spatial-resource-registry.d.ts +3 -0
  38. package/dist/spatial/spatial-resource-registry.d.ts.map +1 -1
  39. package/dist/spatial/spatial-resource-registry.js +12 -3
  40. package/dist/spatial/spatial-resource-registry.js.map +1 -1
  41. package/dist/spatial/tiles-3d-spatial-transformer.d.ts.map +1 -1
  42. package/dist/spatial/tiles-3d-spatial-transformer.js +0 -12
  43. package/dist/spatial/tiles-3d-spatial-transformer.js.map +1 -1
  44. package/dist/tileset-2d.d.ts +2 -1
  45. package/dist/tileset-2d.d.ts.map +1 -1
  46. package/dist/tileset-2d.js +1 -1
  47. package/dist/tileset-2d.js.map +1 -1
  48. package/dist/tileset-3d/common/tileset-3d.d.ts +10 -1
  49. package/dist/tileset-3d/common/tileset-3d.d.ts.map +1 -1
  50. package/dist/tileset-3d/common/tileset-3d.js +42 -9
  51. package/dist/tileset-3d/common/tileset-3d.js.map +1 -1
  52. package/dist/tileset-3d/common/tileset-traverser.d.ts.map +1 -1
  53. package/dist/tileset-3d/common/tileset-traverser.js +2 -3
  54. package/dist/tileset-3d/common/tileset-traverser.js.map +1 -1
  55. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts.map +1 -1
  56. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js +0 -3
  57. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js.map +1 -1
  58. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts +1 -0
  59. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts.map +1 -1
  60. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js +12 -4
  61. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js.map +1 -1
  62. package/dist/tileset-3d/helpers/s2-bounding-volume.d.ts.map +1 -1
  63. package/dist/tileset-3d/helpers/s2-bounding-volume.js +0 -3
  64. package/dist/tileset-3d/helpers/s2-bounding-volume.js.map +1 -1
  65. package/package.json +25 -13
  66. package/src/index.ts +8 -1
  67. package/src/point-cloud-tile-source-loader-types.ts +53 -0
  68. package/src/point-cloud-tile-source-loader.ts +32 -0
  69. package/src/point-cloud-tile-source-types.ts +20 -0
  70. package/src/point-cloud-tile-source.ts +112 -0
  71. package/src/spatial/i3s-spatial-transformer.ts +64 -0
  72. package/src/spatial/spatial-coordinate-transformer.ts +30 -9
  73. package/src/spatial/spatial-resource-registry.ts +14 -3
  74. package/src/spatial/tiles-3d-spatial-transformer.ts +0 -12
  75. package/src/tileset-2d.ts +25 -1
  76. package/src/tileset-3d/common/tileset-3d.ts +56 -12
  77. package/src/tileset-3d/common/tileset-traverser.ts +2 -4
  78. package/src/tileset-3d/format-3d-tiles/implicit-tiling.ts +0 -3
  79. package/src/tileset-3d/format-3d-tiles/tileset-3d-traverser.ts +16 -4
  80. package/src/tileset-3d/helpers/s2-bounding-volume.ts +0 -3
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // dist/index.js
@@ -26,6 +36,7 @@ __export(index_exports, {
26
36
  IndexedArchiveTilesetSource: () => IndexedArchiveTilesetSource,
27
37
  LOD_METRIC_TYPE: () => LOD_METRIC_TYPE,
28
38
  PointCloudTile: () => PointCloudTile,
39
+ PointCloudTileSourceLoader: () => PointCloudTileSourceLoader,
29
40
  PointCloudTileset: () => PointCloudTileset,
30
41
  RasterSet: () => RasterSet,
31
42
  STRATEGY_DEFAULT: () => STRATEGY_DEFAULT,
@@ -72,1701 +83,202 @@ module.exports = __toCommonJS(index_exports);
72
83
  // dist/tileset-3d/common/tileset-3d.js
73
84
  var import_core5 = require("@math.gl/core");
74
85
  var import_geospatial3 = require("@math.gl/geospatial");
75
- var import_stats3 = require("@probe.gl/stats");
76
86
 
77
- // ../loader-utils/src/lib/env-utils/assert.ts
78
- function assert(condition, message) {
79
- if (!condition) {
80
- throw new Error(message || "loader assertion failed.");
87
+ // ../../node_modules/@probe.gl/stats/dist/utils/hi-res-timestamp.js
88
+ function getHiResTimestamp() {
89
+ let timestamp;
90
+ if (typeof window !== "undefined" && window.performance) {
91
+ timestamp = window.performance.now();
92
+ } else if (typeof process !== "undefined" && process.hrtime) {
93
+ const timeParts = process.hrtime();
94
+ timestamp = timeParts[0] * 1e3 + timeParts[1] / 1e6;
95
+ } else {
96
+ timestamp = Date.now();
81
97
  }
98
+ return timestamp;
82
99
  }
83
100
 
84
- // ../loader-utils/src/lib/binary-utils/array-buffer-utils.ts
85
- function sliceArrayBuffer(arrayBuffer, byteOffset, byteLength) {
86
- const subArray = byteLength !== void 0 ? new Uint8Array(arrayBuffer).subarray(byteOffset, byteOffset + byteLength) : new Uint8Array(arrayBuffer).subarray(byteOffset);
87
- const arrayCopy = new Uint8Array(subArray);
88
- return arrayCopy.buffer;
89
- }
90
-
91
- // ../loader-utils/src/lib/request-utils/request-scheduler.ts
92
- var import_stats = require("@probe.gl/stats");
93
- var STAT_QUEUED_REQUESTS = "Queued Requests";
94
- var STAT_ACTIVE_REQUESTS = "Active Requests";
95
- var STAT_CANCELLED_REQUESTS = "Cancelled Requests";
96
- var STAT_QUEUED_REQUESTS_EVER = "Queued Requests Ever";
97
- var STAT_ACTIVE_REQUESTS_EVER = "Active Requests Ever";
98
- var DEFAULT_PROPS = {
99
- id: "request-scheduler",
100
- /** Specifies if the request scheduler should throttle incoming requests, mainly for comparative testing. */
101
- throttleRequests: true,
102
- /** The maximum number of simultaneous active requests. Un-throttled requests do not observe this limit. */
103
- maxRequests: 6,
104
- /**
105
- * Specifies a debounce time, in milliseconds. All requests are queued, until no new requests have
106
- * been added to the queue for this amount of time.
107
- */
108
- debounceTime: 0
109
- };
110
- var RequestScheduler = class {
111
- props;
112
- stats;
113
- activeRequestCount = 0;
114
- /** Tracks the number of active requests and prioritizes/cancels queued requests. */
115
- requestQueue = [];
116
- requestMap = /* @__PURE__ */ new Map();
117
- /** Pending arrival debounce or next-tick refill; only new arrivals replace this timer. */
118
- updateTimer = null;
119
- constructor(props = {}) {
120
- this.props = { ...DEFAULT_PROPS, ...props };
121
- this.stats = new import_stats.Stats({ id: this.props.id });
122
- this.stats.get(STAT_QUEUED_REQUESTS);
123
- this.stats.get(STAT_ACTIVE_REQUESTS);
124
- this.stats.get(STAT_CANCELLED_REQUESTS);
125
- this.stats.get(STAT_QUEUED_REQUESTS_EVER);
126
- this.stats.get(STAT_ACTIVE_REQUESTS_EVER);
127
- }
128
- /**
129
- * Update scheduler props. Preserves active and queued requests.
130
- */
131
- setProps(props) {
132
- if (props.throttleRequests !== void 0) {
133
- this.props.throttleRequests = props.throttleRequests;
134
- }
135
- if (props.maxRequests !== void 0) {
136
- this.props.maxRequests = props.maxRequests;
137
- }
138
- if (props.debounceTime !== void 0) {
139
- this.props.debounceTime = props.debounceTime;
140
- }
141
- }
142
- /**
143
- * Called by an application that wants to issue a request, without having it deeply queued by the browser
144
- *
145
- * When the returned promise resolved, it is OK for the application to issue a request.
146
- * The promise resolves to an object that contains a `done` method.
147
- * When the application's request has completed (or failed), the application must call the `done` function
148
- *
149
- * @param handle
150
- * @param getPriority will be called when request "slots" open up,
151
- * allowing the caller to update priority or cancel the request
152
- * Highest priority executes first, priority < 0 cancels the request
153
- * @returns a promise
154
- * - resolves to a object (with a `done` field) when the request can be issued without queueing,
155
- * - resolves to `null` if the request has been cancelled (by the callback return < 0).
156
- * In this case the application should not issue the request
157
- */
158
- scheduleRequest(handle, getPriority = () => 0) {
159
- if (!this.props.throttleRequests) {
160
- return Promise.resolve({ done: () => {
161
- } });
162
- }
163
- if (this.requestMap.has(handle)) {
164
- return this.requestMap.get(handle);
165
- }
166
- const request = { handle, priority: 0, getPriority };
167
- const promise = new Promise((resolve2) => {
168
- request.resolve = resolve2;
169
- return request;
170
- });
171
- this.requestQueue.push(request);
172
- this.requestMap.set(handle, promise);
173
- this._issueNewRequests();
174
- return promise;
175
- }
176
- // PRIVATE
177
- _issueRequest(request) {
178
- const { handle, resolve: resolve2 } = request;
179
- let isDone = false;
180
- const done = () => {
181
- if (!isDone) {
182
- isDone = true;
183
- this.requestMap.delete(handle);
184
- this.activeRequestCount--;
185
- this.scheduleRefill();
186
- }
187
- };
188
- this.activeRequestCount++;
189
- return resolve2 ? resolve2({ done }) : Promise.resolve({ done });
190
- }
191
- /** Refills freed slots on the next tick while preserving any pending arrival debounce. */
192
- scheduleRefill() {
193
- if (this.updateTimer !== null) {
194
- return;
195
- }
196
- this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), 0);
101
+ // ../../node_modules/@probe.gl/stats/dist/lib/stat.js
102
+ var Stat = class {
103
+ constructor(name, type) {
104
+ this.sampleSize = 1;
105
+ this.time = 0;
106
+ this.count = 0;
107
+ this.samples = 0;
108
+ this.lastTiming = 0;
109
+ this.lastSampleTime = 0;
110
+ this.lastSampleCount = 0;
111
+ this._count = 0;
112
+ this._time = 0;
113
+ this._samples = 0;
114
+ this._startTime = 0;
115
+ this._timerPending = false;
116
+ this.name = name;
117
+ this.type = type;
118
+ this.reset();
197
119
  }
198
- /** Restarts the quiet period when a new request enters the queue. */
199
- _issueNewRequests() {
200
- if (this.updateTimer !== null) {
201
- clearTimeout(this.updateTimer);
202
- }
203
- this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), this.props.debounceTime);
120
+ reset() {
121
+ this.time = 0;
122
+ this.count = 0;
123
+ this.samples = 0;
124
+ this.lastTiming = 0;
125
+ this.lastSampleTime = 0;
126
+ this.lastSampleCount = 0;
127
+ this._count = 0;
128
+ this._time = 0;
129
+ this._samples = 0;
130
+ this._startTime = 0;
131
+ this._timerPending = false;
132
+ return this;
204
133
  }
205
- /** Clears timer ownership before updating priorities and dispatching queued requests. */
206
- _issueNewRequestsAsync() {
207
- if (this.updateTimer !== null) {
208
- clearTimeout(this.updateTimer);
209
- }
210
- this.updateTimer = null;
211
- const freeSlots = Math.max(this.props.maxRequests - this.activeRequestCount, 0);
212
- if (freeSlots === 0) {
213
- return;
214
- }
215
- this._updateAllRequests();
216
- for (let i = 0; i < freeSlots; ++i) {
217
- const request = this.requestQueue.shift();
218
- if (request) {
219
- this._issueRequest(request);
220
- }
221
- }
134
+ setSampleSize(samples) {
135
+ this.sampleSize = samples;
136
+ return this;
222
137
  }
223
- /** Ensure all requests have updated priorities, and that no longer valid requests are cancelled */
224
- _updateAllRequests() {
225
- const requestQueue = this.requestQueue;
226
- for (let i = 0; i < requestQueue.length; ++i) {
227
- const request = requestQueue[i];
228
- if (!this._updateRequest(request)) {
229
- requestQueue.splice(i, 1);
230
- this.requestMap.delete(request.handle);
231
- i--;
232
- }
233
- }
234
- requestQueue.sort((a, b) => a.priority - b.priority);
138
+ /** Call to increment count (+1) */
139
+ incrementCount() {
140
+ this.addCount(1);
141
+ return this;
235
142
  }
236
- /** Update a single request by calling the callback */
237
- _updateRequest(request) {
238
- request.priority = request.getPriority(request.handle);
239
- if (request.priority < 0) {
240
- request.resolve(null);
241
- return false;
242
- }
243
- return true;
143
+ /** Call to decrement count (-1) */
144
+ decrementCount() {
145
+ this.subtractCount(1);
146
+ return this;
244
147
  }
245
- };
246
-
247
- // ../loader-utils/src/lib/request-utils/request-cache.ts
248
- var DEFAULT_MAX_ENTRIES = Number.POSITIVE_INFINITY;
249
- var DEFAULT_MAX_BYTES = Number.POSITIVE_INFINITY;
250
- var RequestCache = class {
251
- /** Maximum number of settled entries retained by this cache. */
252
- maxEntries;
253
- /** Maximum estimated bytes retained by this cache. */
254
- maxBytes;
255
- getByteLength;
256
- onRemove;
257
- entries = /* @__PURE__ */ new Map();
258
- retainedByteLength = 0;
259
- /** Creates a request cache with optional entry and byte limits. */
260
- constructor(props = {}) {
261
- this.maxEntries = validateLimit(props.maxEntries, DEFAULT_MAX_ENTRIES, "maxEntries");
262
- this.maxBytes = validateLimit(props.maxBytes, DEFAULT_MAX_BYTES, "maxBytes");
263
- this.getByteLength = props.getByteLength || (() => 0);
264
- this.onRemove = props.onRemove;
265
- }
266
- /** Number of pending and settled entries currently tracked. */
267
- get size() {
268
- return this.entries.size;
148
+ /** Increase count */
149
+ addCount(value) {
150
+ this._count += value;
151
+ this._samples++;
152
+ this._checkSampling();
153
+ return this;
269
154
  }
270
- /** Number of requests that have not settled. */
271
- get pendingSize() {
272
- let pendingSize = 0;
273
- for (const entry of this.entries.values()) {
274
- pendingSize += entry.pending ? 1 : 0;
275
- }
276
- return pendingSize;
155
+ /** Decrease count */
156
+ subtractCount(value) {
157
+ this._count -= value;
158
+ this._samples++;
159
+ this._checkSampling();
160
+ return this;
277
161
  }
278
- /** Estimated bytes retained by settled entries. */
279
- get byteLength() {
280
- return this.retainedByteLength;
162
+ /** Add an arbitrary timing and bump the count */
163
+ addTime(time) {
164
+ this._time += time;
165
+ this.lastTiming = time;
166
+ this._samples++;
167
+ this._checkSampling();
168
+ return this;
281
169
  }
282
- /** Returns a cached request and updates its LRU position. */
283
- get(key, signal) {
284
- const entry = this.entries.get(key);
285
- if (!entry) {
286
- return void 0;
287
- }
288
- this.touch(key, entry);
289
- return this.waitForEntry(key, entry, signal);
290
- }
291
- /** Returns whether a pending or settled entry exists without updating its LRU position. */
292
- has(key) {
293
- return this.entries.has(key);
294
- }
295
- /** Stores an already available value and returns it. */
296
- set(key, value) {
297
- this.removeEntry(key, "replace");
298
- const byteLength = getValidByteLength(this.getByteLength(value));
299
- const entry = {
300
- promise: Promise.resolve(value),
301
- pending: false,
302
- waiterCount: 0,
303
- byteLength
304
- };
305
- this.entries.set(key, entry);
306
- this.retainedByteLength += byteLength;
307
- this.trim();
308
- return value;
170
+ /** Start a timer */
171
+ timeStart() {
172
+ this._startTime = getHiResTimestamp();
173
+ this._timerPending = true;
174
+ return this;
309
175
  }
310
- /**
311
- * Returns a cached value or starts one shared request.
312
- *
313
- * The loader receives a cache-owned abort signal. One caller aborting only rejects that caller;
314
- * the shared request is cancelled when no waiters remain.
315
- */
316
- getOrLoad(key, load, signal) {
317
- const cached = this.get(key, signal);
318
- if (cached) {
319
- return cached;
320
- }
321
- if (signal == null ? void 0 : signal.aborted) {
322
- return Promise.reject(createAbortError());
323
- }
324
- const controller = new AbortController();
325
- let resolveRequest;
326
- let rejectRequest;
327
- const promise = new Promise((resolve2, reject) => {
328
- resolveRequest = resolve2;
329
- rejectRequest = reject;
330
- });
331
- const entry = {
332
- promise,
333
- controller,
334
- pending: true,
335
- waiterCount: 0,
336
- byteLength: 0
337
- };
338
- this.entries.set(key, entry);
339
- void entry.promise.then(
340
- (value) => this.handleLoadedValue(key, entry, value),
341
- () => this.handleLoadError(key, entry)
342
- );
343
- try {
344
- void Promise.resolve(load(controller.signal)).then(resolveRequest, rejectRequest);
345
- } catch (error) {
346
- rejectRequest(error);
176
+ /** End a timer. Adds to time and bumps the timing count. */
177
+ timeEnd() {
178
+ if (!this._timerPending) {
179
+ return this;
347
180
  }
348
- return this.waitForEntry(key, entry, signal);
181
+ this.addTime(getHiResTimestamp() - this._startTime);
182
+ this._timerPending = false;
183
+ this._checkSampling();
184
+ return this;
349
185
  }
350
- /** Removes one cached or pending request. */
351
- delete(key) {
352
- return this.removeEntry(key, "delete");
186
+ getSampleAverageCount() {
187
+ return this.sampleSize > 0 ? this.lastSampleCount / this.sampleSize : 0;
353
188
  }
354
- /** Aborts pending requests and removes every entry. */
355
- clear() {
356
- for (const key of Array.from(this.entries.keys())) {
357
- this.removeEntry(key, "clear");
358
- }
189
+ /** Calculate average time / count for the previous window */
190
+ getSampleAverageTime() {
191
+ return this.sampleSize > 0 ? this.lastSampleTime / this.sampleSize : 0;
359
192
  }
360
- handleLoadedValue(key, entry, value) {
361
- if (this.entries.get(key) !== entry) {
362
- return;
363
- }
364
- entry.pending = false;
365
- entry.controller = void 0;
366
- try {
367
- entry.byteLength = getValidByteLength(this.getByteLength(value));
368
- } catch {
369
- this.removeEntry(key, "error");
370
- return;
371
- }
372
- this.retainedByteLength += entry.byteLength;
373
- this.trim();
193
+ /** Calculate counts per second for the previous window */
194
+ getSampleHz() {
195
+ return this.lastSampleTime > 0 ? this.sampleSize / (this.lastSampleTime / 1e3) : 0;
374
196
  }
375
- handleLoadError(key, entry) {
376
- var _a;
377
- if (this.entries.get(key) === entry) {
378
- this.removeEntry(key, ((_a = entry.controller) == null ? void 0 : _a.signal.aborted) ? "abort" : "error");
379
- }
197
+ getAverageCount() {
198
+ return this.samples > 0 ? this.count / this.samples : 0;
380
199
  }
381
- waitForEntry(key, entry, signal) {
382
- if (signal == null ? void 0 : signal.aborted) {
383
- return Promise.reject(createAbortError());
384
- }
385
- if (!entry.pending) {
386
- return entry.promise;
387
- }
388
- entry.waiterCount++;
389
- return new Promise((resolve2, reject) => {
390
- let waiting = true;
391
- const finishWaiting = () => {
392
- if (!waiting) return;
393
- waiting = false;
394
- signal == null ? void 0 : signal.removeEventListener("abort", handleAbort);
395
- entry.waiterCount--;
396
- };
397
- const handleAbort = () => {
398
- if (!waiting) return;
399
- finishWaiting();
400
- reject(createAbortError());
401
- if (entry.pending && entry.waiterCount === 0 && this.entries.get(key) === entry) {
402
- this.removeEntry(key, "abort");
403
- }
404
- };
405
- signal == null ? void 0 : signal.addEventListener("abort", handleAbort, { once: true });
406
- void entry.promise.then(
407
- (value) => {
408
- if (!waiting) return;
409
- finishWaiting();
410
- resolve2(value);
411
- },
412
- (error) => {
413
- if (!waiting) return;
414
- finishWaiting();
415
- reject(error);
416
- }
417
- );
418
- });
200
+ /** Calculate average time / count */
201
+ getAverageTime() {
202
+ return this.samples > 0 ? this.time / this.samples : 0;
419
203
  }
420
- touch(key, entry) {
421
- this.entries.delete(key);
422
- this.entries.set(key, entry);
204
+ /** Calculate counts per second */
205
+ getHz() {
206
+ return this.time > 0 ? this.samples / (this.time / 1e3) : 0;
423
207
  }
424
- trim() {
425
- let settledEntryCount = this.entries.size - this.pendingSize;
426
- if (settledEntryCount <= this.maxEntries && this.retainedByteLength <= this.maxBytes) {
427
- return;
428
- }
429
- for (const [key, entry] of this.entries) {
430
- if (!entry.pending) {
431
- this.removeEntry(key, "evict");
432
- settledEntryCount--;
433
- }
434
- if (settledEntryCount <= this.maxEntries && this.retainedByteLength <= this.maxBytes) {
435
- break;
436
- }
208
+ _checkSampling() {
209
+ if (this._samples === this.sampleSize) {
210
+ this.lastSampleTime = this._time;
211
+ this.lastSampleCount = this._count;
212
+ this.count += this._count;
213
+ this.time += this._time;
214
+ this.samples += this._samples;
215
+ this._time = 0;
216
+ this._count = 0;
217
+ this._samples = 0;
437
218
  }
438
219
  }
439
- removeEntry(key, reason) {
440
- var _a, _b;
441
- const entry = this.entries.get(key);
442
- if (!entry) {
443
- return false;
444
- }
445
- this.entries.delete(key);
446
- this.retainedByteLength -= entry.byteLength;
447
- if (entry.pending) {
448
- (_a = entry.controller) == null ? void 0 : _a.abort();
449
- }
450
- (_b = this.onRemove) == null ? void 0 : _b.call(this, key, reason);
451
- return true;
452
- }
453
220
  };
454
- function createAbortError() {
455
- const error = new Error("Request aborted");
456
- error.name = "AbortError";
457
- return error;
458
- }
459
- function validateLimit(value, fallback, name) {
460
- const limit = value ?? fallback;
461
- if (limit < 0 || Number.isNaN(limit)) {
462
- throw new Error(`${name} must be a non-negative number`);
463
- }
464
- return limit;
465
- }
466
- function getValidByteLength(value) {
467
- if (!Number.isFinite(value) || value < 0) {
468
- throw new Error("Request cache entry byte length must be a non-negative finite number");
469
- }
470
- return value;
471
- }
472
221
 
473
- // ../loader-utils/src/lib/request-utils/range-request-scheduler.ts
474
- var import_stats2 = require("@probe.gl/stats");
475
- var RANGE_STATS_KEYS = {
476
- logicalRanges: "Logical Range Requests",
477
- rangeBatches: "Range Request Batches",
478
- transportRanges: "Transport Ranges Created",
479
- completedTransportRanges: "Range Transport Requests Completed",
480
- coalescedRanges: "Coalesced Logical Ranges",
481
- requestedBytes: "Logical Range Request Bytes",
482
- transportBytes: "Range Transport Bytes Requested",
483
- responseBytes: "Range Response Bytes",
484
- networkTimeMs: "Range Network Time",
485
- overfetchBytes: "Range Overfetch Bytes",
486
- failedTransportRanges: "Range Transport Requests Failed",
487
- abortedLogicalRanges: "Aborted Logical Range Requests",
488
- fullResponseFallbacks: "Full Response Fallbacks"
489
- };
490
- var DEFAULT_PROPS2 = {
491
- batchDelayMs: 50,
492
- maxGapBytes: 65536,
493
- rangeExpansionBytes: 65536,
494
- maxMergedBytes: 8388608,
495
- maxConcurrency: 6,
496
- maxQueueSize: 4096,
497
- maxRangeBytes: 64 * 1024 * 1024,
498
- stats: createRangeStats("range-request-scheduler-default"),
499
- onEvent: () => {
500
- }
501
- };
502
- var RangeRequestScheduler = class {
503
- /** Runtime scheduler configuration with defaults filled in. */
504
- props;
505
- /** Runtime counters for range batching and transport behavior. */
506
- stats;
507
- /** Optional event callback for range batching diagnostics. */
508
- onEvent;
509
- pendingRequests = [];
510
- /** Merged transports waiting for a concurrency slot. */
511
- transportQueue = [];
512
- /** Number of active transports. */
513
- activeTransports = 0;
514
- /** Number of unsettled logical requests. */
515
- queuedRequests = 0;
516
- /** Unsettled requests retained until completion or disposal. */
517
- logicalRequests = /* @__PURE__ */ new Set();
518
- /** Controllers for transports owned by this scheduler. */
519
- transportControllers = /* @__PURE__ */ new Set();
520
- /** Disposal prevents further enqueueing. */
521
- finalized = false;
522
- /** Pending batch window, independent of in-flight transport requests. */
523
- flushTimer = null;
524
- /** Creates a scheduler for one group of byte-range-addressable resources. */
525
- constructor(props = {}) {
526
- const rangeExpansionBytes = props.rangeExpansionBytes ?? props.maxGapBytes ?? DEFAULT_PROPS2.rangeExpansionBytes;
527
- this.props = {
528
- batchDelayMs: props.batchDelayMs ?? DEFAULT_PROPS2.batchDelayMs,
529
- maxGapBytes: props.maxGapBytes ?? rangeExpansionBytes,
530
- rangeExpansionBytes,
531
- maxMergedBytes: props.maxMergedBytes ?? DEFAULT_PROPS2.maxMergedBytes,
532
- maxConcurrency: props.maxConcurrency ?? 6,
533
- maxQueueSize: props.maxQueueSize ?? 4096,
534
- maxRangeBytes: props.maxRangeBytes ?? 64 * 1024 * 1024
535
- };
536
- for (const value of [
537
- this.props.maxConcurrency,
538
- this.props.maxQueueSize,
539
- this.props.maxRangeBytes
540
- ]) {
541
- if (!Number.isSafeInteger(value) || value <= 0)
542
- throw new Error("Range scheduler limits must be positive integers");
543
- }
544
- this.stats = props.stats || createRangeStats("range-request-scheduler");
545
- this.onEvent = props.onEvent;
546
- initializeStats(this.stats);
547
- }
548
- /**
549
- * Enqueues one byte range request and resolves with the exact requested byte slice.
550
- */
551
- scheduleRequest(request) {
552
- var _a;
553
- if (this.finalized) return Promise.reject(new Error("Range scheduler is finalized"));
554
- if (!Number.isSafeInteger(request.offset) || request.offset < 0 || !Number.isSafeInteger(request.length) || request.length > this.props.maxRangeBytes || !Number.isSafeInteger(request.offset + request.length))
555
- return Promise.reject(new Error("Invalid or oversized byte range"));
556
- if (this.queuedRequests >= this.props.maxQueueSize)
557
- return Promise.reject(new Error("Range scheduler queue limit exceeded"));
558
- if (request.length < 0) {
559
- return Promise.reject(new Error("Byte range length cannot be negative"));
560
- }
561
- if ((_a = request.signal) == null ? void 0 : _a.aborted) {
562
- return Promise.reject(request.signal.reason ?? createAbortError2());
563
- }
564
- if (request.length === 0) {
565
- return Promise.resolve(new ArrayBuffer(0));
566
- }
567
- this.queuedRequests++;
568
- let pendingRequest;
569
- const promise = new Promise((resolve2, reject) => {
570
- pendingRequest = { ...request, resolve: resolve2, reject, settled: false };
571
- this.logicalRequests.add(pendingRequest);
572
- if (request.signal) {
573
- pendingRequest.abortListener = () => {
574
- var _a2;
575
- this.abortRequest(pendingRequest);
576
- (_a2 = pendingRequest.onAbort) == null ? void 0 : _a2.call(pendingRequest);
577
- };
578
- request.signal.addEventListener("abort", pendingRequest.abortListener, { once: true });
579
- }
580
- this.pendingRequests.push(pendingRequest);
581
- });
582
- this.trackEvent({
583
- type: "queued",
584
- sourceId: request.sourceId,
585
- offset: request.offset,
586
- length: request.length,
587
- logicalRequestCount: 1,
588
- logicalBytes: request.length
589
- });
590
- this.scheduleFlush();
591
- return promise.finally(() => {
592
- var _a2;
593
- if (pendingRequest.abortListener)
594
- (_a2 = request.signal) == null ? void 0 : _a2.removeEventListener("abort", pendingRequest.abortListener);
595
- this.queuedRequests--;
596
- this.logicalRequests.delete(pendingRequest);
597
- });
598
- }
599
- /**
600
- * Enqueues one HTTP byte-range request and resolves with the exact requested byte slice.
601
- */
602
- fetch(request) {
603
- const fetchFunction = request.fetch || globalThis.fetch;
604
- return this.scheduleRequest({
605
- sourceId: request.sourceId || request.url,
606
- offset: request.offset,
607
- length: request.length,
608
- signal: request.signal,
609
- // Different fetch calls may carry different credentials or transport implementations.
610
- // Sharing is therefore opt-in through an explicit common isolation key.
611
- isolationKey: request.isolationKey ?? {},
612
- fetchRange: (offset, length, signal) => fetchHttpRange({
613
- url: request.url,
614
- offset,
615
- length,
616
- signal,
617
- fetch: fetchFunction,
618
- fetchOptions: request.fetchOptions
619
- })
620
- });
621
- }
622
- /** Immediately starts loading the currently queued requests. */
623
- flush() {
624
- if (this.flushTimer !== null) {
625
- clearTimeout(this.flushTimer);
626
- this.flushTimer = null;
627
- }
628
- const pendingRequests = this.pendingRequests;
629
- this.pendingRequests = [];
630
- const activeRequests = pendingRequests.filter((request) => {
631
- var _a;
632
- if (request.settled || ((_a = request.signal) == null ? void 0 : _a.aborted)) {
633
- this.abortRequest(request);
634
- return false;
635
- }
636
- return true;
637
- });
638
- const mergedRequests = this.mergeRequests(activeRequests);
639
- if (activeRequests.length > 0) {
640
- this.trackBatch(activeRequests, mergedRequests);
641
- }
642
- this.transportQueue.push(...mergedRequests);
643
- this.startQueuedTransports();
222
+ // ../../node_modules/@probe.gl/stats/dist/lib/stats.js
223
+ var Stats = class {
224
+ constructor(options) {
225
+ this.stats = {};
226
+ this.id = options.id;
227
+ this.stats = {};
228
+ this._initializeStats(options.stats);
229
+ Object.seal(this);
644
230
  }
645
- /** Cancels owned work and releases queued resources; borrowed users must not finalize shared schedulers. */
646
- finalize() {
647
- var _a;
648
- this.finalized = true;
649
- if (this.flushTimer !== null) clearTimeout(this.flushTimer);
650
- this.flushTimer = null;
651
- for (const request of this.logicalRequests) {
652
- this.abortRequest(request);
653
- if (request.abortListener)
654
- (_a = request.signal) == null ? void 0 : _a.removeEventListener("abort", request.abortListener);
655
- }
656
- for (const controller of this.transportControllers) controller.abort();
657
- this.transportQueue = [];
658
- this.pendingRequests = [];
659
- this.logicalRequests.clear();
660
- }
661
- /** Starts transports while respecting the configured concurrency bound. */
662
- startQueuedTransports() {
663
- while (this.activeTransports < this.props.maxConcurrency && this.transportQueue.length) {
664
- const request = this.transportQueue.shift();
665
- this.activeTransports++;
666
- void this.fetchMergedRequest(request).finally(() => {
667
- this.activeTransports--;
668
- this.startQueuedTransports();
669
- });
670
- }
231
+ /** Acquire a stat. Create if it doesn't exist. */
232
+ get(name, type = "count") {
233
+ return this._getOrCreate({ name, type });
671
234
  }
672
- /** Starts a fixed batch window only when no flush is already scheduled. */
673
- scheduleFlush() {
674
- if (this.flushTimer !== null) {
675
- return;
676
- }
677
- this.flushTimer = setTimeout(() => this.flush(), this.props.batchDelayMs);
235
+ get size() {
236
+ return Object.keys(this.stats).length;
678
237
  }
679
- /** Sorts active requests and combines requests for the same source when thresholds allow. */
680
- mergeRequests(requests) {
681
- requests.sort((left, right) => {
682
- if (left.sourceId !== right.sourceId) {
683
- return left.sourceId < right.sourceId ? -1 : 1;
684
- }
685
- return left.offset - right.offset;
686
- });
687
- const mergedRequests = [];
688
- for (const request of requests) {
689
- const requestEndOffset = request.offset + request.length;
690
- const lastMergedRequest = mergedRequests[mergedRequests.length - 1];
691
- if (lastMergedRequest && canMergeRequests(lastMergedRequest, request, this.props)) {
692
- lastMergedRequest.endOffset = Math.max(lastMergedRequest.endOffset, requestEndOffset);
693
- lastMergedRequest.requests.push(request);
694
- } else {
695
- mergedRequests.push({
696
- sourceId: request.sourceId,
697
- isolationKey: request.isolationKey ?? request.sourceId,
698
- offset: request.offset,
699
- endOffset: requestEndOffset,
700
- fetchRange: request.fetchRange,
701
- requests: [request]
702
- });
703
- }
238
+ /** Reset all stats */
239
+ reset() {
240
+ for (const stat of Object.values(this.stats)) {
241
+ stat.reset();
704
242
  }
705
- return mergedRequests;
243
+ return this;
706
244
  }
707
- /** Loads one merged range and resolves each child request with its sliced bytes. */
708
- async fetchMergedRequest(mergedRequest) {
709
- var _a, _b;
710
- const { offset, endOffset, fetchRange, requests } = mergedRequest;
711
- const abortController = new AbortController();
712
- this.transportControllers.add(abortController);
713
- const requestStartTime = getTimestamp();
714
- const abortTransportIfUnused = () => {
715
- if (requests.every((request) => {
716
- var _a2;
717
- return request.settled || ((_a2 = request.signal) == null ? void 0 : _a2.aborted);
718
- })) {
719
- abortController.abort();
720
- }
721
- };
722
- try {
723
- for (const request of requests) {
724
- request.onAbort = abortTransportIfUnused;
725
- }
726
- abortTransportIfUnused();
727
- if (requests.every((request) => request.settled)) {
728
- return;
729
- }
730
- const logicalBytes = getLogicalRequestBytes(requests);
731
- const length = endOffset - offset;
732
- this.trackEvent({
733
- type: "request",
734
- sourceId: mergedRequest.sourceId,
735
- offset,
736
- length,
737
- logicalRequestCount: requests.length,
738
- logicalBytes,
739
- transportBytes: length,
740
- overfetchBytes: Math.max(length - logicalBytes, 0)
741
- });
742
- const transportResult = normalizeTransportResult(
743
- await fetchRange(offset, length, abortController.signal)
744
- );
745
- const { arrayBuffer } = transportResult;
746
- const isClampedFullResponse = transportResult.fullResponse && offset === 0 && arrayBuffer.byteLength < length;
747
- const isClampedEndOfFile = arrayBuffer.byteLength < length && Number.isSafeInteger(transportResult.sourceByteLength) && offset + arrayBuffer.byteLength === transportResult.sourceByteLength;
748
- if (arrayBuffer.byteLength !== length && !isClampedFullResponse && !isClampedEndOfFile) {
749
- throw new Error(
750
- `Byte-range transport returned ${arrayBuffer.byteLength} bytes; expected ${length}`
751
- );
752
- }
753
- const networkTimeMs = transportResult.networkTimeMs ?? getTimestamp() - requestStartTime;
754
- this.trackEvent({
755
- type: "response",
756
- sourceId: mergedRequest.sourceId,
757
- offset,
758
- length,
759
- logicalRequestCount: requests.length,
760
- logicalBytes,
761
- transportBytes: length,
762
- responseBytes: transportResult.transportBytes ?? arrayBuffer.byteLength,
763
- networkTimeMs,
764
- overfetchBytes: Math.max(length - logicalBytes, 0),
765
- status: transportResult.status,
766
- fullResponse: transportResult.fullResponse
767
- });
768
- for (const request of requests) {
769
- if (request.settled) {
770
- continue;
771
- }
772
- const start = request.offset - offset;
773
- request.settled = true;
774
- request.resolve(arrayBuffer.slice(start, start + request.length));
775
- }
776
- } catch (error) {
777
- if (!abortController.signal.aborted) {
778
- this.trackEvent({
779
- type: "error",
780
- sourceId: mergedRequest.sourceId,
781
- offset,
782
- length: endOffset - offset,
783
- logicalRequestCount: requests.length,
784
- logicalBytes: getLogicalRequestBytes(requests),
785
- networkTimeMs: getTimestamp() - requestStartTime,
786
- error
787
- });
788
- }
789
- for (const request of requests) {
790
- if (request.settled) {
791
- continue;
792
- }
793
- if ((_a = request.signal) == null ? void 0 : _a.aborted) {
794
- this.abortRequest(request);
795
- } else {
796
- request.settled = true;
797
- request.reject(error);
798
- }
799
- }
800
- } finally {
801
- this.transportControllers.delete(abortController);
802
- for (const request of requests) {
803
- if (request.abortListener) {
804
- (_b = request.signal) == null ? void 0 : _b.removeEventListener("abort", request.abortListener);
805
- }
806
- request.onAbort = void 0;
807
- }
245
+ forEach(fn) {
246
+ for (const stat of Object.values(this.stats)) {
247
+ fn(stat);
808
248
  }
809
249
  }
810
- /** Rejects and tracks one logical request exactly once when its caller aborts. */
811
- abortRequest(request) {
812
- var _a;
813
- if (request.settled) {
814
- return;
815
- }
816
- request.settled = true;
817
- this.pendingRequests = this.pendingRequests.filter((pending) => pending !== request);
818
- for (const group of this.transportQueue) {
819
- group.requests = group.requests.filter((pending) => !pending.settled);
820
- if (group.requests.length) {
821
- group.offset = Math.min(...group.requests.map((pending) => pending.offset));
822
- group.endOffset = Math.max(
823
- ...group.requests.map((pending) => pending.offset + pending.length)
824
- );
825
- }
826
- }
827
- this.transportQueue = this.transportQueue.filter((group) => group.requests.length > 0);
828
- request.reject(((_a = request.signal) == null ? void 0 : _a.reason) ?? createAbortError2());
829
- this.trackEvent({
830
- type: "abort",
831
- sourceId: request.sourceId,
832
- offset: request.offset,
833
- length: request.length,
834
- logicalRequestCount: 1,
835
- logicalBytes: request.length
250
+ getTable() {
251
+ const table = {};
252
+ this.forEach((stat) => {
253
+ table[stat.name] = {
254
+ time: stat.time || 0,
255
+ count: stat.count || 0,
256
+ average: stat.getAverageTime() || 0,
257
+ hz: stat.getHz() || 0
258
+ };
836
259
  });
260
+ return table;
837
261
  }
838
- /** Emits one event to Stats and to the optional callback. */
839
- trackEvent(event) {
840
- var _a;
841
- trackStatsEvent(this.stats, event);
842
- try {
843
- (_a = this.onEvent) == null ? void 0 : _a.call(this, event);
844
- } catch {
845
- }
846
- }
847
- /** Emits one batch event after logical requests have been merged. */
848
- trackBatch(activeRequests, mergedRequests) {
849
- const logicalBytes = getLogicalRequestBytes(activeRequests);
850
- const transportBytes = mergedRequests.reduce(
851
- (sum, mergedRequest) => sum + mergedRequest.endOffset - mergedRequest.offset,
852
- 0
853
- );
854
- this.trackEvent({
855
- type: "batch",
856
- logicalRequestCount: activeRequests.length,
857
- transportRequestCount: mergedRequests.length,
858
- logicalBytes,
859
- transportBytes,
860
- overfetchBytes: Math.max(transportBytes - logicalBytes, 0)
861
- });
262
+ _initializeStats(stats = []) {
263
+ stats.forEach((stat) => this._getOrCreate(stat));
862
264
  }
863
- };
864
- function trackStatsEvent(stats, event) {
865
- if ((event.type === "response" || event.type === "error") && event.networkTimeMs !== void 0) {
866
- stats.get(RANGE_STATS_KEYS.networkTimeMs, "time").addTime(event.networkTimeMs);
867
- }
868
- switch (event.type) {
869
- case "queued":
870
- stats.get(RANGE_STATS_KEYS.logicalRanges, "count").incrementCount();
871
- stats.get(RANGE_STATS_KEYS.requestedBytes, "count").addCount(event.logicalBytes || 0);
872
- break;
873
- case "batch":
874
- stats.get(RANGE_STATS_KEYS.rangeBatches, "count").incrementCount();
875
- stats.get("Logical Ranges Batched", "count").addCount(event.logicalRequestCount || 0);
876
- stats.get(RANGE_STATS_KEYS.transportRanges, "count").addCount(event.transportRequestCount || 0);
877
- stats.get(RANGE_STATS_KEYS.coalescedRanges, "count").addCount(
878
- Math.max((event.logicalRequestCount || 0) - (event.transportRequestCount || 0), 0)
879
- );
880
- stats.get(RANGE_STATS_KEYS.transportBytes, "count").addCount(event.transportBytes || 0);
881
- stats.get(RANGE_STATS_KEYS.overfetchBytes, "count").addCount(event.overfetchBytes || 0);
882
- break;
883
- case "response":
884
- stats.get(RANGE_STATS_KEYS.completedTransportRanges, "count").incrementCount();
885
- stats.get(RANGE_STATS_KEYS.responseBytes, "count").addCount(event.responseBytes || 0);
886
- if (event.fullResponse) {
887
- stats.get(RANGE_STATS_KEYS.fullResponseFallbacks, "count").incrementCount();
888
- }
889
- break;
890
- case "error":
891
- stats.get(RANGE_STATS_KEYS.failedTransportRanges, "count").incrementCount();
892
- break;
893
- case "abort":
894
- stats.get(RANGE_STATS_KEYS.abortedLogicalRanges, "count").incrementCount();
895
- break;
896
- default:
897
- }
898
- }
899
- function createRangeStats(id = "range-request-scheduler") {
900
- const stats = new import_stats2.Stats({ id });
901
- initializeStats(stats);
902
- return stats;
903
- }
904
- async function fetchHttpRange(request) {
905
- const abortContext = createAbortableFetchContext(request.signal);
906
- const requestStartTime = getTimestamp();
907
- try {
908
- let fullResponse = false;
909
- let response = await request.fetch(
910
- request.url,
911
- createRangeFetchOptions(
912
- request.fetchOptions,
913
- request.offset,
914
- request.length,
915
- abortContext.signal
916
- )
917
- );
918
- if (response.status === 416 && request.offset === 0) {
919
- const actualLength = parseUnsatisfiedContentRange(response.headers.get("Content-Range"));
920
- if (!actualLength) {
921
- throw new Error("Missing content-length on 416 response");
922
- }
923
- response = await request.fetch(
924
- request.url,
925
- createRangeFetchOptions(request.fetchOptions, 0, actualLength, abortContext.signal)
926
- );
927
- fullResponse = true;
928
- }
929
- if (response.status === 200) {
930
- abortContext.abort();
931
- await cancelIgnoredRangeResponse(response);
932
- throw new Error("Byte-range request failed: server returned 200 instead of 206");
933
- }
934
- if (response.status !== 206 && !response.ok) {
935
- throw new Error(`Bad response code: ${response.status}`);
936
- }
937
- const arrayBuffer = await response.arrayBuffer();
938
- const contentRangeHeader = response.headers.get("Content-Range");
939
- const contentRange = parseSatisfiedContentRange(contentRangeHeader);
940
- if (contentRangeHeader && !contentRange) {
941
- throw new Error(`Invalid Content-Range header: ${contentRangeHeader}`);
942
- }
943
- if (contentRange) {
944
- const responseLength = contentRange.endOffset - contentRange.offset + 1;
945
- const requestedEndOffset = request.offset + request.length - 1;
946
- if (contentRange.offset !== request.offset || contentRange.endOffset > requestedEndOffset || responseLength !== arrayBuffer.byteLength || contentRange.sourceByteLength !== void 0 && contentRange.endOffset >= contentRange.sourceByteLength) {
947
- throw new Error(`Content-Range does not match requested range: ${contentRangeHeader}`);
948
- }
949
- }
950
- return {
951
- arrayBuffer,
952
- status: response.status,
953
- sourceByteLength: contentRange == null ? void 0 : contentRange.sourceByteLength,
954
- transportBytes: arrayBuffer.byteLength,
955
- networkTimeMs: getTimestamp() - requestStartTime,
956
- fullResponse
957
- };
958
- } finally {
959
- abortContext.removeAbortListener();
960
- }
961
- }
962
- function canMergeRequests(mergedRequest, request, props) {
963
- if (mergedRequest.sourceId !== request.sourceId) {
964
- return false;
965
- }
966
- if (mergedRequest.isolationKey !== (request.isolationKey ?? request.sourceId)) {
967
- return false;
968
- }
969
- const requestEndOffset = request.offset + request.length;
970
- const gapBytes = request.offset - mergedRequest.endOffset;
971
- const mergedBytes = Math.max(mergedRequest.endOffset, requestEndOffset) - mergedRequest.offset;
972
- return gapBytes <= props.rangeExpansionBytes && mergedBytes <= props.maxMergedBytes;
973
- }
974
- function initializeStats(stats) {
975
- stats.get(RANGE_STATS_KEYS.logicalRanges, "count");
976
- stats.get(RANGE_STATS_KEYS.requestedBytes, "count");
977
- stats.get(RANGE_STATS_KEYS.rangeBatches, "count");
978
- stats.get("Logical Ranges Batched", "count");
979
- stats.get(RANGE_STATS_KEYS.transportRanges, "count");
980
- stats.get(RANGE_STATS_KEYS.coalescedRanges, "count");
981
- stats.get(RANGE_STATS_KEYS.transportBytes, "count");
982
- stats.get(RANGE_STATS_KEYS.completedTransportRanges, "count");
983
- stats.get(RANGE_STATS_KEYS.responseBytes, "count");
984
- stats.get(RANGE_STATS_KEYS.networkTimeMs, "time");
985
- stats.get(RANGE_STATS_KEYS.overfetchBytes, "count");
986
- stats.get(RANGE_STATS_KEYS.fullResponseFallbacks, "count");
987
- stats.get(RANGE_STATS_KEYS.failedTransportRanges, "count");
988
- stats.get(RANGE_STATS_KEYS.abortedLogicalRanges, "count");
989
- }
990
- function getLogicalRequestBytes(requests) {
991
- return requests.reduce((sum, request) => sum + request.length, 0);
992
- }
993
- function normalizeTransportResult(result) {
994
- return result instanceof ArrayBuffer ? { arrayBuffer: result } : result;
995
- }
996
- function createRangeFetchOptions(fetchOptions, offset, length, signal) {
997
- return {
998
- ...fetchOptions,
999
- signal,
1000
- headers: {
1001
- ...getHeadersObject(fetchOptions == null ? void 0 : fetchOptions.headers),
1002
- Range: `bytes=${offset}-${offset + length - 1}`
1003
- }
1004
- };
1005
- }
1006
- function getHeadersObject(headers) {
1007
- if (!headers) {
1008
- return {};
1009
- }
1010
- if (headers instanceof Headers) {
1011
- return Object.fromEntries(headers.entries());
1012
- }
1013
- if (Array.isArray(headers)) {
1014
- return Object.fromEntries(headers);
1015
- }
1016
- return headers;
1017
- }
1018
- function parseUnsatisfiedContentRange(contentRange) {
1019
- const match = contentRange == null ? void 0 : contentRange.match(/^bytes \*\/(\d+)$/);
1020
- return match ? Number(match[1]) : null;
1021
- }
1022
- function parseSatisfiedContentRange(contentRange) {
1023
- const match = contentRange == null ? void 0 : contentRange.match(/^bytes (\d+)-(\d+)\/(\d+|\*)$/);
1024
- if (!match) {
1025
- return null;
1026
- }
1027
- const offset = Number(match[1]);
1028
- const endOffset = Number(match[2]);
1029
- const sourceByteLength = match[3] === "*" ? void 0 : Number(match[3]);
1030
- if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(endOffset) || offset > endOffset || sourceByteLength !== void 0 && !Number.isSafeInteger(sourceByteLength)) {
1031
- return null;
1032
- }
1033
- return { offset, endOffset, sourceByteLength };
1034
- }
1035
- function createAbortableFetchContext(parentSignal) {
1036
- const abortController = new AbortController();
1037
- const abortListener = () => abortController.abort(parentSignal == null ? void 0 : parentSignal.reason);
1038
- if (parentSignal == null ? void 0 : parentSignal.aborted) {
1039
- abortController.abort(parentSignal == null ? void 0 : parentSignal.reason);
1040
- } else {
1041
- parentSignal == null ? void 0 : parentSignal.addEventListener("abort", abortListener, { once: true });
1042
- }
1043
- return {
1044
- signal: abortController.signal,
1045
- abort: () => abortController.abort(),
1046
- removeAbortListener: () => parentSignal == null ? void 0 : parentSignal.removeEventListener("abort", abortListener)
1047
- };
1048
- }
1049
- async function cancelIgnoredRangeResponse(response) {
1050
- var _a;
1051
- await ((_a = response.body) == null ? void 0 : _a.cancel().catch(() => {
1052
- }));
1053
- }
1054
- function getTimestamp() {
1055
- var _a;
1056
- return ((_a = globalThis.performance) == null ? void 0 : _a.now()) ?? Date.now();
1057
- }
1058
- function createAbortError2() {
1059
- if (typeof DOMException !== "undefined") {
1060
- return new DOMException("Request aborted", "AbortError");
1061
- }
1062
- const error = new Error("Request aborted");
1063
- error.name = "AbortError";
1064
- return error;
1065
- }
1066
-
1067
- // ../loader-utils/src/lib/path-utils/path.ts
1068
- var path_exports = {};
1069
- __export(path_exports, {
1070
- dirname: () => dirname,
1071
- filename: () => filename,
1072
- join: () => join,
1073
- resolve: () => resolve
1074
- });
1075
-
1076
- // ../loader-utils/src/lib/path-utils/get-cwd.ts
1077
- function getCWD() {
1078
- var _a;
1079
- if (typeof process !== "undefined" && typeof process.cwd !== "undefined") {
1080
- return process.cwd();
1081
- }
1082
- const pathname = (_a = globalThis.location) == null ? void 0 : _a.pathname;
1083
- return (pathname == null ? void 0 : pathname.slice(0, pathname.lastIndexOf("/") + 1)) || "";
1084
- }
1085
-
1086
- // ../loader-utils/src/lib/path-utils/path.ts
1087
- function filename(url) {
1088
- const slashIndex = url ? url.lastIndexOf("/") : -1;
1089
- return slashIndex >= 0 ? url.substr(slashIndex + 1) : url;
1090
- }
1091
- function dirname(url) {
1092
- const slashIndex = url ? url.lastIndexOf("/") : -1;
1093
- return slashIndex >= 0 ? url.substr(0, slashIndex) : "";
1094
- }
1095
- function join(...parts) {
1096
- const separator = "/";
1097
- parts = parts.map((part, index) => {
1098
- if (index) {
1099
- part = part.replace(new RegExp(`^${separator}`), "");
1100
- }
1101
- if (index !== parts.length - 1) {
1102
- part = part.replace(new RegExp(`${separator}$`), "");
1103
- }
1104
- return part;
1105
- });
1106
- return parts.join(separator);
1107
- }
1108
- function resolve(...components) {
1109
- const paths = [];
1110
- for (let _i = 0; _i < components.length; _i++) {
1111
- paths[_i] = components[_i];
1112
- }
1113
- let resolvedPath = "";
1114
- let resolvedAbsolute = false;
1115
- let cwd;
1116
- for (let i = paths.length - 1; i >= -1 && !resolvedAbsolute; i--) {
1117
- let path;
1118
- if (i >= 0) {
1119
- path = paths[i];
1120
- } else {
1121
- if (cwd === void 0) {
1122
- cwd = getCWD();
1123
- }
1124
- path = cwd;
1125
- }
1126
- if (path.length === 0) {
1127
- continue;
1128
- }
1129
- resolvedPath = `${path}/${resolvedPath}`;
1130
- resolvedAbsolute = path.charCodeAt(0) === SLASH;
1131
- }
1132
- resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);
1133
- if (resolvedAbsolute) {
1134
- return `/${resolvedPath}`;
1135
- } else if (resolvedPath.length > 0) {
1136
- return resolvedPath;
1137
- }
1138
- return ".";
1139
- }
1140
- var SLASH = 47;
1141
- var DOT = 46;
1142
- function normalizeStringPosix(path, allowAboveRoot) {
1143
- let res = "";
1144
- let lastSlash = -1;
1145
- let dots = 0;
1146
- let code;
1147
- let isAboveRoot = false;
1148
- for (let i = 0; i <= path.length; ++i) {
1149
- if (i < path.length) {
1150
- code = path.charCodeAt(i);
1151
- } else if (code === SLASH) {
1152
- break;
1153
- } else {
1154
- code = SLASH;
1155
- }
1156
- if (code === SLASH) {
1157
- if (lastSlash === i - 1 || dots === 1) {
1158
- } else if (lastSlash !== i - 1 && dots === 2) {
1159
- if (res.length < 2 || !isAboveRoot || res.charCodeAt(res.length - 1) !== DOT || res.charCodeAt(res.length - 2) !== DOT) {
1160
- if (res.length > 2) {
1161
- const start = res.length - 1;
1162
- let j = start;
1163
- for (; j >= 0; --j) {
1164
- if (res.charCodeAt(j) === SLASH) {
1165
- break;
1166
- }
1167
- }
1168
- if (j !== start) {
1169
- res = j === -1 ? "" : res.slice(0, j);
1170
- lastSlash = i;
1171
- dots = 0;
1172
- isAboveRoot = false;
1173
- continue;
1174
- }
1175
- } else if (res.length === 2 || res.length === 1) {
1176
- res = "";
1177
- lastSlash = i;
1178
- dots = 0;
1179
- isAboveRoot = false;
1180
- continue;
1181
- }
1182
- }
1183
- if (allowAboveRoot) {
1184
- if (res.length > 0) {
1185
- res += "/..";
1186
- } else {
1187
- res = "..";
1188
- }
1189
- isAboveRoot = true;
1190
- }
265
+ _getOrCreate(stat) {
266
+ const { name, type } = stat;
267
+ let result = this.stats[name];
268
+ if (!result) {
269
+ if (stat instanceof Stat) {
270
+ result = stat;
1191
271
  } else {
1192
- const slice = path.slice(lastSlash + 1, i);
1193
- if (res.length > 0) {
1194
- res += `/${slice}`;
1195
- } else {
1196
- res = slice;
1197
- }
1198
- isAboveRoot = false;
272
+ result = new Stat(name, type);
1199
273
  }
1200
- lastSlash = i;
1201
- dots = 0;
1202
- } else if (code === DOT && dots !== -1) {
1203
- ++dots;
1204
- } else {
1205
- dots = -1;
274
+ this.stats[name] = result;
1206
275
  }
1207
- }
1208
- return res;
1209
- }
1210
-
1211
- // ../loader-utils/src/lib/files/blob-file.ts
1212
- var BlobFile = class {
1213
- handle;
1214
- size;
1215
- bigsize;
1216
- url;
1217
- constructor(blob) {
1218
- this.handle = blob instanceof ArrayBuffer ? new Blob([blob]) : blob;
1219
- this.size = blob instanceof ArrayBuffer ? blob.byteLength : blob.size;
1220
- this.bigsize = BigInt(this.size);
1221
- this.url = blob instanceof File ? blob.name : "";
1222
- }
1223
- async close() {
1224
- }
1225
- async stat() {
1226
- return {
1227
- size: this.handle.size,
1228
- bigsize: BigInt(this.handle.size),
1229
- isDirectory: false
1230
- };
1231
- }
1232
- async read(start, length, signal) {
1233
- if (signal == null ? void 0 : signal.aborted) {
1234
- throw new Error("Request aborted");
1235
- }
1236
- const arrayBuffer = await this.handle.slice(Number(start), Number(start) + Number(length)).arrayBuffer();
1237
- if (signal == null ? void 0 : signal.aborted) {
1238
- throw new Error("Request aborted");
1239
- }
1240
- return arrayBuffer;
1241
- }
1242
- };
1243
-
1244
- // ../loader-utils/src/lib/request-utils/abort-utils.ts
1245
- function waitForPromiseWithSignal(promise, signal) {
1246
- if (!signal) return promise;
1247
- if (signal.aborted) {
1248
- void promise.catch(() => {
1249
- });
1250
- return Promise.reject(signal.reason);
1251
- }
1252
- return new Promise((resolve2, reject) => {
1253
- const abort = () => {
1254
- signal.removeEventListener("abort", abort);
1255
- reject(signal.reason);
1256
- };
1257
- signal.addEventListener("abort", abort, { once: true });
1258
- void promise.then(
1259
- (value) => {
1260
- signal.removeEventListener("abort", abort);
1261
- resolve2(value);
1262
- },
1263
- (error) => {
1264
- signal.removeEventListener("abort", abort);
1265
- reject(error);
1266
- }
1267
- );
1268
- });
1269
- }
1270
- function waitForPromiseWithSignals(operation, signals) {
1271
- const controller = new AbortController();
1272
- const listeners = [];
1273
- const cleanup = () => {
1274
- for (const [signal, listener] of listeners) signal.removeEventListener("abort", listener);
1275
- };
1276
- for (const signal of signals) {
1277
- if (!signal) continue;
1278
- const listener = () => controller.abort(signal.reason);
1279
- listeners.push([signal, listener]);
1280
- signal.addEventListener("abort", listener, { once: true });
1281
- if (signal.aborted) listener();
1282
- }
1283
- try {
1284
- controller.signal.throwIfAborted();
1285
- return waitForPromiseWithSignal(operation(controller.signal), controller.signal).catch((error) => {
1286
- controller.abort(error);
1287
- throw error;
1288
- }).finally(cleanup);
1289
- } catch (error) {
1290
- controller.abort(error);
1291
- cleanup();
1292
- return Promise.reject(error);
1293
- }
1294
- }
1295
-
1296
- // ../loader-utils/src/lib/files/http-file-transport.ts
1297
- var HttpFileTransport = class {
1298
- /** Remote object URL. */
1299
- url;
1300
- /** Fetch implementation used for range requests. */
1301
- fetchFunction;
1302
- /** Persistent fetch options copied from the caller. */
1303
- fetchOptions;
1304
- /** Validator enforcement mode. */
1305
- consistency;
1306
- /** Caller-supplied identity information. */
1307
- identityHints;
1308
- /** Failure objects already included in telemetry. */
1309
- countedFailures = /* @__PURE__ */ new WeakSet();
1310
- /** Mutable counters backing immutable telemetry snapshots. */
1311
- telemetry = {
1312
- requestedBytes: 0,
1313
- downloadedBytes: 0,
1314
- requestCount: 0,
1315
- networkTimeMs: 0,
1316
- abortCount: 0,
1317
- errorCount: 0
1318
- };
1319
- /** Creates the transport for one remote object. */
1320
- constructor(url, options) {
1321
- validateKnownByteLength(options.byteLength);
1322
- this.url = url;
1323
- this.fetchFunction = options.fetch || ((input, init) => globalThis.fetch(input, init));
1324
- this.fetchOptions = options.fetchOptions ? { ...options.fetchOptions, headers: new Headers(options.fetchOptions.headers) } : void 0;
1325
- this.consistency = options.consistency || "best-effort";
1326
- this.identityHints = {
1327
- byteLength: options.byteLength,
1328
- etag: normalizeHeaderValue(options.etag),
1329
- lastModified: normalizeHeaderValue(options.lastModified)
1330
- };
1331
- }
1332
- /** Returns an identity that is complete enough to avoid an opening request. */
1333
- getInitialIdentity() {
1334
- const { byteLength, etag, lastModified } = this.identityHints;
1335
- if (byteLength !== void 0 && (etag !== void 0 || lastModified !== void 0)) {
1336
- return createIdentity(byteLength, etag, lastModified);
1337
- }
1338
- if (byteLength === 0 && this.consistency === "best-effort") {
1339
- return createIdentity(0);
1340
- }
1341
- return null;
1342
- }
1343
- /** Returns an immutable point-in-time copy of the transport counters. */
1344
- getTelemetry() {
1345
- return Object.freeze({ ...this.telemetry });
1346
- }
1347
- /** Counts each failure object once even when it passes through several async layers. */
1348
- trackFailure(error) {
1349
- if (typeof error === "object" && error !== null) {
1350
- if (this.countedFailures.has(error)) {
1351
- return;
1352
- }
1353
- this.countedFailures.add(error);
1354
- }
1355
- if (isAbortError(error)) {
1356
- this.telemetry.abortCount++;
1357
- } else {
1358
- this.telemetry.errorCount++;
1359
- }
1360
- }
1361
- /** Performs and validates one exact HTTP range request. */
1362
- async requestRange(offset, length, signal, expectedIdentity) {
1363
- var _a;
1364
- const requestStartTime = getTimestamp2();
1365
- const abortContext = createCombinedAbortContext(signal, (_a = this.fetchOptions) == null ? void 0 : _a.signal);
1366
- this.telemetry.requestCount++;
1367
- this.telemetry.requestedBytes += length;
1368
- try {
1369
- const response = await this.fetchFunction(
1370
- this.url,
1371
- createFetchOptions(this.fetchOptions, offset, length, abortContext.signal)
1372
- );
1373
- if (isEmptyIdentityProbeResponse(response, offset, length, expectedIdentity)) {
1374
- return await this.readEmptyIdentityProbe(response, requestStartTime);
1375
- }
1376
- if (response.status !== 206) {
1377
- await cancelResponse(response);
1378
- throw new Error(`HTTP byte-range request expected 206, received ${response.status}`);
1379
- }
1380
- const contentRange = await readContentRange(response);
1381
- const responseIdentity = getResponseIdentity(response, contentRange.byteLength);
1382
- const responseError = getIdentityError(
1383
- expectedIdentity,
1384
- responseIdentity,
1385
- this.identityHints,
1386
- this.consistency
1387
- ) || getRangeError(contentRange, offset, length);
1388
- if (responseError) {
1389
- await cancelResponse(response);
1390
- throw new Error(responseError);
1391
- }
1392
- const arrayBuffer = await response.arrayBuffer();
1393
- this.telemetry.downloadedBytes += arrayBuffer.byteLength;
1394
- if (arrayBuffer.byteLength !== length) {
1395
- throw new Error(
1396
- `HTTP byte-range response contained ${arrayBuffer.byteLength} bytes; expected ${length}`
1397
- );
1398
- }
1399
- return {
1400
- arrayBuffer,
1401
- identity: resolveIdentity(expectedIdentity, responseIdentity, this.identityHints),
1402
- status: response.status,
1403
- transportBytes: arrayBuffer.byteLength,
1404
- networkTimeMs: getTimestamp2() - requestStartTime
1405
- };
1406
- } catch (error) {
1407
- if (expectedIdentity === null || !isAbortError(error)) {
1408
- this.trackFailure(error);
1409
- }
1410
- throw error;
1411
- } finally {
1412
- abortContext.removeAbortListeners();
1413
- this.telemetry.networkTimeMs += getTimestamp2() - requestStartTime;
1414
- }
1415
- }
1416
- /** Validates and consumes the special empty-object identity response. */
1417
- async readEmptyIdentityProbe(response, requestStartTime) {
1418
- const responseIdentity = getResponseIdentity(response, 0);
1419
- const identityError = getIdentityError(
1420
- null,
1421
- responseIdentity,
1422
- this.identityHints,
1423
- this.consistency
1424
- );
1425
- await cancelResponse(response);
1426
- if (identityError) {
1427
- throw new Error(identityError);
1428
- }
1429
- return {
1430
- arrayBuffer: new ArrayBuffer(0),
1431
- identity: resolveIdentity(null, responseIdentity, this.identityHints),
1432
- status: response.status,
1433
- transportBytes: 0,
1434
- networkTimeMs: getTimestamp2() - requestStartTime
1435
- };
276
+ return result;
1436
277
  }
1437
278
  };
1438
- function createFetchOptions(fetchOptions, offset, length, signal) {
1439
- const headers = new Headers(fetchOptions == null ? void 0 : fetchOptions.headers);
1440
- headers.set("Range", `bytes=${offset}-${offset + length - 1}`);
1441
- return {
1442
- ...fetchOptions,
1443
- method: "GET",
1444
- body: void 0,
1445
- headers,
1446
- signal
1447
- };
1448
- }
1449
- function isEmptyIdentityProbeResponse(response, offset, length, expectedIdentity) {
1450
- return response.status === 416 && expectedIdentity === null && offset === 0 && length === 1 && /^bytes \*\/0$/i.test(response.headers.get("Content-Range") || "");
1451
- }
1452
- async function readContentRange(response) {
1453
- try {
1454
- return parseContentRange(response.headers.get("Content-Range"));
1455
- } catch (error) {
1456
- await cancelResponse(response);
1457
- throw error;
1458
- }
1459
- }
1460
- function parseContentRange(contentRange) {
1461
- const match = contentRange == null ? void 0 : contentRange.match(/^bytes (\d+)-(\d+)\/(\d+)$/);
1462
- if (!match) {
1463
- throw new Error("HTTP byte-range response has an invalid Content-Range header");
1464
- }
1465
- return {
1466
- offset: Number(match[1]),
1467
- endOffset: Number(match[2]),
1468
- byteLength: Number(match[3])
1469
- };
1470
- }
1471
- function getResponseIdentity(response, byteLength) {
1472
- return createIdentity(
1473
- byteLength,
1474
- normalizeHeaderValue(response.headers.get("ETag")),
1475
- normalizeHeaderValue(response.headers.get("Last-Modified"))
1476
- );
1477
- }
1478
- function resolveIdentity(expectedIdentity, responseIdentity, identityHints) {
1479
- return expectedIdentity || createIdentity(
1480
- responseIdentity.byteLength,
1481
- responseIdentity.etag ?? identityHints.etag,
1482
- responseIdentity.lastModified ?? identityHints.lastModified
1483
- );
1484
- }
1485
- function getRangeError(contentRange, offset, length) {
1486
- if (!Number.isSafeInteger(contentRange.offset) || !Number.isSafeInteger(contentRange.endOffset) || !Number.isSafeInteger(contentRange.byteLength) || contentRange.offset < 0 || contentRange.endOffset < contentRange.offset || contentRange.endOffset >= contentRange.byteLength) {
1487
- return "HTTP byte-range response has invalid range bounds";
1488
- }
1489
- if (contentRange.offset !== offset || contentRange.endOffset !== offset + length - 1) {
1490
- return "HTTP byte-range response does not match the requested range";
1491
- }
1492
- return null;
1493
- }
1494
- function getIdentityError(expectedIdentity, responseIdentity, identityHints, consistency) {
1495
- const expectedByteLength = (expectedIdentity == null ? void 0 : expectedIdentity.byteLength) ?? identityHints.byteLength;
1496
- if (expectedByteLength !== void 0 && responseIdentity.byteLength !== expectedByteLength) {
1497
- return "HTTP file length changed while the file was open";
1498
- }
1499
- const expectedEtag = (expectedIdentity == null ? void 0 : expectedIdentity.etag) ?? identityHints.etag;
1500
- const expectedLastModified = (expectedIdentity == null ? void 0 : expectedIdentity.lastModified) ?? identityHints.lastModified;
1501
- if (expectedEtag) {
1502
- if (responseIdentity.etag) {
1503
- return expectedEtag === responseIdentity.etag ? null : "HTTP file ETag changed while the file was open";
1504
- }
1505
- if (consistency === "strict") {
1506
- return "HTTP byte-range response is missing the pinned ETag";
1507
- }
1508
- if (expectedLastModified && responseIdentity.lastModified && expectedLastModified !== responseIdentity.lastModified) {
1509
- return "HTTP file Last-Modified value changed while the file was open";
1510
- }
1511
- return null;
1512
- }
1513
- if (expectedLastModified) {
1514
- if (responseIdentity.lastModified && expectedLastModified !== responseIdentity.lastModified) {
1515
- return "HTTP file Last-Modified value changed while the file was open";
1516
- }
1517
- if (consistency === "strict" && !responseIdentity.lastModified) {
1518
- return "HTTP byte-range response is missing the pinned Last-Modified value";
1519
- }
1520
- return null;
1521
- }
1522
- if (consistency === "strict" && !responseIdentity.etag && !responseIdentity.lastModified) {
1523
- return "HTTP byte-range response does not provide an ETag or Last-Modified validator";
1524
- }
1525
- return null;
1526
- }
1527
- function createIdentity(byteLength, etag, lastModified) {
1528
- return Object.freeze({ byteLength, etag, lastModified });
1529
- }
1530
- function validateKnownByteLength(byteLength) {
1531
- if (byteLength !== void 0 && (!Number.isSafeInteger(byteLength) || byteLength < 0)) {
1532
- throw new Error("HttpFile byteLength must be a non-negative safe integer");
1533
- }
1534
- }
1535
- async function cancelResponse(response) {
1536
- var _a;
1537
- await ((_a = response.body) == null ? void 0 : _a.cancel().catch(() => {
1538
- }));
1539
- }
1540
- function normalizeHeaderValue(value) {
1541
- return value || void 0;
1542
- }
1543
- function getTimestamp2() {
1544
- var _a;
1545
- return ((_a = globalThis.performance) == null ? void 0 : _a.now()) ?? Date.now();
1546
- }
1547
- function isAbortError(error) {
1548
- return error instanceof Error && error.name === "AbortError" || error instanceof Error && /aborted/i.test(error.message);
1549
- }
1550
- function createCombinedAbortContext(...signals) {
1551
- const abortController = new AbortController();
1552
- const uniqueSignals = [
1553
- ...new Set(signals.filter((signal) => Boolean(signal)))
1554
- ];
1555
- const abortListener = () => abortController.abort();
1556
- for (const signal of uniqueSignals) {
1557
- if (signal.aborted) {
1558
- abortController.abort();
1559
- } else {
1560
- signal.addEventListener("abort", abortListener, { once: true });
1561
- }
1562
- }
1563
- return {
1564
- signal: abortController.signal,
1565
- removeAbortListeners: () => {
1566
- for (const signal of uniqueSignals) {
1567
- signal.removeEventListener("abort", abortListener);
1568
- }
1569
- }
1570
- };
1571
- }
1572
279
 
1573
- // ../loader-utils/src/lib/files/http-file.ts
1574
- var HttpFile = class _HttpFile {
1575
- /** URL used as the ReadableFile handle. */
1576
- handle;
1577
- /** Remote object URL. */
1578
- url;
1579
- /** HTTP transport and response validator for this file. */
1580
- transport;
1581
- /** Scheduler used to coalesce compatible range reads. */
1582
- rangeScheduler;
1583
- /** Unique key that prevents coalescing across transport or credential contexts. */
1584
- schedulerIsolationKey = {};
1585
- /** Caller-supplied length available before identity discovery. */
1586
- suppliedByteLength;
1587
- /** Pinned remote object identity. */
1588
- identity;
1589
- /** Shared opening probe, while identity discovery is in progress. */
1590
- openPromise = null;
1591
- /** Whether the file has stopped accepting operations. */
1592
- closed = false;
1593
- /** Creates a lazy HTTP file. Use {@link HttpFile.open} when identity must be pinned immediately. */
1594
- constructor(url, options = {}) {
1595
- this.handle = url;
1596
- this.url = url;
1597
- this.transport = new HttpFileTransport(url, options);
1598
- this.rangeScheduler = options.rangeScheduler || new RangeRequestScheduler({ batchDelayMs: 0, ...options.rangeSchedulerProps });
1599
- this.suppliedByteLength = options.byteLength;
1600
- this.identity = this.transport.getInitialIdentity();
1601
- }
1602
- /** Opens a file and pins its byte length and available validators. */
1603
- static async open(url, options = {}, signal) {
1604
- const file = new _HttpFile(url, options);
1605
- await file.open(signal);
1606
- return file;
1607
- }
1608
- /** Pins this file's byte length and available validators. */
1609
- async open(signal) {
1610
- this.assertOpen();
1611
- if (signal == null ? void 0 : signal.aborted) {
1612
- const error = createAbortError3();
1613
- this.transport.trackFailure(error);
1614
- throw error;
1615
- }
1616
- await this.getIdentity(signal);
1617
- return this;
1618
- }
1619
- /** Pinned file length, or zero before a lazy file has opened. */
1620
- get size() {
1621
- var _a;
1622
- return ((_a = this.identity) == null ? void 0 : _a.byteLength) ?? this.suppliedByteLength ?? 0;
1623
- }
1624
- /** Pinned file length as a bigint, or zero before a lazy file has opened. */
1625
- get bigsize() {
1626
- return BigInt(this.size);
1627
- }
1628
- /** Returns the pinned identity, or null before a lazy file has opened. */
1629
- getIdentitySnapshot() {
1630
- return this.identity;
1631
- }
1632
- /** Returns an immutable point-in-time copy of this file's transport counters. */
1633
- getTelemetry() {
1634
- return this.transport.getTelemetry();
1635
- }
1636
- /** Prevents new operations. Active fetches remain controlled by their read signals. */
1637
- async close() {
1638
- this.closed = true;
1639
- }
1640
- /** Returns pinned file information without issuing a HEAD request. */
1641
- async stat() {
1642
- this.assertOpen();
1643
- const identity = await this.getIdentity();
1644
- return {
1645
- size: identity.byteLength,
1646
- bigsize: BigInt(identity.byteLength),
1647
- isDirectory: false
1648
- };
1649
- }
1650
- /** Reads exactly one byte range, with optional cancellation. */
1651
- async read(offset = 0, length = 0, signal) {
1652
- this.assertOpen();
1653
- if (signal == null ? void 0 : signal.aborted) {
1654
- const error = createAbortError3();
1655
- this.transport.trackFailure(error);
1656
- throw error;
1657
- }
1658
- const identity = await this.getIdentity(signal);
1659
- const numericOffset = normalizeOffset(offset);
1660
- validateRange(numericOffset, length, identity.byteLength);
1661
- if (length === 0) {
1662
- return new ArrayBuffer(0);
1663
- }
1664
- try {
1665
- return await this.rangeScheduler.scheduleRequest({
1666
- sourceId: this.url,
1667
- isolationKey: this.schedulerIsolationKey,
1668
- offset: numericOffset,
1669
- length,
1670
- signal,
1671
- fetchRange: this.fetchScheduledRange
1672
- });
1673
- } catch (error) {
1674
- this.transport.trackFailure(error);
1675
- throw error;
1676
- }
1677
- }
1678
- /** Reads a range and returns a Response for legacy ReadableFile consumers. */
1679
- async fetchRange(offset, length, signal) {
1680
- const numericOffset = normalizeOffset(offset);
1681
- const arrayBuffer = await this.read(numericOffset, length, signal);
1682
- const headers = createIdentityHeaders(this.identity, numericOffset, length);
1683
- return new Response(arrayBuffer, { status: 206, headers });
1684
- }
1685
- /** Stable scheduler callback used by every read from this file. */
1686
- fetchScheduledRange = async (offset, length, signal) => {
1687
- const identity = await this.getIdentity(signal);
1688
- const result = await this.transport.requestRange(offset, length, signal, identity);
1689
- return {
1690
- arrayBuffer: result.arrayBuffer,
1691
- status: result.status,
1692
- transportBytes: result.transportBytes,
1693
- networkTimeMs: result.networkTimeMs
1694
- };
1695
- };
1696
- /** Returns the shared lazy identity promise, retrying after a failed probe. */
1697
- getIdentity(signal) {
1698
- if (this.identity) {
1699
- return Promise.resolve(this.identity);
1700
- }
1701
- if (!this.openPromise) {
1702
- const nextOpenPromise = this.probeIdentity();
1703
- const cachedOpenPromise = nextOpenPromise.catch((error) => {
1704
- if (this.openPromise === cachedOpenPromise) {
1705
- this.openPromise = null;
1706
- }
1707
- throw error;
1708
- });
1709
- this.openPromise = cachedOpenPromise;
1710
- }
1711
- return waitForPromiseWithSignal(this.openPromise, signal).catch((error) => {
1712
- this.transport.trackFailure(error);
1713
- throw error;
1714
- });
1715
- }
1716
- /** Uses a one-byte GET range to discover object length and validators. */
1717
- async probeIdentity() {
1718
- try {
1719
- const result = await this.transport.requestRange(0, 1, void 0, null);
1720
- this.identity = result.identity;
1721
- return result.identity;
1722
- } catch (error) {
1723
- this.transport.trackFailure(error);
1724
- throw error;
1725
- }
1726
- }
1727
- /** Throws when the file has been closed. */
1728
- assertOpen() {
1729
- if (this.closed) {
1730
- throw new Error("HttpFile is closed");
1731
- }
1732
- }
1733
- };
1734
- function createIdentityHeaders(identity, offset, length) {
1735
- const headers = new Headers();
1736
- if (length > 0 && identity) {
1737
- headers.set("Content-Range", `bytes ${offset}-${offset + length - 1}/${identity.byteLength}`);
1738
- }
1739
- if (identity == null ? void 0 : identity.etag) {
1740
- headers.set("ETag", identity.etag);
1741
- }
1742
- if (identity == null ? void 0 : identity.lastModified) {
1743
- headers.set("Last-Modified", identity.lastModified);
1744
- }
1745
- return headers;
1746
- }
1747
- function normalizeOffset(offset) {
1748
- const numericOffset = Number(offset);
1749
- if (!Number.isSafeInteger(numericOffset) || numericOffset < 0) {
1750
- throw new Error("HTTP byte-range offset must be a non-negative safe integer");
1751
- }
1752
- return numericOffset;
1753
- }
1754
- function validateRange(offset, length, byteLength) {
1755
- if (!Number.isSafeInteger(length) || length < 0) {
1756
- throw new Error("HTTP byte-range length must be a non-negative safe integer");
1757
- }
1758
- if (offset + length > byteLength) {
1759
- throw new Error("HTTP byte range extends beyond the end of the file");
1760
- }
1761
- }
1762
- function createAbortError3() {
1763
- if (typeof DOMException !== "undefined") {
1764
- return new DOMException("Request aborted", "AbortError");
1765
- }
1766
- const error = new Error("Request aborted");
1767
- error.name = "AbortError";
1768
- return error;
1769
- }
280
+ // dist/tileset-3d/common/tileset-3d.js
281
+ var import_loader_utils2 = require("@loaders.gl/loader-utils");
1770
282
 
1771
283
  // dist/utils/doubly-linked-list-node.js
1772
284
  var DoublyLinkedListNode = class {
@@ -1924,9 +436,10 @@ var TilesetCache = class {
1924
436
  // dist/tileset-3d/helpers/transform-utils.js
1925
437
  var import_geospatial = require("@math.gl/geospatial");
1926
438
  var import_core = require("@math.gl/core");
439
+ var import_loader_utils = require("@loaders.gl/loader-utils");
1927
440
  function calculateTransformProps(tileHeader, tile) {
1928
- assert(tileHeader);
1929
- assert(tile);
441
+ (0, import_loader_utils.assert)(tileHeader);
442
+ (0, import_loader_utils.assert)(tile);
1930
443
  const { rtcCenter, gltfUpAxis } = tile;
1931
444
  const { computedTransform, boundingVolume: { center } } = tileHeader;
1932
445
  let modelMatrix = new import_core.Matrix4(computedTransform);
@@ -1970,15 +483,14 @@ function calculateTransformProps(tileHeader, tile) {
1970
483
  }
1971
484
  var TRANSLATION_LIMIT_SQUARED = 1e6 ** 2;
1972
485
  function _getRootNode(tile) {
1973
- var _a, _b;
1974
486
  const gltf = tile.gltf;
1975
487
  if (!gltf) {
1976
488
  return null;
1977
489
  }
1978
490
  const sceneIndex = typeof gltf.scene === "number" ? gltf.scene : 0;
1979
- const scene = (_a = gltf.scenes) == null ? void 0 : _a[sceneIndex];
1980
- const rootNode = (_b = scene == null ? void 0 : scene.nodes) == null ? void 0 : _b[0];
1981
- if (!(rootNode == null ? void 0 : rootNode.matrix))
491
+ const scene = gltf.scenes?.[sceneIndex];
492
+ const rootNode = scene?.nodes?.[0];
493
+ if (!rootNode?.matrix)
1982
494
  return null;
1983
495
  const m = rootNode.matrix;
1984
496
  const translationMagnitude = m[12] * m[12] + m[13] * m[13] + m[14] * m[14];
@@ -2067,7 +579,7 @@ function updateCameraMotionState(previousState, position, direction, currentTime
2067
579
  const directionArray = Array.from(direction);
2068
580
  const positionChanged = previousState ? positionArray.length !== previousState.position.length || positionArray.some((value, index) => Math.abs(value - previousState.position[index]) > CAMERA_POSITION_EPSILON) : false;
2069
581
  const directionChanged = previousState ? directionArray.length !== previousState.direction.length || directionArray.some((value, index) => Math.abs(value - previousState.direction[index]) > CAMERA_DIRECTION_EPSILON) : false;
2070
- const lastMovementTime = positionChanged || directionChanged ? currentTime : (previousState == null ? void 0 : previousState.lastMovementTime) ?? Number.NEGATIVE_INFINITY;
582
+ const lastMovementTime = positionChanged || directionChanged ? currentTime : previousState?.lastMovementTime ?? Number.NEGATIVE_INFINITY;
2071
583
  return {
2072
584
  state: {
2073
585
  position: positionArray,
@@ -2198,7 +710,7 @@ function getTiles3DScreenSpaceError(tile, frameState, useParentLodMetric, viewpo
2198
710
  }
2199
711
  function getOrthographicScreenSpaceError(lodMetricValue, frameState, lodScale, viewportHeightFraction) {
2200
712
  const viewport = frameState.viewport;
2201
- if (!(viewport == null ? void 0 : viewport.orthographic)) {
713
+ if (!viewport?.orthographic) {
2202
714
  return null;
2203
715
  }
2204
716
  const metersPerPixel = viewport.metersPerPixel;
@@ -2208,8 +720,7 @@ function getOrthographicScreenSpaceError(lodMetricValue, frameState, lodScale, v
2208
720
  return lodMetricValue * lodScale * viewportHeightFraction / metersPerPixel;
2209
721
  }
2210
722
  function getContentBoundingVolumeHeader(root) {
2211
- var _a;
2212
- return ((_a = root.header.content) == null ? void 0 : _a.boundingVolume) || root.header.boundingVolume;
723
+ return root.header.content?.boundingVolume || root.header.boundingVolume;
2213
724
  }
2214
725
  function getRegionHeightRange(region, frameState) {
2215
726
  const upDirection = scratchPositionNormal.copy(frameState.camera.position).normalize();
@@ -2411,7 +922,6 @@ function normalizeCrsIdentifier(identifier) {
2411
922
 
2412
923
  // dist/spatial/get-spatial-coordinate-frame.js
2413
924
  function getSpatialCoordinateFrame(definition) {
2414
- var _a, _b;
2415
925
  if (typeof definition === "string") {
2416
926
  const representation = (0, import_crs.inferCRSRepresentation)(definition);
2417
927
  if (representation === "wkt") {
@@ -2426,7 +936,7 @@ function getSpatialCoordinateFrame(definition) {
2426
936
  if (projJsonDefinition.type === "BoundCRS" && projJsonDefinition.source_crs) {
2427
937
  return getSpatialCoordinateFrame(projJsonDefinition.source_crs);
2428
938
  }
2429
- if (projJsonDefinition.type === "CompoundCRS" && ((_a = projJsonDefinition.components) == null ? void 0 : _a[0])) {
939
+ if (projJsonDefinition.type === "CompoundCRS" && projJsonDefinition.components?.[0]) {
2430
940
  return getSpatialCoordinateFrame(projJsonDefinition.components[0]);
2431
941
  }
2432
942
  if (String(projJsonDefinition.type).includes("Projected")) {
@@ -2436,7 +946,7 @@ function getSpatialCoordinateFrame(definition) {
2436
946
  return "geographic";
2437
947
  }
2438
948
  if (String(projJsonDefinition.type).includes("Geodetic")) {
2439
- return ((_b = projJsonDefinition.coordinate_system) == null ? void 0 : _b.subtype) === "Cartesian" ? "geocentric" : "geographic";
949
+ return projJsonDefinition.coordinate_system?.subtype === "Cartesian" ? "geocentric" : "geographic";
2440
950
  }
2441
951
  return "unknown";
2442
952
  }
@@ -2490,8 +1000,8 @@ function getWktCoordinateFrame(definition) {
2490
1000
  case "GEODCRS":
2491
1001
  case "GEODETICCRS": {
2492
1002
  const coordinateSystem = root.values.find((value) => value.type === "node" && value.keyword.toUpperCase() === "CS");
2493
- const subtype = coordinateSystem == null ? void 0 : coordinateSystem.values[0];
2494
- if ((subtype == null ? void 0 : subtype.type) !== "enumeration" && (subtype == null ? void 0 : subtype.type) !== "string") {
1003
+ const subtype = coordinateSystem?.values[0];
1004
+ if (subtype?.type !== "enumeration" && subtype?.type !== "string") {
2495
1005
  return "unknown";
2496
1006
  }
2497
1007
  return subtype.value.toUpperCase() === "CARTESIAN" ? "geocentric" : subtype.value.toUpperCase() === "ELLIPSOIDAL" ? "geographic" : "unknown";
@@ -2501,10 +1011,9 @@ function getWktCoordinateFrame(definition) {
2501
1011
  }
2502
1012
  }
2503
1013
  function getProjStringCoordinateFrame(definition) {
2504
- var _a;
2505
1014
  try {
2506
- const projection = (_a = (0, import_crs.parsePROJString)(definition).parameters.find((parameter) => parameter.name.toLowerCase() === "proj")) == null ? void 0 : _a.value;
2507
- switch (projection == null ? void 0 : projection.toLowerCase()) {
1015
+ const projection = (0, import_crs.parsePROJString)(definition).parameters.find((parameter) => parameter.name.toLowerCase() === "proj")?.value;
1016
+ switch (projection?.toLowerCase()) {
2508
1017
  case "longlat":
2509
1018
  case "latlong":
2510
1019
  return "geographic";
@@ -2588,23 +1097,23 @@ function createTilesetSpatialReference(discovered, options = {}) {
2588
1097
  }
2589
1098
  function applyTilesetSpatialOptions(discovered, options = {}) {
2590
1099
  return createTilesetSpatialReference({
2591
- sourceCrs: discovered == null ? void 0 : discovered.sourceCrs,
2592
- sourceCrsState: discovered == null ? void 0 : discovered.crs.state,
2593
- sourceCrsRepresentation: (discovered == null ? void 0 : discovered.crs.state) === "explicit" || (discovered == null ? void 0 : discovered.crs.state) === "default" ? discovered.crs.representation : void 0,
2594
- sourceCrsAlternatives: (discovered == null ? void 0 : discovered.crs.state) === "explicit" || (discovered == null ? void 0 : discovered.crs.state) === "default" ? discovered.crs.alternatives : void 0,
2595
- verticalCrs: discovered == null ? void 0 : discovered.verticalCrs,
2596
- units: discovered == null ? void 0 : discovered.units,
2597
- verticalUnitScale: discovered == null ? void 0 : discovered.verticalUnitScale,
2598
- coordinateEpoch: discovered == null ? void 0 : discovered.coordinateEpoch,
2599
- heightReference: discovered == null ? void 0 : discovered.heightReference,
2600
- elevationMode: discovered == null ? void 0 : discovered.elevationMode,
2601
- elevationOffset: discovered == null ? void 0 : discovered.elevationOffset,
2602
- elevationUnit: discovered == null ? void 0 : discovered.elevationUnit,
2603
- elevationUnitScale: discovered == null ? void 0 : discovered.elevationUnitScale,
2604
- coordinateFrame: discovered == null ? void 0 : discovered.coordinateFrame,
2605
- axisOrder: discovered == null ? void 0 : discovered.axisOrder,
2606
- provenance: discovered == null ? void 0 : discovered.provenance,
2607
- warnings: discovered == null ? void 0 : discovered.warnings
1100
+ sourceCrs: discovered?.sourceCrs,
1101
+ sourceCrsState: discovered?.crs.state,
1102
+ sourceCrsRepresentation: discovered?.crs.state === "explicit" || discovered?.crs.state === "default" ? discovered.crs.representation : void 0,
1103
+ sourceCrsAlternatives: discovered?.crs.state === "explicit" || discovered?.crs.state === "default" ? discovered.crs.alternatives : void 0,
1104
+ verticalCrs: discovered?.verticalCrs,
1105
+ units: discovered?.units,
1106
+ verticalUnitScale: discovered?.verticalUnitScale,
1107
+ coordinateEpoch: discovered?.coordinateEpoch,
1108
+ heightReference: discovered?.heightReference,
1109
+ elevationMode: discovered?.elevationMode,
1110
+ elevationOffset: discovered?.elevationOffset,
1111
+ elevationUnit: discovered?.elevationUnit,
1112
+ elevationUnitScale: discovered?.elevationUnitScale,
1113
+ coordinateFrame: discovered?.coordinateFrame,
1114
+ axisOrder: discovered?.axisOrder,
1115
+ provenance: discovered?.provenance,
1116
+ warnings: discovered?.warnings
2608
1117
  }, options);
2609
1118
  }
2610
1119
  function getKnownCRSDefinition(reference) {
@@ -2669,7 +1178,7 @@ function resolveMaximumCacheOverflowBytes(options, fallbackOverflowBytes) {
2669
1178
  const maximumCacheOverflowBytes = options.maximumCacheOverflowBytes ?? fallbackOverflowBytes;
2670
1179
  return validateCacheByteLength(maximumCacheOverflowBytes, "maximumCacheOverflowBytes");
2671
1180
  }
2672
- var DEFAULT_PROPS3 = {
1181
+ var DEFAULT_PROPS = {
2673
1182
  description: "",
2674
1183
  ellipsoid: import_geospatial3.Ellipsoid.WGS84,
2675
1184
  modelMatrix: new import_core5.Matrix4(),
@@ -2797,6 +1306,7 @@ var Tileset3D = class {
2797
1306
  _traverser;
2798
1307
  _cache = new TilesetCache();
2799
1308
  _requestScheduler;
1309
+ /** Drawn fallback instances retained independently for each viewport tree. */
2800
1310
  _heldTiles = /* @__PURE__ */ new Set();
2801
1311
  updatePromise = null;
2802
1312
  tilesetInitializationPromise;
@@ -2811,15 +1321,16 @@ var Tileset3D = class {
2811
1321
  }
2812
1322
  const suppliedOptions = options || {};
2813
1323
  const usesTiles3DCacheDefaults = source.type === TILESET_TYPE.TILES3D;
2814
- const defaultCacheBytes = usesTiles3DCacheDefaults ? DEFAULT_PROPS3.cacheBytes : DEFAULT_I3S_CACHE_BYTES;
2815
- const defaultMaximumCacheOverflowBytes = usesTiles3DCacheDefaults ? DEFAULT_PROPS3.maximumCacheOverflowBytes : DEFAULT_I3S_MAXIMUM_CACHE_OVERFLOW_BYTES;
1324
+ const defaultCacheBytes = usesTiles3DCacheDefaults ? DEFAULT_PROPS.cacheBytes : DEFAULT_I3S_CACHE_BYTES;
1325
+ const defaultMaximumCacheOverflowBytes = usesTiles3DCacheDefaults ? DEFAULT_PROPS.maximumCacheOverflowBytes : DEFAULT_I3S_MAXIMUM_CACHE_OVERFLOW_BYTES;
2816
1326
  const cacheBytes = resolveCacheBytes(suppliedOptions, defaultCacheBytes);
2817
1327
  const maximumCacheOverflowBytes = resolveMaximumCacheOverflowBytes(suppliedOptions, defaultMaximumCacheOverflowBytes);
2818
1328
  this.options = {
2819
- ...DEFAULT_PROPS3,
1329
+ ...DEFAULT_PROPS,
2820
1330
  ...suppliedOptions,
2821
1331
  cacheBytes,
2822
1332
  maximumCacheOverflowBytes,
1333
+ skipLevelOfDetail: suppliedOptions.skipLevelOfDetail ?? source.type === TILESET_TYPE.TILES3D,
2823
1334
  memoryAdjustedScreenSpaceError: suppliedOptions.memoryAdjustedScreenSpaceError ?? usesTiles3DCacheDefaults
2824
1335
  };
2825
1336
  this.loadOptions = this.options.loadOptions || {};
@@ -2836,7 +1347,7 @@ var Tileset3D = class {
2836
1347
  this.refine = "";
2837
1348
  this.contentFormats = this.source.contentFormats;
2838
1349
  this._traverser = this._initializeTraverser();
2839
- this._requestScheduler = new RequestScheduler({
1350
+ this._requestScheduler = new import_loader_utils2.RequestScheduler({
2840
1351
  throttleRequests: this.options.throttleRequests,
2841
1352
  maxRequests: this.options.maxRequests
2842
1353
  });
@@ -2847,14 +1358,13 @@ var Tileset3D = class {
2847
1358
  if (metadata) {
2848
1359
  this.spatialReference = applyTilesetSpatialOptions(metadata.spatialReference, this.options.spatial);
2849
1360
  }
2850
- this.stats = new import_stats3.Stats({ id: this.url });
1361
+ this.stats = new Stats({ id: this.url });
2851
1362
  this._initializeStats();
2852
1363
  this.tilesetInitializationPromise = this._initializeTileSet();
2853
1364
  }
2854
1365
  destroy() {
2855
- var _a, _b;
2856
1366
  this._clearDeferredTraversal();
2857
- (_b = (_a = this.source).destroy) == null ? void 0 : _b.call(_a);
1367
+ this.source.destroy?.();
2858
1368
  this._destroy();
2859
1369
  }
2860
1370
  isLoaded() {
@@ -2939,8 +1449,7 @@ var Tileset3D = class {
2939
1449
  return this.source.getTileUrl(tilePath);
2940
1450
  }
2941
1451
  hasExtension(extensionName) {
2942
- var _a, _b;
2943
- return Boolean((_b = (_a = this.source).hasExtension) == null ? void 0 : _b.call(_a, extensionName));
1452
+ return Boolean(this.source.hasExtension?.(extensionName));
2944
1453
  }
2945
1454
  update(viewports = null) {
2946
1455
  this.tilesetInitializationPromise.then(() => {
@@ -2960,12 +1469,12 @@ var Tileset3D = class {
2960
1469
  this.lastUpdatedVieports = viewports;
2961
1470
  }
2962
1471
  if (!this.updatePromise) {
2963
- this.updatePromise = new Promise((resolve2) => {
1472
+ this.updatePromise = new Promise((resolve) => {
2964
1473
  setTimeout(() => {
2965
1474
  if (this.lastUpdatedVieports) {
2966
1475
  this.doUpdate(this.lastUpdatedVieports);
2967
1476
  }
2968
- resolve2(this._frameNumber);
1477
+ resolve(this._frameNumber);
2969
1478
  this.updatePromise = null;
2970
1479
  }, this.options.debounceTime);
2971
1480
  });
@@ -3105,27 +1614,41 @@ var Tileset3D = class {
3105
1614
  this._emptyTiles = this._emptyTiles.concat(frameStateDataValue._emptyTiles);
3106
1615
  }
3107
1616
  this.selectedTiles = this.options.onTraversalComplete(this.selectedTiles);
3108
- const selectedIds = new Set(this.selectedTiles.map((tile) => tile.id));
1617
+ const selectedTiles = new Set(this.selectedTiles);
3109
1618
  const hasUndrawnTiles = this.selectedTiles.some((tile) => !tile.tileDrawn);
3110
1619
  let heldBackCount = 0;
3111
1620
  if (hasUndrawnTiles) {
3112
- for (const tileId of selectedIds) {
3113
- this._heldTiles.add(tileId);
1621
+ const activeRoots = new Set(Object.keys(this.frameStateData).map((viewportId) => this.roots[viewportId]));
1622
+ const descendantReadiness = /* @__PURE__ */ new Map();
1623
+ for (const tile of this.selectedTiles) {
1624
+ for (let ancestor = tile.parent; ancestor; ancestor = ancestor.parent) {
1625
+ descendantReadiness.set(ancestor, (descendantReadiness.get(ancestor) ?? true) && tile.tileDrawn);
1626
+ }
3114
1627
  }
3115
- for (const tileId of this._heldTiles) {
3116
- if (selectedIds.has(tileId))
1628
+ for (const tile of previousSelectedTiles) {
1629
+ if (tile.tileDrawn)
1630
+ this._heldTiles.add(tile);
1631
+ }
1632
+ for (const tile of this._heldTiles) {
1633
+ let root = tile;
1634
+ while (root.parent)
1635
+ root = root.parent;
1636
+ if (!activeRoots.has(root)) {
1637
+ this._heldTiles.delete(tile);
1638
+ continue;
1639
+ }
1640
+ if (selectedTiles.has(tile))
3117
1641
  continue;
3118
- const tile = this._tiles[tileId];
3119
- if (tile && tile.contentAvailable) {
1642
+ if (tile.contentAvailable && !this._hasDrawnReplacement(tile, selectedTiles, descendantReadiness)) {
3120
1643
  tile._selectedFrame = this._frameNumber;
3121
1644
  this.selectedTiles.push(tile);
3122
1645
  heldBackCount++;
3123
1646
  } else {
3124
- this._heldTiles.delete(tileId);
1647
+ this._heldTiles.delete(tile);
3125
1648
  }
3126
1649
  }
3127
1650
  } else {
3128
- this._heldTiles = selectedIds;
1651
+ this._heldTiles = selectedTiles;
3129
1652
  }
3130
1653
  if (heldBackCount > 0) {
3131
1654
  setTimeout(() => {
@@ -3142,6 +1665,19 @@ var Tileset3D = class {
3142
1665
  this.options.onUpdate();
3143
1666
  }
3144
1667
  }
1668
+ /**
1669
+ * Releases fallback geometry once its own selected replacement has drawn.
1670
+ * Unrelated pending branches must not delay this region's handoff. When no related
1671
+ * replacement is selected, retain the fallback until the complete selection has drawn.
1672
+ */
1673
+ _hasDrawnReplacement(tile, selectedTiles, descendantReadiness) {
1674
+ for (let ancestor = tile.parent; ancestor; ancestor = ancestor.parent) {
1675
+ if (selectedTiles.has(ancestor)) {
1676
+ return ancestor.tileDrawn;
1677
+ }
1678
+ }
1679
+ return descendantReadiness.get(tile) === true;
1680
+ }
3145
1681
  _tilesChanged(oldSelectedTiles, selectedTiles) {
3146
1682
  if (oldSelectedTiles.length !== selectedTiles.length) {
3147
1683
  return true;
@@ -3188,21 +1724,20 @@ var Tileset3D = class {
3188
1724
  this.stats.get(MAXIMUM_SSE).count = this.memoryAdjustedScreenSpaceError;
3189
1725
  }
3190
1726
  async _initializeTileSet() {
3191
- var _a, _b, _c, _d;
3192
1727
  try {
3193
1728
  const initializePromise = this.source.initialize();
3194
1729
  const initialMetadata = this._getSourceMetadata();
3195
1730
  if (initialMetadata) {
3196
1731
  this._syncSourceState(initialMetadata);
3197
1732
  }
3198
- if (((_a = initialMetadata == null ? void 0 : initialMetadata.tileset) == null ? void 0 : _a.root) && typeof initialMetadata.tileset.root.then !== "function" && (!this.source.prepareTileset || ((_b = this.spatialReference) == null ? void 0 : _b.status) === "native")) {
1733
+ if (initialMetadata?.tileset?.root && typeof initialMetadata.tileset.root.then !== "function" && (!this.source.prepareTileset || this.spatialReference?.status === "native")) {
3199
1734
  this.root = this._initializeTileHeaders(initialMetadata.tileset, null);
3200
1735
  this._applyViewState();
3201
1736
  }
3202
1737
  await initializePromise;
3203
1738
  const metadata = this.source.getMetadata();
3204
1739
  this._syncSourceState(metadata);
3205
- await ((_d = (_c = this.source).prepareTileset) == null ? void 0 : _d.call(_c, this));
1740
+ await this.source.prepareTileset?.(this);
3206
1741
  if (!this.root) {
3207
1742
  this.root = this._initializeTileHeaders(metadata.tileset, null);
3208
1743
  }
@@ -3288,16 +1823,15 @@ var Tileset3D = class {
3288
1823
  this.options.onTilesetError(error, this);
3289
1824
  }
3290
1825
  _onTileLoad(tile, loadResult) {
3291
- var _a, _b, _c, _d;
3292
- if (!(loadResult == null ? void 0 : loadResult.loaded)) {
1826
+ if (!loadResult?.loaded) {
3293
1827
  return;
3294
1828
  }
3295
1829
  if (tile.content) {
3296
1830
  calculateTransformProps(tile, tile.content);
3297
1831
  }
3298
- (_b = (_a = this.source).onTileLoaded) == null ? void 0 : _b.call(_a, this, tile, loadResult);
1832
+ this.source.onTileLoaded?.(this, tile, loadResult);
3299
1833
  this._syncSourceState(this.source.getMetadata());
3300
- const totalTiles = (_d = (_c = this.source).getTilesTotalCount) == null ? void 0 : _d.call(_c);
1834
+ const totalTiles = this.source.getTilesTotalCount?.();
3301
1835
  if (totalTiles) {
3302
1836
  this.stats.get(TILES_TOTAL).reset();
3303
1837
  this.stats.get(TILES_TOTAL).addCount(totalTiles);
@@ -3367,7 +1901,6 @@ var Tileset3D = class {
3367
1901
  tile.destroy();
3368
1902
  }
3369
1903
  _syncSourceState(metadata) {
3370
- var _a;
3371
1904
  this.tileset = metadata.tileset;
3372
1905
  this.loader = metadata.loader;
3373
1906
  this.type = metadata.type;
@@ -3388,25 +1921,24 @@ var Tileset3D = class {
3388
1921
  this.spatialReference = preserveTransformedSpatialReference(this.spatialReference, spatialReference);
3389
1922
  this.properties = this.source.properties ?? this.properties;
3390
1923
  this.extras = this.source.extras ?? this.extras;
3391
- if ((_a = this.options.attributions) == null ? void 0 : _a.length) {
1924
+ if (this.options.attributions?.length) {
3392
1925
  this.credits = { attributions: this.options.attributions };
3393
1926
  } else {
3394
1927
  this.credits = this.source.credits || this.credits;
3395
1928
  }
3396
1929
  }
3397
1930
  _applyViewState() {
3398
- var _a, _b;
3399
1931
  const viewState = this.source.getViewState(this.root);
3400
1932
  this.asset = viewState.asset || this.source.asset || {};
3401
1933
  this.properties = viewState.properties ?? this.source.properties;
3402
1934
  this.extras = viewState.extras ?? this.source.extras ?? null;
3403
1935
  this.credits = viewState.credits || this.source.credits || this.credits || { attributions: this.options.attributions || [] };
3404
1936
  this.description = viewState.description || this.options.description || "";
3405
- this.boundingVolume = viewState.boundingVolume || ((_a = this.root) == null ? void 0 : _a.boundingVolume) || null;
1937
+ this.boundingVolume = viewState.boundingVolume || this.root?.boundingVolume || null;
3406
1938
  this.cartographicCenter = viewState.cartographicCenter || new import_core5.Vector3();
3407
1939
  this.cartesianCenter = viewState.cartesianCenter || null;
3408
1940
  this.zoom = viewState.zoom || 1;
3409
- this.geometricError = ((_b = this.tileset) == null ? void 0 : _b.geometricError) || 0;
1941
+ this.geometricError = this.tileset?.geometricError || 0;
3410
1942
  }
3411
1943
  /**
3412
1944
  * Returns normalized source metadata when initialization has already populated it.
@@ -3420,12 +1952,11 @@ var Tileset3D = class {
3420
1952
  }
3421
1953
  };
3422
1954
  function preserveTransformedSpatialReference(current, next) {
3423
- return (current == null ? void 0 : current.status) === "transformed" && current.sourceCrs === next.sourceCrs && current.targetCrs === next.targetCrs && current.targetHeightReference === next.targetHeightReference && current.outputCoordinates === next.outputCoordinates ? current : next;
1955
+ return current?.status === "transformed" && current.sourceCrs === next.sourceCrs && current.targetCrs === next.targetCrs && current.targetHeightReference === next.targetHeightReference && current.outputCoordinates === next.outputCoordinates ? current : next;
3424
1956
  }
3425
1957
 
3426
1958
  // dist/tileset-3d/common/tileset-observability.js
3427
1959
  function getTileset3DTraversalSnapshot(tileset) {
3428
- var _a;
3429
1960
  const selectedTiles = tileset.selectedTiles.slice();
3430
1961
  const requestedTiles = tileset.requestedTiles.slice();
3431
1962
  const emptyTiles = tileset.emptyTiles.slice();
@@ -3435,7 +1966,7 @@ function getTileset3DTraversalSnapshot(tileset) {
3435
1966
  return typeof count === "number" && Number.isFinite(count) ? count : 0;
3436
1967
  };
3437
1968
  const implicitTilingSource = tileset.source;
3438
- const implicitTiling = (_a = implicitTilingSource.getImplicitTilingStats) == null ? void 0 : _a.call(implicitTilingSource);
1969
+ const implicitTiling = implicitTilingSource.getImplicitTilingStats?.();
3439
1970
  return {
3440
1971
  frameNumber: tileset.frameNumber,
3441
1972
  selectedTileIds: getTileIds(selectedTiles),
@@ -3455,7 +1986,6 @@ function getTileset3DTraversalSnapshot(tileset) {
3455
1986
 
3456
1987
  // dist/tileset-3d/common/tileset-content-traversal.js
3457
1988
  async function* traverseTilesetContents(tileset, options = {}) {
3458
- var _a, _b;
3459
1989
  await tileset.tilesetInitializationPromise;
3460
1990
  throwIfAborted(options.signal);
3461
1991
  if (!tileset.root) {
@@ -3496,7 +2026,7 @@ async function* traverseTilesetContents(tileset, options = {}) {
3496
2026
  if (!loadResult.loaded) {
3497
2027
  throw new Error(`Unable to load tile content for tile ${tile.id}`);
3498
2028
  }
3499
- (_b = (_a = tileset.source).onTileLoaded) == null ? void 0 : _b.call(_a, tileset, tile, loadResult);
2029
+ tileset.source.onTileLoaded?.(tileset, tile, loadResult);
3500
2030
  }
3501
2031
  yield { tile, contents: tile.contentEntries };
3502
2032
  } finally {
@@ -3510,12 +2040,13 @@ async function* traverseTilesetContents(tileset, options = {}) {
3510
2040
  }
3511
2041
  }
3512
2042
  function throwIfAborted(signal) {
3513
- if (signal == null ? void 0 : signal.aborted) {
2043
+ if (signal?.aborted) {
3514
2044
  throw signal.reason ?? new DOMException("The operation was aborted", "AbortError");
3515
2045
  }
3516
2046
  }
3517
2047
 
3518
2048
  // dist/tileset-3d/common/indexed-archive-tileset-source.js
2049
+ var import_loader_utils3 = require("@loaders.gl/loader-utils");
3519
2050
  var IndexedArchiveTilesetSource = class {
3520
2051
  /** URL exposed to the tileset source that owns this archive source. */
3521
2052
  sourceUrl;
@@ -3583,30 +2114,30 @@ var IndexedArchiveTilesetSource = class {
3583
2114
  async openArchiveReadableFile() {
3584
2115
  const { data } = this.options;
3585
2116
  if (typeof data !== "string") {
3586
- return new BlobFile(data);
2117
+ return new import_loader_utils3.BlobFile(data);
3587
2118
  }
3588
2119
  if (/^https?:\/\//i.test(data)) {
3589
- return new HttpFile(data);
2120
+ return new import_loader_utils3.HttpFile(data);
3590
2121
  }
3591
2122
  const coreApi = this.options.getCoreApi();
3592
2123
  if (!coreApi) {
3593
2124
  throw new Error(this.options.missingCoreApiMessage);
3594
2125
  }
3595
2126
  const response = await coreApi.fetchFile(data);
3596
- return new BlobFile(await response.arrayBuffer());
2127
+ return new import_loader_utils3.BlobFile(await response.arrayBuffer());
3597
2128
  }
3598
2129
  resolveArchivePath(request, baseUrl) {
3599
2130
  const requestWithoutQuery = stripQueryString(request);
3600
2131
  const archiveRoot = stripQueryString(this.sourceUrl);
3601
2132
  const baseWithoutQuery = stripQueryString(baseUrl);
3602
- const basePath = baseWithoutQuery === archiveRoot ? archiveRoot : path_exports.dirname(baseWithoutQuery);
2133
+ const basePath = baseWithoutQuery === archiveRoot ? archiveRoot : import_loader_utils3.path.dirname(baseWithoutQuery);
3603
2134
  const markerExpression = new RegExp(`\\.${this.options.archiveExtension}/(.*)$`, "i");
3604
2135
  const markerMatch = requestWithoutQuery.match(markerExpression);
3605
- if (markerMatch == null ? void 0 : markerMatch[1]) {
2136
+ if (markerMatch?.[1]) {
3606
2137
  return markerMatch[1];
3607
2138
  }
3608
2139
  const isAbsoluteRequest = /^[a-z][a-z0-9+.-]*:/i.test(requestWithoutQuery) || requestWithoutQuery.startsWith("/");
3609
- const absoluteRequest = requestWithoutQuery.startsWith(archiveRoot) ? requestWithoutQuery : baseWithoutQuery === archiveRoot && !isAbsoluteRequest ? `${archiveRoot}/${requestWithoutQuery}` : /^[a-z][a-z0-9+.-]*:\/\//i.test(baseWithoutQuery) ? new URL(requestWithoutQuery, baseWithoutQuery).href : path_exports.resolve(basePath, requestWithoutQuery);
2140
+ const absoluteRequest = requestWithoutQuery.startsWith(archiveRoot) ? requestWithoutQuery : baseWithoutQuery === archiveRoot && !isAbsoluteRequest ? `${archiveRoot}/${requestWithoutQuery}` : /^[a-z][a-z0-9+.-]*:\/\//i.test(baseWithoutQuery) ? new URL(requestWithoutQuery, baseWithoutQuery).href : import_loader_utils3.path.resolve(basePath, requestWithoutQuery);
3610
2141
  if (absoluteRequest === archiveRoot) {
3611
2142
  return "";
3612
2143
  }
@@ -3636,7 +2167,6 @@ function getTile3DFeatureIdSets(payload) {
3636
2167
  const featureIdSets = [];
3637
2168
  const visited = /* @__PURE__ */ new Set();
3638
2169
  const visit = (value) => {
3639
- var _a, _b;
3640
2170
  if (!value || typeof value !== "object") {
3641
2171
  return;
3642
2172
  }
@@ -3645,7 +2175,7 @@ function getTile3DFeatureIdSets(payload) {
3645
2175
  }
3646
2176
  visited.add(value);
3647
2177
  const record = value;
3648
- const declarations = (_b = (_a = record.extensions) == null ? void 0 : _a.EXT_mesh_features) == null ? void 0 : _b.featureIds;
2178
+ const declarations = record.extensions?.EXT_mesh_features?.featureIds;
3649
2179
  if (Array.isArray(declarations)) {
3650
2180
  for (const declaration of declarations) {
3651
2181
  if (!declaration || typeof declaration !== "object") {
@@ -3676,6 +2206,7 @@ function getTile3DFeatureIdSets(payload) {
3676
2206
  var import_core6 = require("@math.gl/core");
3677
2207
  var import_culling3 = require("@math.gl/culling");
3678
2208
  var import_geospatial4 = require("@math.gl/geospatial");
2209
+ var import_loader_utils4 = require("@loaders.gl/loader-utils");
3679
2210
  function defined(x) {
3680
2211
  return x !== void 0 && x !== null;
3681
2212
  }
@@ -3683,7 +2214,7 @@ var scratchPoint = new import_core6.Vector3();
3683
2214
  var scratchScale = new import_core6.Vector3();
3684
2215
  var identityTransform = new import_core6.Matrix4();
3685
2216
  function createBoundingVolume(boundingVolumeHeader, transform, result, initialTransform = transform) {
3686
- assert(boundingVolumeHeader, "3D Tile: boundingVolume must be defined");
2217
+ (0, import_loader_utils4.assert)(boundingVolumeHeader, "3D Tile: boundingVolume must be defined");
3687
2218
  if (boundingVolumeHeader.box) {
3688
2219
  const boxTransform = boundingVolumeHeader.s2VolumeInfo ? identityTransform : transform;
3689
2220
  return createBox(boundingVolumeHeader.box, boxTransform, result);
@@ -3901,6 +2432,7 @@ function getProjectedRadius(tile, frameState) {
3901
2432
  }
3902
2433
 
3903
2434
  // dist/utils/managed-array.js
2435
+ var import_loader_utils5 = require("@loaders.gl/loader-utils");
3904
2436
  var ManagedArray = class {
3905
2437
  _map = /* @__PURE__ */ new Map();
3906
2438
  _array;
@@ -3941,7 +2473,7 @@ var ManagedArray = class {
3941
2473
  * @param {Number} index The index to get.
3942
2474
  */
3943
2475
  get(index) {
3944
- assert(index < this._array.length);
2476
+ (0, import_loader_utils5.assert)(index < this._array.length);
3945
2477
  return this._array[index];
3946
2478
  }
3947
2479
  /**
@@ -3951,7 +2483,7 @@ var ManagedArray = class {
3951
2483
  * @param {*} element The element to set at index.
3952
2484
  */
3953
2485
  set(index, element) {
3954
- assert(index >= 0);
2486
+ (0, import_loader_utils5.assert)(index >= 0);
3955
2487
  if (index >= this.length) {
3956
2488
  this.length = index + 1;
3957
2489
  }
@@ -4005,7 +2537,7 @@ var ManagedArray = class {
4005
2537
  * @param {Number} length The length.
4006
2538
  */
4007
2539
  reserve(length) {
4008
- assert(length >= 0);
2540
+ (0, import_loader_utils5.assert)(length >= 0);
4009
2541
  if (length > this._array.length) {
4010
2542
  this._array.length = length;
4011
2543
  }
@@ -4016,7 +2548,7 @@ var ManagedArray = class {
4016
2548
  * @param {Number} length The length.
4017
2549
  */
4018
2550
  resize(length) {
4019
- assert(length >= 0);
2551
+ (0, import_loader_utils5.assert)(length >= 0);
4020
2552
  this.length = length;
4021
2553
  }
4022
2554
  /**
@@ -4041,7 +2573,7 @@ var ManagedArray = class {
4041
2573
  };
4042
2574
 
4043
2575
  // dist/tileset-3d/common/tileset-traverser.js
4044
- var DEFAULT_PROPS4 = {
2576
+ var DEFAULT_PROPS2 = {
4045
2577
  loadSiblings: false,
4046
2578
  skipLevelOfDetail: false,
4047
2579
  baseScreenSpaceError: 1024,
@@ -4081,7 +2613,7 @@ var TilesetTraverser = class {
4081
2613
  }
4082
2614
  // TODO nested props
4083
2615
  constructor(options) {
4084
- this.options = { ...DEFAULT_PROPS4, ...options };
2616
+ this.options = { ...DEFAULT_PROPS2, ...options };
4085
2617
  }
4086
2618
  /** Returns whether skip-LOD traversal is enabled and supported by the loaded content. */
4087
2619
  isSkipLevelOfDetailEnabled() {
@@ -4193,9 +2725,6 @@ var TilesetTraverser = class {
4193
2725
  childRefines = child.contentAvailable;
4194
2726
  }
4195
2727
  refines = refines && childRefines;
4196
- if (!refines) {
4197
- return false;
4198
- }
4199
2728
  }
4200
2729
  }
4201
2730
  if (!hasVisibleChild) {
@@ -4661,7 +3190,7 @@ var Tile3D = class {
4661
3190
  */
4662
3191
  _getGpuMemoryUsageInBytes() {
4663
3192
  const contents = this.contents.length ? this.contents : [this.content];
4664
- return contents.reduce((total, content) => total + ((content == null ? void 0 : content.gpuMemoryUsageInBytes) || (content == null ? void 0 : content.byteLength) || 0), 0);
3193
+ return contents.reduce((total, content) => total + (content?.gpuMemoryUsageInBytes || content?.byteLength || 0), 0);
4665
3194
  }
4666
3195
  /**
4667
3196
  * Returns scheduler priority for render-content requests.
@@ -4767,13 +3296,12 @@ var Tile3D = class {
4767
3296
  }
4768
3297
  /** Loads source content and updates the tile's renderer-neutral payload state. */
4769
3298
  async _loadContentFromSource() {
4770
- var _a;
4771
3299
  const loadResult = await this.tileset.source.loadTileContent(this);
4772
3300
  if (loadResult.contents) {
4773
3301
  this.contents = loadResult.contents;
4774
3302
  this.content = this.contents[0] || null;
4775
3303
  }
4776
- this.vectorContent = ((_a = this.contents.find((content) => Boolean(content == null ? void 0 : content.vectorContent))) == null ? void 0 : _a.vectorContent) || null;
3304
+ this.vectorContent = this.contents.find((content) => Boolean(content?.vectorContent))?.vectorContent || null;
4777
3305
  if (this.tileset.options.contentLoader) {
4778
3306
  await this.tileset.options.contentLoader(this);
4779
3307
  }
@@ -4870,13 +3398,12 @@ var Tile3D = class {
4870
3398
  }
4871
3399
  /** Refreshes tile and content metadata from a source or materialized tile header. */
4872
3400
  _initializeMetadata(header) {
4873
- var _a;
4874
3401
  this.metadata = header.metadata || null;
4875
3402
  const contentHeaders = Array.isArray(header.content) ? header.content : [header.content];
4876
3403
  this.contentMetadata = contentHeaders.filter(Boolean).map((contentHeader) => contentHeader.metadata || null);
4877
3404
  const firstContentHeader = contentHeaders.find(Boolean) || {};
4878
3405
  const groupReference = firstContentHeader.group;
4879
- const group = typeof groupReference === "number" ? ((_a = this.tileset.groups) == null ? void 0 : _a[groupReference]) || null : groupReference || null;
3406
+ const group = typeof groupReference === "number" ? this.tileset.groups?.[groupReference] || null : groupReference || null;
4880
3407
  const metadataContext = {
4881
3408
  tileset: this.tileset.metadata || null,
4882
3409
  group,
@@ -4892,17 +3419,14 @@ var Tile3D = class {
4892
3419
  /** Updates payload and renderability while retaining immutable metadata descriptors. */
4893
3420
  _updateContentEntriesAfterLoad(loadResult) {
4894
3421
  if (loadResult.contentEntries) {
4895
- this.contentEntries = loadResult.contentEntries.map((entry, index) => {
4896
- var _a;
4897
- return {
4898
- ...entry,
4899
- index,
4900
- boundingVolume: entry.boundingVolume || this._contentBoundingVolumes[index] || this.boundingVolume,
4901
- payload: entry.payload ?? this.contents[index] ?? null,
4902
- featureIds: ((_a = entry.featureIds) == null ? void 0 : _a.length) ? entry.featureIds : getTile3DFeatureIdSets(entry.payload ?? this.contents[index]),
4903
- renderable: Boolean(entry.renderable !== false && (entry.payload ?? this.contents[index]) && !isNestedTilesetPayload(entry.payload ?? this.contents[index]))
4904
- };
4905
- });
3422
+ this.contentEntries = loadResult.contentEntries.map((entry, index) => ({
3423
+ ...entry,
3424
+ index,
3425
+ boundingVolume: entry.boundingVolume || this._contentBoundingVolumes[index] || this.boundingVolume,
3426
+ payload: entry.payload ?? this.contents[index] ?? null,
3427
+ featureIds: entry.featureIds?.length ? entry.featureIds : getTile3DFeatureIdSets(entry.payload ?? this.contents[index]),
3428
+ renderable: Boolean(entry.renderable !== false && (entry.payload ?? this.contents[index]) && !isNestedTilesetPayload(entry.payload ?? this.contents[index]))
3429
+ }));
4906
3430
  this.featureIdSets = this.contentEntries.flatMap((entry) => entry.featureIds);
4907
3431
  return;
4908
3432
  }
@@ -4920,8 +3444,7 @@ var Tile3D = class {
4920
3444
  }
4921
3445
  /** Returns whether an ordered content entry currently has renderable payload. */
4922
3446
  isContentRenderable(index) {
4923
- var _a;
4924
- return Boolean((_a = this.contentEntries[index]) == null ? void 0 : _a.renderable);
3447
+ return Boolean(this.contentEntries[index]?.renderable);
4925
3448
  }
4926
3449
  /** Initializes additive renderer-neutral descriptors from a normalized tile header. */
4927
3450
  _initializeContentEntries(tileHeader) {
@@ -5004,7 +3527,6 @@ var Tile3D = class {
5004
3527
  * @param frameState - Current camera and viewport measurements.
5005
3528
  */
5006
3529
  _updateRequestPriorityMetrics(frameState) {
5007
- var _a, _b, _c, _d, _e;
5008
3530
  if (this.tileset.type !== TILESET_TYPE.TILES3D) {
5009
3531
  this._screenSpaceErrorProgressiveResolution = this._screenSpaceError;
5010
3532
  this._priorityProgressiveResolution = false;
@@ -5015,8 +3537,8 @@ var Tile3D = class {
5015
3537
  const options = this.tileset.options;
5016
3538
  const progressiveResolutionHeightFraction = options.progressiveResolutionHeightFraction;
5017
3539
  this._screenSpaceErrorProgressiveResolution = this.getScreenSpaceError(frameState, false, progressiveResolutionHeightFraction);
5018
- this._priorityProgressiveResolution = isProgressiveResolutionPriority(this._screenSpaceErrorProgressiveResolution, (_a = this.parent) == null ? void 0 : _a._screenSpaceErrorProgressiveResolution, this.tileset.memoryAdjustedScreenSpaceError, progressiveResolutionHeightFraction);
5019
- if (!options.foveatedScreenSpaceError || ((_b = frameState.viewport) == null ? void 0 : _b.orthographic) || !((_c = frameState.camera) == null ? void 0 : _c.position) || !((_d = frameState.camera) == null ? void 0 : _d.direction)) {
3540
+ this._priorityProgressiveResolution = isProgressiveResolutionPriority(this._screenSpaceErrorProgressiveResolution, this.parent?._screenSpaceErrorProgressiveResolution, this.tileset.memoryAdjustedScreenSpaceError, progressiveResolutionHeightFraction);
3541
+ if (!options.foveatedScreenSpaceError || frameState.viewport?.orthographic || !frameState.camera?.position || !frameState.camera?.direction) {
5020
3542
  this._foveatedFactor = 0;
5021
3543
  this.priorityDeferred = false;
5022
3544
  return;
@@ -5034,7 +3556,7 @@ var Tile3D = class {
5034
3556
  foveatedFactor: this._foveatedFactor,
5035
3557
  verticalFieldOfView: frameState.camera.verticalFieldOfView,
5036
3558
  screenSpaceError: this._screenSpaceError,
5037
- parentScreenSpaceError: (_e = this.parent) == null ? void 0 : _e._screenSpaceError,
3559
+ parentScreenSpaceError: this.parent?._screenSpaceError,
5038
3560
  maximumScreenSpaceError: this.tileset.memoryAdjustedScreenSpaceError,
5039
3561
  priorityProgressiveResolution: this._priorityProgressiveResolution
5040
3562
  });
@@ -5106,8 +3628,7 @@ var Tile3D = class {
5106
3628
  // INTERNAL METHODS
5107
3629
  /** Initializes the tile's LOD metric from its header or its nearest available ancestor. */
5108
3630
  _initializeLodMetric(header) {
5109
- var _a;
5110
- this._scaleGeometricError = typeof header._scaleGeometricError === "boolean" ? header._scaleGeometricError : ((_a = this.parent) == null ? void 0 : _a._scaleGeometricError) ?? true;
3631
+ this._scaleGeometricError = typeof header._scaleGeometricError === "boolean" ? header._scaleGeometricError : this.parent?._scaleGeometricError ?? true;
5111
3632
  if ("lodMetricType" in header) {
5112
3633
  this.lodMetricType = header.lodMetricType;
5113
3634
  } else {
@@ -5158,13 +3679,12 @@ var Tile3D = class {
5158
3679
  this._updateBoundingVolume(tileHeader);
5159
3680
  }
5160
3681
  _initializeContent(tileHeader) {
5161
- var _a;
5162
3682
  this.content = { _tileset: this.tileset, _tile: this };
5163
3683
  this.contents = [];
5164
3684
  this.hasEmptyContent = true;
5165
3685
  this.contentState = TILE_CONTENT_STATE.UNLOADED;
5166
3686
  this.hasTilesetContent = false;
5167
- if (tileHeader.contentUrl || ((_a = tileHeader.contentUrls) == null ? void 0 : _a.length)) {
3687
+ if (tileHeader.contentUrl || tileHeader.contentUrls?.length) {
5168
3688
  this.content = null;
5169
3689
  this.hasEmptyContent = false;
5170
3690
  }
@@ -5203,7 +3723,7 @@ var Tile3D = class {
5203
3723
  * `content`.
5204
3724
  */
5205
3725
  _isTileset() {
5206
- return (this.contents.length ? this.contents : [this.content]).some((content) => (content == null ? void 0 : content.shape) === "tileset3d");
3726
+ return (this.contents.length ? this.contents : [this.content]).some((content) => content?.shape === "tileset3d");
5207
3727
  }
5208
3728
  _onContentLoaded() {
5209
3729
  const contents = this.contents.length ? this.contents : [this.content];
@@ -5233,7 +3753,7 @@ var Tile3D = class {
5233
3753
  this._contentBoundingVolumeHeaders = Array.isArray(content) ? content : [content];
5234
3754
  }
5235
3755
  const contentHeaders = content ? Array.isArray(content) ? content : [content] : this._contentBoundingVolumeHeaders;
5236
- this._contentBoundingVolumes = contentHeaders.length ? contentHeaders.map((headerEntry) => (headerEntry == null ? void 0 : headerEntry.boundingVolume) ? createBoundingVolume(headerEntry.boundingVolume, this.computedTransform, void 0, this._initialTransform) : this.boundingVolume) : [this.boundingVolume];
3756
+ this._contentBoundingVolumes = contentHeaders.length ? contentHeaders.map((headerEntry) => headerEntry?.boundingVolume ? createBoundingVolume(headerEntry.boundingVolume, this.computedTransform, void 0, this._initialTransform) : this.boundingVolume) : [this.boundingVolume];
5237
3757
  this._contentBoundingVolume = this._contentBoundingVolumes[0] || null;
5238
3758
  }
5239
3759
  /**
@@ -5253,7 +3773,8 @@ var Tile3D = class {
5253
3773
  };
5254
3774
 
5255
3775
  // dist/tileset-3d/format-3d-tiles/tiles-3d-source.js
5256
- var import_geospatial10 = require("@math.gl/geospatial");
3776
+ var import_loader_utils6 = require("@loaders.gl/loader-utils");
3777
+ var import_geospatial9 = require("@math.gl/geospatial");
5257
3778
  var import_core12 = require("@math.gl/core");
5258
3779
 
5259
3780
  // dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js
@@ -5309,7 +3830,7 @@ var Tileset3DTraverser = class extends TilesetTraverser {
5309
3830
  if (!tile.hasRenderContent) {
5310
3831
  this.emptyTiles[tile.id] = tile;
5311
3832
  this.loadTile(tile, frameState);
5312
- if (stoppedRefining) {
3833
+ if (stoppedRefining && (!tile.hasEmptyContent || tile.hasChildren)) {
5313
3834
  this.selectDesiredTile(tile, frameState);
5314
3835
  }
5315
3836
  } else if (tile.refine === TILE_REFINEMENT.ADD) {
@@ -5350,7 +3871,7 @@ var Tileset3DTraverser = class extends TilesetTraverser {
5350
3871
  if (child.isVisibleAndInRequestVolume) {
5351
3872
  stack.push(child);
5352
3873
  hasVisibleChild = true;
5353
- } else if (this.options.loadSiblings) {
3874
+ } else if (this.options.loadSiblings && child._inRequestVolume) {
5354
3875
  this.loadTile(child, frameState);
5355
3876
  this.touchTile(child, frameState);
5356
3877
  }
@@ -5430,6 +3951,9 @@ var Tileset3DTraverser = class extends TilesetTraverser {
5430
3951
  while (fallbackTile) {
5431
3952
  if (this.shouldSelectTile(fallbackTile, frameState)) {
5432
3953
  this.selectTile(fallbackTile, frameState);
3954
+ if (fallbackTile !== tile) {
3955
+ this.selectLoadedDescendants(tile, frameState, true);
3956
+ }
5433
3957
  return;
5434
3958
  }
5435
3959
  fallbackTile = fallbackTile.parent;
@@ -5441,8 +3965,9 @@ var Tileset3DTraverser = class extends TilesetTraverser {
5441
3965
  *
5442
3966
  * @param root - Unavailable tile whose descendants are searched.
5443
3967
  * @param frameState - Current culling state.
3968
+ * @param drawnOnly - Reuse drawn detail without starting obsolete GPU work.
5444
3969
  */
5445
- selectLoadedDescendants(root, frameState) {
3970
+ selectLoadedDescendants(root, frameState, drawnOnly = false) {
5446
3971
  const stack = [{ tile: root, depth: 0 }];
5447
3972
  while (stack.length > 0) {
5448
3973
  const { tile, depth } = stack.pop();
@@ -5451,7 +3976,7 @@ var Tileset3DTraverser = class extends TilesetTraverser {
5451
3976
  if (!child.isVisibleAndInRequestVolume) {
5452
3977
  continue;
5453
3978
  }
5454
- if (child.contentAvailable) {
3979
+ if (this.shouldSelectTile(child, frameState) && (!drawnOnly || child.tileDrawn)) {
5455
3980
  this.selectTile(child, frameState);
5456
3981
  this.touchTile(child, frameState);
5457
3982
  } else if (depth < 1) {
@@ -5478,8 +4003,7 @@ var Tileset3DTraverser = class extends TilesetTraverser {
5478
4003
  * @param frameState - Current culling and LOD state.
5479
4004
  */
5480
4005
  updateChildTiles(tile, frameState) {
5481
- var _a;
5482
- const isImplicitHierarchyRoot = ((_a = tile.header.implicitSubtree) == null ? void 0 : _a.coordinates.level) === 0;
4006
+ const isImplicitHierarchyRoot = tile.header.implicitSubtree?.coordinates.level === 0;
5483
4007
  if (tile.hasUnloadedChildren && tile.isVisibleAndInRequestVolume && (isImplicitHierarchyRoot || this.shouldRefine(tile, frameState))) {
5484
4008
  const requestKey = `${frameState.viewport.id}:${tile.id}`;
5485
4009
  if (!this.pendingImplicitSubtrees.has(requestKey)) {
@@ -5662,19 +4186,18 @@ function getI3SVerticalUnitScale(heightUnit, zFactor) {
5662
4186
 
5663
4187
  // dist/spatial/format-spatial-reference.js
5664
4188
  function getI3SSpatialReference(layer) {
5665
- var _a, _b, _c, _d, _e, _f, _g, _h;
5666
- const spatialReference = layer.spatialReference || ((_a = layer.fullExtent) == null ? void 0 : _a.spatialReference);
4189
+ const spatialReference = layer.spatialReference || layer.fullExtent?.spatialReference;
5667
4190
  const sourceCrs = getI3SCrsDefinition(spatialReference);
5668
- const verticalCrs = ((_b = layer.heightModelInfo) == null ? void 0 : _b.vertCRS) || getI3SVerticalCrsDefinition(spatialReference);
5669
- const heightModel = (_c = layer.heightModelInfo) == null ? void 0 : _c.heightModel;
5670
- const verticalUnit = (_d = layer.heightModelInfo) == null ? void 0 : _d.heightUnit;
4191
+ const verticalCrs = layer.heightModelInfo?.vertCRS || getI3SVerticalCrsDefinition(spatialReference);
4192
+ const heightModel = layer.heightModelInfo?.heightModel;
4193
+ const verticalUnit = layer.heightModelInfo?.heightUnit;
5671
4194
  const verticalUnitScale = getI3SVerticalUnitScale(verticalUnit, layer.ZFactor);
5672
4195
  const heightReference = heightModel === "ellipsoidal" ? "ellipsoidal" : heightModel === "gravity_related_height" ? "orthometric" : "unknown";
5673
4196
  const sourceIdentifier = getCrsIdentifier(spatialReference);
5674
4197
  const coordinateFrame = sourceIdentifier === void 0 ? sourceCrs ? getSpatialCoordinateFrame(sourceCrs) : "unknown" : getSpatialCoordinateFrame(`EPSG:${sourceIdentifier}`);
5675
4198
  const units = getI3SCoordinateUnits(coordinateFrame, verticalUnit, layer.ZFactor);
5676
4199
  const warnings = [];
5677
- const elevationMode = getI3SElevationMode((_e = layer.elevationInfo) == null ? void 0 : _e.mode);
4200
+ const elevationMode = getI3SElevationMode(layer.elevationInfo?.mode);
5678
4201
  const elevationUnit = layer.elevationInfo ? layer.elevationInfo.unit || "meter" : void 0;
5679
4202
  const elevationUnitScale = getI3SLinearUnitScale(elevationUnit);
5680
4203
  if (verticalUnitScale === void 0) {
@@ -5683,7 +4206,7 @@ function getI3SSpatialReference(layer) {
5683
4206
  if (layer.elevationInfo && elevationUnitScale === void 0) {
5684
4207
  warnings.push(`Unsupported I3S elevation unit ${elevationUnit}`);
5685
4208
  }
5686
- if (((_f = layer.elevationInfo) == null ? void 0 : _f.mode) && !elevationMode) {
4209
+ if (layer.elevationInfo?.mode && !elevationMode) {
5687
4210
  warnings.push(`Unsupported I3S elevation mode ${layer.elevationInfo.mode}`);
5688
4211
  }
5689
4212
  if (elevationMode && elevationMode !== "absoluteHeight") {
@@ -5692,15 +4215,15 @@ function getI3SSpatialReference(layer) {
5692
4215
  return createTilesetSpatialReference({
5693
4216
  sourceCrs,
5694
4217
  sourceCrsRepresentation: sourceIdentifier !== void 0 ? "identifier" : sourceCrs ? "wkt" : void 0,
5695
- sourceCrsAlternatives: sourceIdentifier !== void 0 && (spatialReference == null ? void 0 : spatialReference.wkt) ? [{ definition: spatialReference.wkt, representation: "wkt" }] : void 0,
4218
+ sourceCrsAlternatives: sourceIdentifier !== void 0 && spatialReference?.wkt ? [{ definition: spatialReference.wkt, representation: "wkt" }] : void 0,
5696
4219
  verticalCrs,
5697
4220
  units,
5698
4221
  verticalUnitScale: verticalUnitScale ?? Number.NaN,
5699
4222
  heightReference,
5700
4223
  elevationMode,
5701
- elevationOffset: (_g = layer.elevationInfo) == null ? void 0 : _g.offset,
4224
+ elevationOffset: layer.elevationInfo?.offset,
5702
4225
  elevationUnit,
5703
- elevationUnitScale: ((_h = layer.elevationInfo) == null ? void 0 : _h.mode) && !elevationMode ? Number.NaN : elevationUnitScale ?? (layer.elevationInfo ? Number.NaN : 1),
4226
+ elevationUnitScale: layer.elevationInfo?.mode && !elevationMode ? Number.NaN : elevationUnitScale ?? (layer.elevationInfo ? Number.NaN : 1),
5704
4227
  coordinateFrame,
5705
4228
  axisOrder: sourceCrs ? "xyz" : "unknown",
5706
4229
  provenance: sourceCrs ? "metadata" : "unknown",
@@ -5728,7 +4251,6 @@ function getI3SElevationMode(mode) {
5728
4251
  }
5729
4252
  }
5730
4253
  function get3DTilesSpatialReference(tileset) {
5731
- var _a, _b;
5732
4254
  const draftSpatialReference = getDraft3DTilesSpatialReference(tileset);
5733
4255
  if (draftSpatialReference) {
5734
4256
  return draftSpatialReference;
@@ -5747,7 +4269,7 @@ function get3DTilesSpatialReference(tileset) {
5747
4269
  warnings.push("3D Tiles geocentric CRS is explicitly unknown");
5748
4270
  provenance = "metadata";
5749
4271
  sourceCrsState = "unknown";
5750
- } else if ((_b = (_a = tileset.root) == null ? void 0 : _a.boundingVolume) == null ? void 0 : _b.region) {
4272
+ } else if (tileset.root?.boundingVolume?.region) {
5751
4273
  sourceCrs = "EPSG:4978";
5752
4274
  provenance = "format-default";
5753
4275
  sourceCrsState = "default";
@@ -5771,8 +4293,7 @@ function get3DTilesSpatialReference(tileset) {
5771
4293
  });
5772
4294
  }
5773
4295
  function getDraft3DTilesSpatialReference(tileset) {
5774
- var _a, _b, _c;
5775
- const extension = (_a = tileset.extensions) == null ? void 0 : _a.EXT_geospatial_crs;
4296
+ const extension = tileset.extensions?.EXT_geospatial_crs;
5776
4297
  if (!extension) {
5777
4298
  return void 0;
5778
4299
  }
@@ -5782,8 +4303,8 @@ function getDraft3DTilesSpatialReference(tileset) {
5782
4303
  let epoch;
5783
4304
  let representation;
5784
4305
  if (extension.format === "wkid") {
5785
- const wkidExtension = (_b = extension.extensions) == null ? void 0 : _b.EXT_geospatial_crs_wkid;
5786
- if (typeof (wkidExtension == null ? void 0 : wkidExtension.authority) === "string" && Number.isInteger(wkidExtension.wkid)) {
4306
+ const wkidExtension = extension.extensions?.EXT_geospatial_crs_wkid;
4307
+ if (typeof wkidExtension?.authority === "string" && Number.isInteger(wkidExtension.wkid)) {
5787
4308
  sourceCrs = `${wkidExtension.authority}:${wkidExtension.wkid}`;
5788
4309
  representation = "identifier";
5789
4310
  if (Number.isInteger(wkidExtension.vcsWkid)) {
@@ -5797,8 +4318,8 @@ function getDraft3DTilesSpatialReference(tileset) {
5797
4318
  warnings.push("EXT_geospatial_crs_wkid requires string authority and integer wkid");
5798
4319
  }
5799
4320
  } else if (extension.format === "wkt2") {
5800
- const wktExtension = (_c = extension.extensions) == null ? void 0 : _c.EXT_geospatial_crs_wkt2;
5801
- if (typeof (wktExtension == null ? void 0 : wktExtension.wkt2) === "string" && wktExtension.wkt2.trim()) {
4321
+ const wktExtension = extension.extensions?.EXT_geospatial_crs_wkt2;
4322
+ if (typeof wktExtension?.wkt2 === "string" && wktExtension.wkt2.trim()) {
5802
4323
  sourceCrs = wktExtension.wkt2;
5803
4324
  representation = "wkt";
5804
4325
  } else {
@@ -5812,7 +4333,7 @@ function getDraft3DTilesSpatialReference(tileset) {
5812
4333
  if (verticalCrs && !verticalSemantics) {
5813
4334
  warnings.push(`Unsupported vertical CRS ${String(verticalCrs)}; vertical unit and height reference are unknown`);
5814
4335
  }
5815
- const verticalUnit = verticalCrs ? verticalSemantics == null ? void 0 : verticalSemantics.unit : "meter";
4336
+ const verticalUnit = verticalCrs ? verticalSemantics?.unit : "meter";
5816
4337
  return createTilesetSpatialReference({
5817
4338
  sourceCrs,
5818
4339
  sourceCrsState: sourceCrs ? "explicit" : "unknown",
@@ -5820,8 +4341,8 @@ function getDraft3DTilesSpatialReference(tileset) {
5820
4341
  verticalCrs,
5821
4342
  coordinateEpoch: epoch,
5822
4343
  units: coordinateFrame === "geocentric" ? ["meter", "meter", "meter"] : coordinateFrame === "geographic" && verticalUnit ? ["degree", "degree", verticalUnit] : void 0,
5823
- verticalUnitScale: verticalCrs ? (verticalSemantics == null ? void 0 : verticalSemantics.verticalUnitScale) ?? Number.NaN : 1,
5824
- heightReference: verticalCrs ? (verticalSemantics == null ? void 0 : verticalSemantics.heightReference) ?? "unknown" : sourceCrs ? "ellipsoidal" : "unknown",
4344
+ verticalUnitScale: verticalCrs ? verticalSemantics?.verticalUnitScale ?? Number.NaN : 1,
4345
+ heightReference: verticalCrs ? verticalSemantics?.heightReference ?? "unknown" : sourceCrs ? "ellipsoidal" : "unknown",
5825
4346
  coordinateFrame,
5826
4347
  axisOrder: sourceCrs ? "xyz" : "unknown",
5827
4348
  provenance: "metadata",
@@ -5866,27 +4387,26 @@ function getI3SCrsDefinition(spatialReference) {
5866
4387
  if (identifier !== void 0) {
5867
4388
  return `EPSG:${identifier}`;
5868
4389
  }
5869
- return spatialReference == null ? void 0 : spatialReference.wkt;
4390
+ return spatialReference?.wkt;
5870
4391
  }
5871
4392
  function getI3SVerticalCrsDefinition(spatialReference) {
5872
- const identifier = (spatialReference == null ? void 0 : spatialReference.latestVcsWkid) ?? (spatialReference == null ? void 0 : spatialReference.vcsWkid);
4393
+ const identifier = spatialReference?.latestVcsWkid ?? spatialReference?.vcsWkid;
5873
4394
  return identifier === void 0 ? void 0 : `EPSG:${identifier}`;
5874
4395
  }
5875
4396
  function getCrsIdentifier(spatialReference) {
5876
- return (spatialReference == null ? void 0 : spatialReference.latestWkid) ?? (spatialReference == null ? void 0 : spatialReference.wkid);
4397
+ return spatialReference?.latestWkid ?? spatialReference?.wkid;
5877
4398
  }
5878
4399
  function getTilesetSemanticValue(tileset, semantic) {
5879
- var _a, _b, _c, _d;
5880
- const classIdentifier = (_a = tileset.metadata) == null ? void 0 : _a.class;
4400
+ const classIdentifier = tileset.metadata?.class;
5881
4401
  if (!classIdentifier) {
5882
4402
  return void 0;
5883
4403
  }
5884
- const classDefinition = (_c = (_b = tileset.schema) == null ? void 0 : _b.classes) == null ? void 0 : _c[classIdentifier];
5885
- const propertyDefinitions = classDefinition == null ? void 0 : classDefinition.properties;
5886
- const propertyValues = (_d = tileset.metadata) == null ? void 0 : _d.properties;
4404
+ const classDefinition = tileset.schema?.classes?.[classIdentifier];
4405
+ const propertyDefinitions = classDefinition?.properties;
4406
+ const propertyValues = tileset.metadata?.properties;
5887
4407
  for (const [propertyIdentifier, propertyDefinition] of Object.entries(propertyDefinitions || {})) {
5888
4408
  if (propertyDefinition.semantic === semantic) {
5889
- return propertyValues == null ? void 0 : propertyValues[propertyIdentifier];
4409
+ return propertyValues?.[propertyIdentifier];
5890
4410
  }
5891
4411
  }
5892
4412
  return void 0;
@@ -5895,19 +4415,27 @@ function getTilesetSemanticValue(tileset, semantic) {
5895
4415
  // dist/spatial/spatial-coordinate-transformer.js
5896
4416
  var import_core10 = require("@math.gl/core");
5897
4417
  var import_geospatial7 = require("@math.gl/geospatial");
5898
- var import_projection2 = require("@math.gl/projection");
4418
+ var import_bulk = require("@math.gl/projection/bulk");
5899
4419
 
5900
4420
  // dist/spatial/spatial-resource-registry.js
5901
4421
  var import_geoid = require("@math.gl/geoid");
5902
4422
  var import_projection = require("@math.gl/projection");
5903
4423
  var geoidModels = /* @__PURE__ */ new Map();
4424
+ var projectionAliases = {};
4425
+ var datumGrids = {};
4426
+ var spatialProjectionEngine = new import_projection.FullProjectionEngine();
4427
+ function getSpatialProjectionEngine() {
4428
+ return spatialProjectionEngine;
4429
+ }
5904
4430
  function registerSpatialCrs(name, definition) {
5905
4431
  validateResourceName(name, "CRS");
5906
- import_projection.Projection.defineProjectionAliases({ [name]: definition });
4432
+ projectionAliases[name] = definition;
4433
+ spatialProjectionEngine = new import_projection.FullProjectionEngine({ aliases: projectionAliases, datumGrids });
5907
4434
  }
5908
4435
  function registerSpatialDatumGrid(name, data) {
5909
4436
  validateResourceName(name, "datum grid");
5910
- import_projection.Projection.registerDatumGrid(name, data);
4437
+ datumGrids[name] = (0, import_projection.parseNTv2Grid)(data);
4438
+ spatialProjectionEngine = new import_projection.FullProjectionEngine({ aliases: projectionAliases, datumGrids });
5911
4439
  }
5912
4440
  function registerGeoidModel(name, geoid) {
5913
4441
  validateResourceName(name, "geoid model");
@@ -5933,6 +4461,8 @@ var SpatialCoordinateTransformer = class {
5933
4461
  spatialReference;
5934
4462
  /** Projection from the source CRS directly to the requested horizontal target CRS. */
5935
4463
  horizontalProjection;
4464
+ /** Reusable packed xyz projection for horizontal-only coordinate batches. */
4465
+ horizontalProjectionBuffer;
5936
4466
  /** Projection from the source CRS to geographic longitude, latitude, and ellipsoidal height. */
5937
4467
  geographicProjection;
5938
4468
  /** Projection from adjusted geographic coordinates to the requested output CRS. */
@@ -5955,6 +4485,7 @@ var SpatialCoordinateTransformer = class {
5955
4485
  */
5956
4486
  constructor(spatialReference, options = {}) {
5957
4487
  this.spatialReference = spatialReference;
4488
+ const projectionEngine = getSpatialProjectionEngine();
5958
4489
  validateTransformRequest(spatialReference);
5959
4490
  const outputCrs = spatialReference.targetCrs || spatialReference.sourceCrs;
5960
4491
  this.sourceIsGeocentric = isWgs84Geocentric(spatialReference.sourceCrs);
@@ -5962,22 +4493,28 @@ var SpatialCoordinateTransformer = class {
5962
4493
  this.sourceIsGeographic = isWgs84Geographic(spatialReference.sourceCrs);
5963
4494
  this.outputIsGeographic = isWgs84Geographic(outputCrs);
5964
4495
  if (spatialReference.sourceCrs && spatialReference.targetCrs && !this.sourceIsGeocentric && !this.outputIsGeocentric) {
5965
- this.horizontalProjection = new import_projection2.Projection({
4496
+ this.horizontalProjection = projectionEngine.createProjection({
5966
4497
  from: getHorizontalProjectionDefinition(spatialReference.sourceCrs),
5967
4498
  to: getHorizontalProjectionDefinition(spatialReference.targetCrs),
5968
4499
  enforceAxis: false
5969
4500
  });
4501
+ if (!requiresHeightTransformation(spatialReference)) {
4502
+ this.horizontalProjectionBuffer = new import_bulk.ProjectionBuffer({
4503
+ projection: this.horizontalProjection,
4504
+ dimension: 3
4505
+ });
4506
+ }
5970
4507
  }
5971
4508
  if (requiresHeightTransformation(spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
5972
4509
  if (!this.sourceIsGeographic && !this.sourceIsGeocentric) {
5973
- this.geographicProjection = new import_projection2.Projection({
4510
+ this.geographicProjection = projectionEngine.createProjection({
5974
4511
  from: getHorizontalProjectionDefinition(spatialReference.sourceCrs),
5975
4512
  to: WGS84_GEOGRAPHIC_CRS,
5976
4513
  enforceAxis: false
5977
4514
  });
5978
4515
  }
5979
4516
  if (!this.outputIsGeographic && !this.outputIsGeocentric) {
5980
- this.heightOutputProjection = new import_projection2.Projection({
4517
+ this.heightOutputProjection = projectionEngine.createProjection({
5981
4518
  from: WGS84_GEOGRAPHIC_CRS,
5982
4519
  to: getHorizontalProjectionDefinition(outputCrs),
5983
4520
  enforceAxis: false
@@ -6017,17 +4554,23 @@ var SpatialCoordinateTransformer = class {
6017
4554
  return result;
6018
4555
  }
6019
4556
  if (this.horizontalProjection) {
6020
- const projected = this.horizontalProjection.project(result.slice(0, 3));
4557
+ const projected = this.horizontalProjection.projectSync(result.slice(0, 3));
6021
4558
  result.splice(0, projected.length, ...projected);
6022
4559
  }
6023
4560
  return result;
6024
4561
  }
6025
- /** Transform a packed sequence of xyz positions, preserving the input array type only when safe. */
4562
+ /** Transform packed xyz positions into owned Float64 storage, batching finite horizontal transforms. */
6026
4563
  transformPositions(positions) {
6027
4564
  if (positions.length % 3 !== 0) {
6028
4565
  throw new Error("Packed spatial positions must contain a multiple of three components");
6029
4566
  }
6030
4567
  const transformedPositions = new Float64Array(positions.length);
4568
+ if (this.horizontalProjectionBuffer) {
4569
+ transformedPositions.set(positions);
4570
+ if (transformedPositions.every(Number.isFinite)) {
4571
+ return this.horizontalProjectionBuffer.projectFlatTo(transformedPositions, transformedPositions);
4572
+ }
4573
+ }
6031
4574
  for (let index = 0; index < positions.length; index += 3) {
6032
4575
  const transformed = this.transformPosition([
6033
4576
  Number(positions[index]),
@@ -6081,7 +4624,7 @@ var SpatialCoordinateTransformer = class {
6081
4624
  if (this.sourceIsGeographic) {
6082
4625
  return coordinate.slice(0, 3);
6083
4626
  }
6084
- return this.geographicProjection.project(coordinate.slice(0, 3));
4627
+ return this.geographicProjection.projectSync(coordinate.slice(0, 3));
6085
4628
  }
6086
4629
  /** Convert one conventional WGS84 geographic coordinate to the selected output CRS. */
6087
4630
  fromGeographic(coordinate) {
@@ -6091,7 +4634,7 @@ var SpatialCoordinateTransformer = class {
6091
4634
  if (this.outputIsGeographic) {
6092
4635
  return coordinate.slice(0, 3);
6093
4636
  }
6094
- return this.heightOutputProjection.project(coordinate.slice(0, 3));
4637
+ return this.heightOutputProjection.projectSync(coordinate.slice(0, 3));
6095
4638
  }
6096
4639
  };
6097
4640
  function getFiniteDifferenceJacobian(transformer, position, epsilon) {
@@ -6189,7 +4732,6 @@ function transformHeight(height, geoidUndulation, source, target) {
6189
4732
 
6190
4733
  // dist/spatial/tiles-3d-spatial-transformer.js
6191
4734
  var import_core11 = require("@math.gl/core");
6192
- var import_geospatial8 = require("@math.gl/geospatial");
6193
4735
  var Tiles3DSpatialTransformer = class {
6194
4736
  /** Normalized reference describing the completed operation. */
6195
4737
  spatialReference;
@@ -6228,16 +4770,6 @@ var Tiles3DSpatialTransformer = class {
6228
4770
  }
6229
4771
  /** Transforms one WGS84 region sample into the selected output frame. */
6230
4772
  transformRegionSample(sample) {
6231
- const [longitudeDegrees, latitudeDegrees, height] = sample;
6232
- const targetCrs = this.spatialReference.targetCrs || this.spatialReference.sourceCrs;
6233
- if (targetCrs && getSpatialCoordinateFrame(targetCrs) === "geocentric") {
6234
- const cartesian = import_geospatial8.Ellipsoid.WGS84.cartographicToCartesian([
6235
- longitudeDegrees,
6236
- latitudeDegrees,
6237
- height
6238
- ]);
6239
- return Array.from(cartesian);
6240
- }
6241
4773
  return this.geographicCoordinateTransformer.transformPosition(sample);
6242
4774
  }
6243
4775
  };
@@ -6346,10 +4878,10 @@ var import_s22 = require("@math.gl/dggs/s2");
6346
4878
 
6347
4879
  // dist/tileset-3d/helpers/s2-bounding-volume.js
6348
4880
  var import_s2 = require("@math.gl/dggs/s2");
6349
- var import_geospatial9 = require("@math.gl/geospatial");
4881
+ var import_geospatial8 = require("@math.gl/geospatial");
6350
4882
  function convertS2BoundingVolumeToOBB(s2VolumeInfo) {
6351
4883
  const [[west, south], [east, north]] = (0, import_s2.getS2Bounds)(s2VolumeInfo.token);
6352
- const orientedBoundingBox = (0, import_geospatial9.makeOBBFromRegion)([west, south, east, north, s2VolumeInfo.minimumHeight, s2VolumeInfo.maximumHeight], import_geospatial9.Ellipsoid.WGS84, { units: "degrees" });
4884
+ const orientedBoundingBox = (0, import_geospatial8.makeOBBFromRegion)([west, south, east, north, s2VolumeInfo.minimumHeight, s2VolumeInfo.maximumHeight], import_geospatial8.Ellipsoid.WGS84, { units: "degrees" });
6353
4885
  return [...orientedBoundingBox.center, ...orientedBoundingBox.halfAxes];
6354
4886
  }
6355
4887
 
@@ -6504,7 +5036,6 @@ function createLazyImplicitTileHeader(subtree, descriptor, coordinates) {
6504
5036
  };
6505
5037
  }
6506
5038
  function getSubtreeAttributeOverrides(attributes, rowIndex, scope) {
6507
- var _a, _b;
6508
5039
  if (!attributes || rowIndex < 0) {
6509
5040
  return {};
6510
5041
  }
@@ -6529,11 +5060,11 @@ function getSubtreeAttributeOverrides(attributes, rowIndex, scope) {
6529
5060
  if (scope === "content") {
6530
5061
  return { boundingVolume };
6531
5062
  }
6532
- const geometricError = (_a = getAttributeComponents(attributes.TILE_GEOMETRIC_ERROR, rowIndex, 1)) == null ? void 0 : _a[0];
5063
+ const geometricError = getAttributeComponents(attributes.TILE_GEOMETRIC_ERROR, rowIndex, 1)?.[0];
6533
5064
  if (geometricError !== void 0 && (!Number.isFinite(geometricError) || geometricError < 0)) {
6534
5065
  throw new Error("3DTILES_subtree: TILE_GEOMETRIC_ERROR must be nonnegative");
6535
5066
  }
6536
- const refineValue = (_b = getAttributeComponents(attributes.TILE_REFINE, rowIndex, 1)) == null ? void 0 : _b[0];
5067
+ const refineValue = getAttributeComponents(attributes.TILE_REFINE, rowIndex, 1)?.[0];
6537
5068
  if (refineValue !== void 0 && refineValue !== 0 && refineValue !== 1) {
6538
5069
  throw new Error("3DTILES_subtree: TILE_REFINE must be 0 or 1");
6539
5070
  }
@@ -6555,7 +5086,6 @@ function getAttributeComponents(values, rowIndex, componentCount) {
6555
5086
  return Array.from({ length: componentCount }, (_unused, componentIndex) => Number(values[offset + componentIndex]));
6556
5087
  }
6557
5088
  function getAvailabilityRank(availability, index) {
6558
- var _a;
6559
5089
  if (availability.constant === 1) {
6560
5090
  return index;
6561
5091
  }
@@ -6564,7 +5094,7 @@ function getAvailabilityRank(availability, index) {
6564
5094
  }
6565
5095
  let ranks = AVAILABILITY_RANK_CACHE.get(availability);
6566
5096
  if (!ranks) {
6567
- const bitCount = (((_a = availability.explicitBitstream) == null ? void 0 : _a.byteLength) || 0) * 8;
5097
+ const bitCount = (availability.explicitBitstream?.byteLength || 0) * 8;
6568
5098
  ranks = new Uint32Array(bitCount + 1);
6569
5099
  for (let candidateIndex = 0; candidateIndex < bitCount; candidateIndex++) {
6570
5100
  ranks[candidateIndex + 1] = ranks[candidateIndex] + Number(getAvailabilityValue(availability, candidateIndex));
@@ -6574,12 +5104,11 @@ function getAvailabilityRank(availability, index) {
6574
5104
  return ranks[index];
6575
5105
  }
6576
5106
  function findImplicitPackageResource(files, resourceUrl) {
6577
- var _a;
6578
- if (!(files == null ? void 0 : files.length)) {
5107
+ if (!files?.length) {
6579
5108
  return void 0;
6580
5109
  }
6581
5110
  const urlWithoutQuery = resourceUrl.split("?")[0];
6582
- const packageRelativePath = (_a = /^gltf-package:\/\/[^/]+\/(.*)$/.exec(urlWithoutQuery)) == null ? void 0 : _a[1];
5111
+ const packageRelativePath = /^gltf-package:\/\/[^/]+\/(.*)$/.exec(urlWithoutQuery)?.[1];
6583
5112
  const exactFileIndex = files.findIndex((file) => {
6584
5113
  const reference = file.originalUri || file.name;
6585
5114
  return file.uri === urlWithoutQuery || Boolean(reference && (urlWithoutQuery === reference || packageRelativePath === reference));
@@ -6594,10 +5123,10 @@ function findImplicitPackageResource(files, resourceUrl) {
6594
5123
  return fileIndex < 0 ? void 0 : { fileIndex, files };
6595
5124
  }
6596
5125
  function mergeImplicitPackageFiles(parentFiles, childFiles) {
6597
- if (!(childFiles == null ? void 0 : childFiles.length)) {
5126
+ if (!childFiles?.length) {
6598
5127
  return parentFiles;
6599
5128
  }
6600
- if (!(parentFiles == null ? void 0 : parentFiles.length)) {
5129
+ if (!parentFiles?.length) {
6601
5130
  return childFiles;
6602
5131
  }
6603
5132
  const childReferences = new Set(childFiles.flatMap((file) => [file.uri, file.originalUri, file.name].filter(Boolean)));
@@ -6607,18 +5136,17 @@ function mergeImplicitPackageFiles(parentFiles, childFiles) {
6607
5136
  ];
6608
5137
  }
6609
5138
  function formatImplicitTileHeader(subtree, descriptor, reference, coordinates, availabilityIndex, contentAvailability, children) {
6610
- var _a, _b, _c, _d, _e;
6611
5139
  const tilePropertyIndex = getAvailabilityRank(subtree.tileAvailability, availabilityIndex);
6612
- const tileProperties = (_a = subtree.tilePropertyRows) == null ? void 0 : _a[tilePropertyIndex];
5140
+ const tileProperties = subtree.tilePropertyRows?.[tilePropertyIndex];
6613
5141
  const primaryContentAvailability = Array.isArray(subtree.contentAvailability) ? subtree.contentAvailability[0] : subtree.contentAvailability;
6614
5142
  const contentPropertyIndex = primaryContentAvailability && getAvailabilityValue(primaryContentAvailability, availabilityIndex) ? getAvailabilityRank(primaryContentAvailability, availabilityIndex) : -1;
6615
- const contentProperties = (_b = subtree.contentPropertyRows) == null ? void 0 : _b[contentPropertyIndex];
6616
- const tileTemplateProperties = ((_c = subtree.tileTemplatePropertyRows) == null ? void 0 : _c[tilePropertyIndex]) || tileProperties;
6617
- const contentTemplateProperties = ((_d = subtree.contentTemplatePropertyRows) == null ? void 0 : _d[contentPropertyIndex]) || contentProperties;
5143
+ const contentProperties = subtree.contentPropertyRows?.[contentPropertyIndex];
5144
+ const tileTemplateProperties = subtree.tileTemplatePropertyRows?.[tilePropertyIndex] || tileProperties;
5145
+ const contentTemplateProperties = subtree.contentTemplatePropertyRows?.[contentPropertyIndex] || contentProperties;
6618
5146
  const templateProperties = { ...tileTemplateProperties, ...contentTemplateProperties };
6619
5147
  const tileAttributes = getSubtreeAttributeOverrides(subtree.tileAttributes, tilePropertyIndex, "tile");
6620
5148
  const contentAttributes = getSubtreeAttributeOverrides(subtree.contentAttributes, contentPropertyIndex, "content");
6621
- const contentUrlTemplates = ((_e = descriptor.contentUrlTemplates) == null ? void 0 : _e.length) ? descriptor.contentUrlTemplates : [descriptor.contentUrlTemplate];
5149
+ const contentUrlTemplates = descriptor.contentUrlTemplates?.length ? descriptor.contentUrlTemplates : [descriptor.contentUrlTemplate];
6622
5150
  const contentEntries = contentUrlTemplates.map((templateUrl, contentIndex) => {
6623
5151
  if (!contentAvailability[contentIndex] || !templateUrl) {
6624
5152
  return null;
@@ -6635,10 +5163,9 @@ function formatImplicitTileHeader(subtree, descriptor, reference, coordinates, a
6635
5163
  const availableContentUrls = contentEntries.map((entry) => entry.contentUrl);
6636
5164
  const resourceFiles = mergeImplicitPackageFiles(descriptor.resourceFiles, subtree.resourceFiles);
6637
5165
  const content = contentEntries.map(({ contentIndex, contentUrl: contentUrl2 }) => {
6638
- var _a2;
6639
5166
  const packageResource = findImplicitPackageResource(resourceFiles, contentUrl2);
6640
5167
  return {
6641
- ...((_a2 = descriptor.contentHeaders) == null ? void 0 : _a2[contentIndex]) || (contentIndex === 0 ? descriptor.contentHeader : {}) || {},
5168
+ ...descriptor.contentHeaders?.[contentIndex] || (contentIndex === 0 ? descriptor.contentHeader : {}) || {},
6642
5169
  ...contentAttributes,
6643
5170
  uri: contentUrl2,
6644
5171
  ...contentProperties ? { metadata: { properties: contentProperties } } : {},
@@ -6686,10 +5213,10 @@ function getImplicitTileId(reference, coordinates) {
6686
5213
  return `${reference.subtreeUrl}#implicit=${coordinates.level}/${coordinates.x}/${coordinates.y}/${coordinates.z}`;
6687
5214
  }
6688
5215
  function getAvailabilityValue(availability, index) {
6689
- if (typeof (availability == null ? void 0 : availability.constant) === "number") {
5216
+ if (typeof availability?.constant === "number") {
6690
5217
  return Boolean(availability.constant);
6691
5218
  }
6692
- const bitstream = availability == null ? void 0 : availability.explicitBitstream;
5219
+ const bitstream = availability?.explicitBitstream;
6693
5220
  if (!bitstream) {
6694
5221
  return false;
6695
5222
  }
@@ -6716,7 +5243,6 @@ function getImplicitChildCount(subdivisionScheme) {
6716
5243
  return subdivisionScheme === "OCTREE" ? OCTREE_CHILD_COUNT : QUADTREE_CHILD_COUNT;
6717
5244
  }
6718
5245
  function calculateImplicitBoundingVolume(rootBoundingVolume, coordinates, subdivisionScheme) {
6719
- var _a;
6720
5246
  if (rootBoundingVolume.region) {
6721
5247
  const [west, south, east, north, minimumHeight, maximumHeight] = rootBoundingVolume.region;
6722
5248
  const divisionCount = 2 ** coordinates.level;
@@ -6748,7 +5274,7 @@ function calculateImplicitBoundingVolume(rootBoundingVolume, coordinates, subdiv
6748
5274
  if (rootBoundingVolume.s2VolumeInfo) {
6749
5275
  return calculateS2ImplicitBoundingVolume(rootBoundingVolume, coordinates, subdivisionScheme);
6750
5276
  }
6751
- if ((_a = rootBoundingVolume.extensions) == null ? void 0 : _a["3DTILES_shape_cylinder_region"]) {
5277
+ if (rootBoundingVolume.extensions?.["3DTILES_shape_cylinder_region"]) {
6752
5278
  return {
6753
5279
  ...rootBoundingVolume,
6754
5280
  box: [...rootBoundingVolume.box]
@@ -6794,10 +5320,10 @@ function calculateS2ImplicitBoundingVolume(rootBoundingVolume, coordinates, subd
6794
5320
  maximumHeight: rootS2VolumeInfo.minimumHeight + (subdivisionScheme === "OCTREE" ? heightSize * (coordinates.z + 1) : heightSize * divisionCount)
6795
5321
  };
6796
5322
  const extensions = rootBoundingVolume.extensions ? { ...rootBoundingVolume.extensions } : void 0;
6797
- if (extensions == null ? void 0 : extensions["3DTILES_bounding_volume_S2"]) {
5323
+ if (extensions?.["3DTILES_bounding_volume_S2"]) {
6798
5324
  extensions["3DTILES_bounding_volume_S2"] = childS2VolumeInfo;
6799
5325
  }
6800
- if (extensions == null ? void 0 : extensions["3DTILES_shape_s2"]) {
5326
+ if (extensions?.["3DTILES_shape_s2"]) {
6801
5327
  extensions["3DTILES_shape_s2"] = childS2VolumeInfo;
6802
5328
  }
6803
5329
  return {
@@ -6818,11 +5344,10 @@ function normalizeRegionLongitude(longitude) {
6818
5344
  return normalizedLongitude;
6819
5345
  }
6820
5346
  function getImplicitTileType(contentUrl) {
6821
- var _a;
6822
5347
  if (!contentUrl) {
6823
5348
  return TILE_TYPE.EMPTY;
6824
5349
  }
6825
- const extension = (_a = contentUrl.split("?")[0].split(".").pop()) == null ? void 0 : _a.toLowerCase();
5350
+ const extension = contentUrl.split("?")[0].split(".").pop()?.toLowerCase();
6826
5351
  switch (extension) {
6827
5352
  case "pnts":
6828
5353
  return TILE_TYPE.POINTCLOUD;
@@ -6917,19 +5442,18 @@ var Tiles3DSource = class {
6917
5442
  * @param loadOptions Loader options forwarded to tile requests.
6918
5443
  */
6919
5444
  constructor(input, loadOptions = {}) {
6920
- var _a;
6921
5445
  const request = normalizeTiles3DRequest(input);
6922
5446
  this.rootTileset = isTilesetRequest(input) ? null : input;
6923
5447
  this.tileset = this.rootTileset;
6924
5448
  this.loader = request.loader;
6925
5449
  this.url = request.url;
6926
- this.basePath = request.basePath || path_exports.dirname(request.url);
5450
+ this.basePath = request.basePath || import_loader_utils6.path.dirname(request.url);
6927
5451
  this.resolver = request.resolver;
6928
5452
  this.coreApi = request.coreApi;
6929
5453
  this.loadOptions = loadOptions;
6930
- const maximumCachedSubtrees = Number((_a = loadOptions["3d-tiles"]) == null ? void 0 : _a.maximumCachedSubtrees);
5454
+ const maximumCachedSubtrees = Number(loadOptions["3d-tiles"]?.maximumCachedSubtrees);
6931
5455
  const maximumCacheEntries = Number.isFinite(maximumCachedSubtrees) ? Math.max(0, Math.floor(maximumCachedSubtrees)) : DEFAULT_MAXIMUM_CACHED_SUBTREES;
6932
- this.implicitSubtreeCache = new RequestCache({ maxEntries: maximumCacheEntries });
5456
+ this.implicitSubtreeCache = new import_loader_utils6.RequestCache({ maxEntries: maximumCacheEntries });
6933
5457
  }
6934
5458
  /**
6935
5459
  * Releases URL and parsed-subtree caches and blocks late subtree installation.
@@ -6946,7 +5470,6 @@ var Tiles3DSource = class {
6946
5470
  * Fetches and validates top-level metadata, then normalizes common fields used by {@link Tileset3D}.
6947
5471
  */
6948
5472
  async initialize() {
6949
- var _a;
6950
5473
  if (!this.rootTileset) {
6951
5474
  const loaderOptions = this.loadOptions[this.loader.id] || {};
6952
5475
  this.rootTileset = await this.loadRootData(this.url, {
@@ -6986,7 +5509,7 @@ var Tiles3DSource = class {
6986
5509
  tileset: this.rootTileset,
6987
5510
  lodMetricType: this.rootTileset.lodMetricType,
6988
5511
  lodMetricValue: this.rootTileset.lodMetricValue,
6989
- refine: (_a = this.rootTileset.root) == null ? void 0 : _a.refine,
5512
+ refine: this.rootTileset.root?.refine,
6990
5513
  spatialReference: get3DTilesSpatialReference(this.rootTileset)
6991
5514
  };
6992
5515
  }
@@ -7022,7 +5545,6 @@ var Tiles3DSource = class {
7022
5545
  * Builds explicit runtime headers while leaving implicit subtree references lazy.
7023
5546
  */
7024
5547
  initializeTileHeaders(tileset, tilesetJson, parentTile) {
7025
- var _a;
7026
5548
  const rootHeader = parentTile ? tilesetJson.root : this.preparedRootHeader || tilesetJson.root;
7027
5549
  const rootTile = new Tile3D(tileset, rootHeader, parentTile || void 0);
7028
5550
  if (parentTile) {
@@ -7036,7 +5558,7 @@ var Tiles3DSource = class {
7036
5558
  const children = tile.header.children || [];
7037
5559
  for (const childHeader of children) {
7038
5560
  const childTile = new Tile3D(tileset, childHeader, tile);
7039
- if ((_a = childTile.contentUrl) == null ? void 0 : _a.includes("?session=")) {
5561
+ if (childTile.contentUrl?.includes("?session=")) {
7040
5562
  const url = new URL(childTile.contentUrl);
7041
5563
  const session = url.searchParams.get("session");
7042
5564
  if (session) {
@@ -7060,10 +5582,9 @@ var Tiles3DSource = class {
7060
5582
  * Loads binary content or nested tileset JSON for a runtime tile.
7061
5583
  */
7062
5584
  async loadTileContent(tile) {
7063
- var _a, _b, _c, _d, _e, _f;
7064
5585
  const contentUrls = (tile.contentUrls || [tile.contentUrl]).filter(Boolean);
7065
5586
  const cachedContentHeaders = this.tileContentHeaders.get(tile);
7066
- const contentHeaders = cachedContentHeaders || (Array.isArray((_a = tile.header) == null ? void 0 : _a.content) ? tile.header.content : ((_b = tile.header) == null ? void 0 : _b.content) ? [tile.header.content] : []);
5587
+ const contentHeaders = cachedContentHeaders || (Array.isArray(tile.header?.content) ? tile.header.content : tile.header?.content ? [tile.header.content] : []);
7067
5588
  if (!cachedContentHeaders) {
7068
5589
  this.tileContentHeaders.set(tile, contentHeaders);
7069
5590
  }
@@ -7077,17 +5598,16 @@ var Tiles3DSource = class {
7077
5598
  isTileset: "auto",
7078
5599
  assetGltfUpAxis: this.asset && this.asset.gltfUpAxis || "Y",
7079
5600
  _tilesetOptions: {
7080
- spatialReference: ((_c = tile.header) == null ? void 0 : _c._spatialReference) || ((_d = tile.tileset) == null ? void 0 : _d.spatialReference),
7081
- spatialOptions: (_e = tile.tileset) == null ? void 0 : _e.options.spatial,
7082
- spatialTransform: (_f = tile.header) == null ? void 0 : _f._spatialTransform
5601
+ spatialReference: tile.header?._spatialReference || tile.tileset?.spatialReference,
5602
+ spatialOptions: tile.tileset?.options.spatial,
5603
+ spatialTransform: tile.header?._spatialTransform
7083
5604
  }
7084
5605
  }
7085
5606
  };
7086
5607
  const contents = await Promise.all(contentUrls.map((contentUrl, contentIndex) => {
7087
- var _a2;
7088
5608
  const contentHeader = contentHeaders[contentIndex] || {};
7089
- const vectorExtension = (_a2 = contentHeader.extensions) == null ? void 0 : _a2["3DTILES_content_gltf_vector"];
7090
- const vectorContent = contentHeader._vectorContent || ((vectorExtension == null ? void 0 : vectorExtension.vector) === true ? { clip: vectorExtension.clip === true } : void 0);
5609
+ const vectorExtension = contentHeader.extensions?.["3DTILES_content_gltf_vector"];
5610
+ const vectorContent = contentHeader._vectorContent || (vectorExtension?.vector === true ? { clip: vectorExtension.clip === true } : void 0);
7091
5611
  const contentOptions = vectorContent ? {
7092
5612
  ...options,
7093
5613
  [this.loader.id]: {
@@ -7099,7 +5619,7 @@ var Tiles3DSource = class {
7099
5619
  }));
7100
5620
  tile.contents = contents;
7101
5621
  tile.content = contents[0] || null;
7102
- const nestedTilesets = contents.filter((content) => (content == null ? void 0 : content.shape) === "tileset3d");
5622
+ const nestedTilesets = contents.filter((content) => content?.shape === "tileset3d");
7103
5623
  return {
7104
5624
  loaded: true,
7105
5625
  contents,
@@ -7260,9 +5780,9 @@ var Tiles3DSource = class {
7260
5780
  let cartographicCenter;
7261
5781
  if (center && (center[0] !== 0 || center[1] !== 0 || center[2] !== 0)) {
7262
5782
  cartographicCenter = new import_core12.Vector3();
7263
- import_geospatial10.Ellipsoid.WGS84.cartesianToCartographic(center, cartographicCenter);
5783
+ import_geospatial9.Ellipsoid.WGS84.cartesianToCartographic(center, cartographicCenter);
7264
5784
  } else {
7265
- cartographicCenter = new import_core12.Vector3(0, 0, -import_geospatial10.Ellipsoid.WGS84.radii[0]);
5785
+ cartographicCenter = new import_core12.Vector3(0, 0, -import_geospatial9.Ellipsoid.WGS84.radii[0]);
7266
5786
  }
7267
5787
  return {
7268
5788
  asset: this.asset,
@@ -7288,10 +5808,7 @@ var Tiles3DSource = class {
7288
5808
  */
7289
5809
  onTileLoaded(tileset, tile, loadResult) {
7290
5810
  const contents = tile.contents.length ? tile.contents : [tile.content];
7291
- const extensionsRemoved = contents.flatMap((content) => {
7292
- var _a;
7293
- return ((_a = content == null ? void 0 : content.gltf) == null ? void 0 : _a.extensionsRemoved) || [];
7294
- });
5811
+ const extensionsRemoved = contents.flatMap((content) => content?.gltf?.extensionsRemoved || []);
7295
5812
  if (extensionsRemoved.includes("KHR_draco_mesh_compression")) {
7296
5813
  this.contentFormats.draco = true;
7297
5814
  }
@@ -7328,7 +5845,7 @@ var Tiles3DSource = class {
7328
5845
  prepareNestedTileset(tileset, nestedTileset) {
7329
5846
  const nestedSpatialReference = nestedTileset.spatialMetadata;
7330
5847
  const parentSpatialReference = tileset.spatialReference;
7331
- if ((nestedSpatialReference == null ? void 0 : nestedSpatialReference.status) === "unresolved" || (nestedSpatialReference == null ? void 0 : nestedSpatialReference.crs.state) === "unknown") {
5848
+ if (nestedSpatialReference?.status === "unresolved" || nestedSpatialReference?.crs.state === "unknown") {
7332
5849
  throw new Error(nestedSpatialReference.warnings[0] || "Nested 3D Tiles CRS is explicitly unresolved and cannot be placed in the parent frame");
7333
5850
  }
7334
5851
  if (!nestedSpatialReference || !nestedSpatialReference.sourceCrs) {
@@ -7453,7 +5970,7 @@ var Tiles3DSource = class {
7453
5970
  /** Resolves a retained package-file byte range without eagerly copying other package files. */
7454
5971
  async getPackageFileData(file) {
7455
5972
  if (file.data) {
7456
- return sliceArrayBuffer(file.data, file.byteOffset, file.byteLength);
5973
+ return (0, import_loader_utils6.sliceArrayBuffer)(file.data, file.byteOffset, file.byteLength);
7457
5974
  }
7458
5975
  if (file.bufferUri && this.coreApi) {
7459
5976
  const response = await this.coreApi.fetchFile(this.getTileUrl(file.bufferUri));
@@ -7461,7 +5978,7 @@ var Tiles3DSource = class {
7461
5978
  throw new Error(`Failed to fetch 3D Tiles package buffer: HTTP ${response.status}`);
7462
5979
  }
7463
5980
  const buffer = await response.arrayBuffer();
7464
- return sliceArrayBuffer(buffer, file.byteOffset, file.byteLength);
5981
+ return (0, import_loader_utils6.sliceArrayBuffer)(buffer, file.byteOffset, file.byteLength);
7465
5982
  }
7466
5983
  throw new Error("3D Tiles package file has no available byte source");
7467
5984
  }
@@ -7501,7 +6018,6 @@ var Tiles3DSource = class {
7501
6018
  * @returns Number of newly allocated runtime tile nodes.
7502
6019
  */
7503
6020
  initializeMaterializedChildren(tileset, parentTile, childHeaders) {
7504
- var _a;
7505
6021
  let materializedTileCount = 0;
7506
6022
  const stack = [
7507
6023
  { parentTile, childHeaders }
@@ -7514,7 +6030,7 @@ var Tiles3DSource = class {
7514
6030
  childTile.depth = entry.parentTile.depth + 1;
7515
6031
  tileset.stats.get("Tiles In Tileset(s)").incrementCount();
7516
6032
  materializedTileCount++;
7517
- if ((_a = childHeader.children) == null ? void 0 : _a.length) {
6033
+ if (childHeader.children?.length) {
7518
6034
  stack.push({ parentTile: childTile, childHeaders: childHeader.children });
7519
6035
  }
7520
6036
  }
@@ -7523,7 +6039,7 @@ var Tiles3DSource = class {
7523
6039
  }
7524
6040
  };
7525
6041
  function throwIfTraversalAborted(signal) {
7526
- if (signal == null ? void 0 : signal.aborted) {
6042
+ if (signal?.aborted) {
7527
6043
  throw signal.reason ?? new DOMException("The operation was aborted", "AbortError");
7528
6044
  }
7529
6045
  }
@@ -7534,13 +6050,13 @@ function normalizeTiles3DRequest(input) {
7534
6050
  if (isTilesetRequest(input)) {
7535
6051
  return {
7536
6052
  ...input,
7537
- basePath: input.basePath || path_exports.dirname(input.url)
6053
+ basePath: input.basePath || import_loader_utils6.path.dirname(input.url)
7538
6054
  };
7539
6055
  }
7540
6056
  return {
7541
6057
  url: input.url,
7542
6058
  loader: input.loader,
7543
- basePath: input.basePath || path_exports.dirname(input.url),
6059
+ basePath: input.basePath || import_loader_utils6.path.dirname(input.url),
7544
6060
  resolver: input.resolver,
7545
6061
  coreApi: input.coreApi
7546
6062
  };
@@ -7559,7 +6075,8 @@ function addNestedSpatialReference(nestedTileset, spatialReference) {
7559
6075
  }
7560
6076
 
7561
6077
  // dist/tileset-3d/format-i3s/i3s-source.js
7562
- var import_geospatial12 = require("@math.gl/geospatial");
6078
+ var import_loader_utils7 = require("@loaders.gl/loader-utils");
6079
+ var import_geospatial11 = require("@math.gl/geospatial");
7563
6080
  var import_core14 = require("@math.gl/core");
7564
6081
 
7565
6082
  // dist/tileset-3d/format-i3s/i3s-pending-tiles-register.js
@@ -7596,8 +6113,7 @@ var I3SPendingTilesRegister = class {
7596
6113
  * @returns
7597
6114
  */
7598
6115
  isZero(viewportId, frameNumber) {
7599
- var _a;
7600
- const count = ((_a = this.frameNumberMap.get(viewportId)) == null ? void 0 : _a.get(frameNumber)) || 0;
6116
+ const count = this.frameNumberMap.get(viewportId)?.get(frameNumber) || 0;
7601
6117
  return count === 0;
7602
6118
  }
7603
6119
  };
@@ -7696,10 +6212,7 @@ var I3STilesetTraverser = class extends TilesetTraverser {
7696
6212
  const childTiles = tile.children;
7697
6213
  for (const child of children) {
7698
6214
  const extendedId = `${child.id}-${frameState.viewport.id}`;
7699
- const childTile = childTiles && childTiles.find((t) => {
7700
- var _a;
7701
- return t.id === extendedId || ((_a = t.header) == null ? void 0 : _a.id) === child.id;
7702
- });
6215
+ const childTile = childTiles && childTiles.find((t) => t.id === extendedId || t.header?.id === child.id);
7703
6216
  if (!childTile) {
7704
6217
  const request = () => this._loadTile(tile, child.id, frameState);
7705
6218
  const cachedRequest = this._tileManager.find(extendedId);
@@ -7745,7 +6258,7 @@ var I3STilesetTraverser = class extends TilesetTraverser {
7745
6258
 
7746
6259
  // dist/spatial/i3s-spatial-transformer.js
7747
6260
  var import_core13 = require("@math.gl/core");
7748
- var import_geospatial11 = require("@math.gl/geospatial");
6261
+ var import_geospatial10 = require("@math.gl/geospatial");
7749
6262
  var I3SSpatialTransformer = class {
7750
6263
  /** Descriptor attached to output after all adapter-owned spatial values have been transformed. */
7751
6264
  spatialReference;
@@ -7778,7 +6291,6 @@ var I3SSpatialTransformer = class {
7778
6291
  * @param options - Registered geoid and custom resource options used by the shared transformer.
7779
6292
  */
7780
6293
  constructor(spatialReference, options = {}) {
7781
- var _a;
7782
6294
  if (spatialReference.status !== "transformable" && spatialReference.status !== "transformed") {
7783
6295
  throw new Error("I3SSpatialTransformer requires a requested, transformable spatial output");
7784
6296
  }
@@ -7795,7 +6307,7 @@ var I3SSpatialTransformer = class {
7795
6307
  if (this.elevationProvider && (typeof this.elevationProvider.sampleElevations !== "function" || typeof this.elevationProvider.getElevationRange !== "function")) {
7796
6308
  throw new Error("An I3S elevation provider must implement sampleElevations() and getElevationRange()");
7797
6309
  }
7798
- const providerUnitScale = getI3SLinearUnitScale(((_a = this.elevationProvider) == null ? void 0 : _a.unit) || "meter");
6310
+ const providerUnitScale = getI3SLinearUnitScale(this.elevationProvider?.unit || "meter");
7799
6311
  if (this.elevationProvider && providerUnitScale === void 0) {
7800
6312
  throw new Error(`Unsupported elevation-provider unit ${this.elevationProvider.unit}`);
7801
6313
  }
@@ -7924,6 +6436,32 @@ var I3SSpatialTransformer = class {
7924
6436
  const placedPositions = await this.placeSourcePositions(combinedPositions);
7925
6437
  return this.transformPlacedPositions(placedPositions.subarray(0, sourcePositions.length), placedPositions.subarray(sourcePositions.length));
7926
6438
  }
6439
+ /**
6440
+ * Transforms conversion geometry without passing through renderer float32 offsets.
6441
+ * Positions and normals share one batch of elevation samples. Source arrays remain unchanged.
6442
+ * @param sourcePositions - Packed absolute xyz positions in source units.
6443
+ * @param normals - Optional packed normals paired with the positions.
6444
+ * @param normalReferenceFrame - I3S earth-centered or vertex-reference-frame declaration.
6445
+ * @returns Absolute target positions and optional transformed normals.
6446
+ */
6447
+ async transformGeometryAsync(sourcePositions, normals, normalReferenceFrame = "earth-centered") {
6448
+ if (sourcePositions.length % 3 || normals && normals.length !== sourcePositions.length) {
6449
+ throw new Error("Conversion positions and normals must contain matching finite xyz triples");
6450
+ }
6451
+ for (let index = 0; index < sourcePositions.length; index++) {
6452
+ if (!Number.isFinite(sourcePositions[index]) || normals && !Number.isFinite(normals[index])) {
6453
+ throw new Error("Conversion positions and normals must contain matching finite xyz triples");
6454
+ }
6455
+ }
6456
+ if (!["earth-centered", "vertex-reference-frame"].includes(normalReferenceFrame)) {
6457
+ throw new Error("Unsupported I3S normal reference frame");
6458
+ }
6459
+ const placedPositions = await this.placeSourcePositions(sourcePositions);
6460
+ return {
6461
+ positions: this.positionTransformer.transformPositions(placedPositions),
6462
+ normals: normals ? this.transformNormals(normals, placedPositions, normalReferenceFrame) : void 0
6463
+ };
6464
+ }
7927
6465
  /** Transform already placed positions into renderer-relative target coordinates. */
7928
6466
  transformPlacedPositions(sourcePositions, sourceOrigin) {
7929
6467
  const origin = this.transformPlacedPosition(sourceOrigin);
@@ -7961,7 +6499,19 @@ var I3SSpatialTransformer = class {
7961
6499
  * @param normalReferenceFrame - I3S normal frame declaration.
7962
6500
  */
7963
6501
  transformNormals(normals, sourcePositions, normalReferenceFrame = "earth-centered") {
6502
+ if (normals.length !== sourcePositions.length || normals.length % 3) {
6503
+ throw new Error("I3S normals and positions must have matching xyz component counts");
6504
+ }
7964
6505
  const transformedNormals = new Float32Array(normals.length);
6506
+ if (normalReferenceFrame === "earth-centered" && (this.spatialReference.targetCrs || this.spatialReference.sourceCrs) === "EPSG:4978") {
6507
+ for (let index = 0; index < normals.length; index += 3) {
6508
+ const length = Math.hypot(normals[index], normals[index + 1], normals[index + 2]);
6509
+ for (let axis = 0; axis < 3; axis++) {
6510
+ transformedNormals[index + axis] = length ? normals[index + axis] / length : normals[index + axis];
6511
+ }
6512
+ }
6513
+ return transformedNormals;
6514
+ }
7965
6515
  for (let index = 0; index < normals.length; index += 3) {
7966
6516
  const geographic = this.sourceToGeographicTransformer.transformPosition([
7967
6517
  sourcePositions[index],
@@ -8006,24 +6556,23 @@ var I3SSpatialTransformer = class {
8006
6556
  }
8007
6557
  /** Rebuild an I3S bound as a WGS84 ECEF box for generic `Tileset3D` traversal. */
8008
6558
  transformBoundingVolumeToGeocentric(bounds) {
8009
- const cartesianSamples = this.getGeographicBoundSamples(bounds).map((position) => Array.from(import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position))));
6559
+ const cartesianSamples = this.getGeographicBoundSamples(bounds).map((position) => Array.from(import_geospatial10.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position))));
8010
6560
  return { box: getAxisAlignedBox(cartesianSamples) };
8011
6561
  }
8012
6562
  /** Rebuild an I3S bound as WGS84 ECEF after asynchronous elevation placement. */
8013
6563
  async transformBoundingVolumeToGeocentricAsync(bounds) {
8014
- const cartesianSamples = (await this.getGeographicBoundSamplesAsync(bounds)).map((position) => Array.from(import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position))));
6564
+ const cartesianSamples = (await this.getGeographicBoundSamplesAsync(bounds)).map((position) => Array.from(import_geospatial10.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position))));
8015
6565
  return { box: getAxisAlignedBox(cartesianSamples) };
8016
6566
  }
8017
6567
  /** Return a WGS84 geographic MBS used by the I3S screen-threshold calculation. */
8018
6568
  transformBoundingSphereToGeographic(bounds) {
8019
- var _a, _b;
8020
- const sourceCenter = ((_a = bounds.mbs) == null ? void 0 : _a.length) ? Array.from(bounds.mbs).slice(0, 3) : bounds.obb ? Array.from(bounds.obb.center).slice(0, 3) : null;
6569
+ const sourceCenter = bounds.mbs?.length ? Array.from(bounds.mbs).slice(0, 3) : bounds.obb ? Array.from(bounds.obb.center).slice(0, 3) : null;
8021
6570
  if (!sourceCenter) {
8022
6571
  throw new Error("I3S spatial transformation requires an MBS or OBB bound");
8023
6572
  }
8024
6573
  const placedCenter = this.placeSourcePositionsSync(sourceCenter);
8025
6574
  const geographicCenter = this.sourceToGeographicTransformer.transformPosition(Array.from(placedCenter));
8026
- const radius = ((_b = bounds.mbs) == null ? void 0 : _b.length) ? bounds.mbs[3] : Math.hypot(...Array.from(bounds.obb.halfSize).slice(0, 3));
6575
+ const radius = bounds.mbs?.length ? bounds.mbs[3] : Math.hypot(...Array.from(bounds.obb.halfSize).slice(0, 3));
8027
6576
  return [geographicCenter[0], geographicCenter[1], geographicCenter[2], radius];
8028
6577
  }
8029
6578
  /** Return a placed WGS84 MBS used by the I3S screen-threshold calculation. */
@@ -8038,7 +6587,7 @@ var I3SSpatialTransformer = class {
8038
6587
  */
8039
6588
  async transformBoundsAsync(bounds) {
8040
6589
  const geographicSamples = await this.getGeographicBoundSamplesAsync(bounds);
8041
- const cartesianSamples = geographicSamples.map((position) => Array.from(import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position))));
6590
+ const cartesianSamples = geographicSamples.map((position) => Array.from(import_geospatial10.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position))));
8042
6591
  const targetSamples = geographicSamples.map((position) => this.geographicToTargetTransformer.transformPosition(position));
8043
6592
  return {
8044
6593
  boundingVolume: { box: getAxisAlignedBox(cartesianSamples) },
@@ -8161,11 +6710,11 @@ var I3SSpatialTransformer = class {
8161
6710
  if (this.targetCoordinateFrame === "geographic") {
8162
6711
  return ecefVectorToLocalEnu(ecefNormal, geographic).normalize();
8163
6712
  }
8164
- const cartesian = import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(geographic));
6713
+ const cartesian = import_geospatial10.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(geographic));
8165
6714
  const jacobianColumns = [];
8166
6715
  for (const direction of getPositiveAxisDirections()) {
8167
- const positiveGeographic = import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(new import_core13.Vector3(cartesian).add(direction));
8168
- const negativeGeographic = import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(new import_core13.Vector3(cartesian).subtract(direction));
6716
+ const positiveGeographic = import_geospatial10.Ellipsoid.WGS84.cartesianToCartographic(new import_core13.Vector3(cartesian).add(direction));
6717
+ const negativeGeographic = import_geospatial10.Ellipsoid.WGS84.cartesianToCartographic(new import_core13.Vector3(cartesian).subtract(direction));
8169
6718
  const positiveTarget = this.geographicToTargetTransformer.transformPosition(positiveGeographic);
8170
6719
  const negativeTarget = this.geographicToTargetTransformer.transformPosition(negativeGeographic);
8171
6720
  jacobianColumns.push((positiveTarget[0] - negativeTarget[0]) / 2, (positiveTarget[1] - negativeTarget[1]) / 2, (positiveTarget[2] - negativeTarget[2]) / 2);
@@ -8207,7 +6756,7 @@ function getGeographicBoundingSphere(geographicSamples) {
8207
6756
  if (!geographicSamples.length) {
8208
6757
  throw new Error("I3S spatial transformation requires at least one bound sample");
8209
6758
  }
8210
- const cartesianSamples = geographicSamples.map((position) => import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position)));
6759
+ const cartesianSamples = geographicSamples.map((position) => import_geospatial10.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position)));
8211
6760
  const cartesianCenter = new import_core13.Vector3();
8212
6761
  for (const sample of cartesianSamples) {
8213
6762
  cartesianCenter.add(sample);
@@ -8217,7 +6766,7 @@ function getGeographicBoundingSphere(geographicSamples) {
8217
6766
  for (const sample of cartesianSamples) {
8218
6767
  radius = Math.max(radius, new import_core13.Vector3(sample).subtract(cartesianCenter).magnitude());
8219
6768
  }
8220
- const geographicCenter = import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(cartesianCenter);
6769
+ const geographicCenter = import_geospatial10.Ellipsoid.WGS84.cartesianToCartographic(cartesianCenter);
8221
6770
  return [geographicCenter[0], geographicCenter[1], geographicCenter[2], radius];
8222
6771
  }
8223
6772
  function getSourceBoundSamples(bounds, sourceFrame, sourceToGeographicTransformer, sourceVerticalUnitScale) {
@@ -8234,14 +6783,14 @@ function getSourceBoundSamples(bounds, sourceFrame, sourceToGeographicTransforme
8234
6783
  ];
8235
6784
  if (sourceFrame === "geographic") {
8236
6785
  const geographicCenter = sourceToGeographicTransformer.transformPosition(center2);
8237
- const cartesianCenter = import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(geographicCenter));
6786
+ const cartesianCenter = import_geospatial10.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(geographicCenter));
8238
6787
  const cartesianAxes = bounds.normalReferenceFrame === "vertex-reference-frame" ? axes.map((axis) => localEnuVectorToEcef(axis, geographicCenter)) : axes;
8239
6788
  return getBoxSigns().map((signs) => {
8240
6789
  const corner = new import_core13.Vector3(cartesianCenter);
8241
6790
  for (let axisIndex = 0; axisIndex < 3; axisIndex++) {
8242
6791
  corner.add(new import_core13.Vector3(cartesianAxes[axisIndex]).scale(signs[axisIndex]));
8243
6792
  }
8244
- return Array.from(import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(corner));
6793
+ return Array.from(import_geospatial10.Ellipsoid.WGS84.cartesianToCartographic(corner));
8245
6794
  });
8246
6795
  }
8247
6796
  return getBoxSigns().map((signs) => {
@@ -8261,8 +6810,8 @@ function getSourceBoundSamples(bounds, sourceFrame, sourceToGeographicTransforme
8261
6810
  const radius = mbs[3];
8262
6811
  if (sourceFrame === "geographic") {
8263
6812
  const geographicCenter = sourceToGeographicTransformer.transformPosition(center);
8264
- const cartesianCenter = import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(geographicCenter));
8265
- return getAxisDirections().map((direction) => Array.from(import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(new import_core13.Vector3(cartesianCenter).add(new import_core13.Vector3(direction).scale(radius)))));
6813
+ const cartesianCenter = import_geospatial10.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(geographicCenter));
6814
+ return getAxisDirections().map((direction) => Array.from(import_geospatial10.Ellipsoid.WGS84.cartesianToCartographic(new import_core13.Vector3(cartesianCenter).add(new import_core13.Vector3(direction).scale(radius)))));
8266
6815
  }
8267
6816
  return getAxisDirections().map((direction) => Array.from(new import_core13.Vector3(center).add(new import_core13.Vector3(direction).scale(radius))));
8268
6817
  }
@@ -8407,7 +6956,7 @@ var I3SSource = class {
8407
6956
  this.loader = request.loader;
8408
6957
  this.contentLoader = getI3SContentLoader(request.loader);
8409
6958
  this.url = request.url;
8410
- this.basePath = request.basePath || path_exports.dirname(request.url);
6959
+ this.basePath = request.basePath || import_loader_utils7.path.dirname(request.url);
8411
6960
  this.resolver = request.resolver;
8412
6961
  this.coreApi = request.coreApi;
8413
6962
  this.loadOptions = loadOptions;
@@ -8417,7 +6966,6 @@ var I3SSource = class {
8417
6966
  * Fetches and normalizes root I3S metadata for runtime consumption.
8418
6967
  */
8419
6968
  async initialize() {
8420
- var _a;
8421
6969
  if (!this.rootTileset) {
8422
6970
  this.rootTileset = await this.loadRootData(this.getTileUrl(this.url), {
8423
6971
  ...this.loadOptions,
@@ -8436,7 +6984,7 @@ var I3SSource = class {
8436
6984
  tileset: this.rootTileset,
8437
6985
  lodMetricType: this.rootTileset.lodMetricType,
8438
6986
  lodMetricValue: this.rootTileset.lodMetricValue,
8439
- refine: (_a = this.rootTileset.root) == null ? void 0 : _a.refine,
6987
+ refine: this.rootTileset.root?.refine,
8440
6988
  spatialReference: getI3SSpatialReference(this.rootTileset)
8441
6989
  };
8442
6990
  }
@@ -8570,10 +7118,7 @@ var I3SSource = class {
8570
7118
  if (typeof childId !== "string" && typeof childId !== "number") {
8571
7119
  throw new Error("I3S child header is missing its node ID");
8572
7120
  }
8573
- const existingChild = parentTile.children.find((tile) => {
8574
- var _a;
8575
- return tile.id === String(childId) || ((_a = tile.header) == null ? void 0 : _a.id) === childId;
8576
- });
7121
+ const existingChild = parentTile.children.find((tile) => tile.id === String(childId) || tile.header?.id === childId);
8577
7122
  if (existingChild) {
8578
7123
  orderedChildren.push(existingChild);
8579
7124
  continue;
@@ -8605,7 +7150,7 @@ var I3SSource = class {
8605
7150
  const hash = hashIndex >= 0 ? tilePath.slice(hashIndex) : "";
8606
7151
  const tilePathWithoutHash = hashIndex >= 0 ? tilePath.slice(0, hashIndex) : tilePath;
8607
7152
  const queryDelimiterIndex = tilePathWithoutHash.indexOf("?");
8608
- const path = queryDelimiterIndex === -1 ? tilePathWithoutHash : tilePathWithoutHash.slice(0, queryDelimiterIndex);
7153
+ const path4 = queryDelimiterIndex === -1 ? tilePathWithoutHash : tilePathWithoutHash.slice(0, queryDelimiterIndex);
8609
7154
  const existingQuery = queryDelimiterIndex === -1 ? "" : tilePathWithoutHash.slice(queryDelimiterIndex + 1);
8610
7155
  const existingQueryParams = new URLSearchParams(existingQuery);
8611
7156
  const queryParams = new URLSearchParams();
@@ -8615,13 +7160,12 @@ var I3SSource = class {
8615
7160
  }
8616
7161
  }
8617
7162
  const queryString = queryParams.toString();
8618
- return `${path}${existingQuery ? `?${existingQuery}` : ""}${queryString ? `${existingQuery ? "&" : "?"}${queryString}` : ""}${hash}`;
7163
+ return `${path4}${existingQuery ? `?${existingQuery}` : ""}${queryString ? `${existingQuery ? "&" : "?"}${queryString}` : ""}${hash}`;
8619
7164
  }
8620
7165
  /**
8621
7166
  * Derives the default view state from full extent or store extent metadata.
8622
7167
  */
8623
7168
  getViewState(rootTile) {
8624
- var _a;
8625
7169
  if (this.spatialTransformer && rootTile) {
8626
7170
  const center = new import_core14.Vector3(rootTile.boundingVolume.center);
8627
7171
  const cartographicCenter = new import_core14.Vector3(rootTile.header.i3sLodMbs.slice(0, 3));
@@ -8646,19 +7190,19 @@ var I3SSource = class {
8646
7190
  const { xmin, xmax, ymin, ymax, zmin, zmax } = fullExtent;
8647
7191
  const cartographicCenter = new import_core14.Vector3(xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2, zmin + (zmax - zmin) / 2);
8648
7192
  const cartesianCenter = new import_core14.Vector3();
8649
- import_geospatial12.Ellipsoid.WGS84.cartographicToCartesian(cartographicCenter, cartesianCenter);
7193
+ import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(cartographicCenter, cartesianCenter);
8650
7194
  return {
8651
7195
  cartographicCenter,
8652
7196
  cartesianCenter,
8653
7197
  zoom: getZoomFromFullExtent(fullExtent, cartographicCenter, cartesianCenter)
8654
7198
  };
8655
7199
  }
8656
- const extent = (_a = metadata.tileset.store) == null ? void 0 : _a.extent;
7200
+ const extent = metadata.tileset.store?.extent;
8657
7201
  if (extent) {
8658
7202
  const [xmin, ymin, xmax, ymax] = extent;
8659
7203
  const cartographicCenter = new import_core14.Vector3(xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2, 0);
8660
7204
  const cartesianCenter = new import_core14.Vector3();
8661
- import_geospatial12.Ellipsoid.WGS84.cartographicToCartesian(cartographicCenter, cartesianCenter);
7205
+ import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(cartographicCenter, cartesianCenter);
8662
7206
  return {
8663
7207
  cartographicCenter,
8664
7208
  cartesianCenter,
@@ -8692,9 +7236,8 @@ var I3SSource = class {
8692
7236
  * Returns the total number of known tiles when node pages metadata is available.
8693
7237
  */
8694
7238
  getTilesTotalCount() {
8695
- var _a, _b;
8696
7239
  const metadata = this.getMetadata();
8697
- return ((_b = (_a = metadata.tileset) == null ? void 0 : _a.nodePagesTile) == null ? void 0 : _b.nodesInNodePages) || null;
7240
+ return metadata.tileset?.nodePagesTile?.nodesInNodePages || null;
8698
7241
  }
8699
7242
  /**
8700
7243
  * Loads data through injected core APIs so this module stays independent from `@loaders.gl/core`.
@@ -8741,14 +7284,13 @@ var I3SSource = class {
8741
7284
  }
8742
7285
  /** Transform one I3S header bound after target options and elevation providers are available. */
8743
7286
  async transformTileHeader(header) {
8744
- var _a;
8745
7287
  if (!this.spatialTransformer) {
8746
7288
  return header;
8747
7289
  }
8748
7290
  const sourceBounds = {
8749
7291
  mbs: header.mbs,
8750
7292
  obb: header.obb,
8751
- normalReferenceFrame: (_a = this.getMetadata().tileset.store) == null ? void 0 : _a.normalReferenceFrame
7293
+ normalReferenceFrame: this.getMetadata().tileset.store?.normalReferenceFrame
8752
7294
  };
8753
7295
  const transformedBounds = await this.spatialTransformer.transformBoundsAsync(sourceBounds);
8754
7296
  return {
@@ -8762,7 +7304,7 @@ var I3SSource = class {
8762
7304
  }
8763
7305
  };
8764
7306
  function throwIfTraversalAborted2(signal) {
8765
- if (signal == null ? void 0 : signal.aborted) {
7307
+ if (signal?.aborted) {
8766
7308
  throw signal.reason ?? new DOMException("The operation was aborted", "AbortError");
8767
7309
  }
8768
7310
  }
@@ -8776,13 +7318,13 @@ function normalizeI3SRequest(input) {
8776
7318
  if (isTilesetRequest2(input)) {
8777
7319
  return {
8778
7320
  ...input,
8779
- basePath: input.basePath || path_exports.dirname(input.url)
7321
+ basePath: input.basePath || import_loader_utils7.path.dirname(input.url)
8780
7322
  };
8781
7323
  }
8782
7324
  return {
8783
7325
  url: input.url,
8784
7326
  loader: input.loader,
8785
- basePath: input.basePath || path_exports.dirname(input.url),
7327
+ basePath: input.basePath || import_loader_utils7.path.dirname(input.url),
8786
7328
  resolver: input.resolver,
8787
7329
  coreApi: input.coreApi
8788
7330
  };
@@ -8945,12 +7487,11 @@ var SharedTile2DHeader = class {
8945
7487
  }
8946
7488
  /** Cancels an in-flight tile request. */
8947
7489
  abort() {
8948
- var _a;
8949
7490
  if (this.isLoaded) {
8950
7491
  return;
8951
7492
  }
8952
7493
  this._isCancelled = true;
8953
- (_a = this._abortController) == null ? void 0 : _a.abort();
7494
+ this._abortController?.abort();
8954
7495
  }
8955
7496
  };
8956
7497
  function normalizeTileError(error) {
@@ -8964,7 +7505,7 @@ function normalizeTileError(error) {
8964
7505
  }
8965
7506
 
8966
7507
  // dist/tileset-2d/tileset-2d.js
8967
- var import_stats4 = require("@probe.gl/stats");
7508
+ var import_loader_utils8 = require("@loaders.gl/loader-utils");
8968
7509
  var STRATEGY_NEVER = "never";
8969
7510
  var STRATEGY_REPLACE = "no-overlap";
8970
7511
  var STRATEGY_DEFAULT = "best-available";
@@ -9011,7 +7552,7 @@ var Tileset2D = class _Tileset2D {
9011
7552
  _lastTileContext = null;
9012
7553
  /** Creates a tileset from either `getTileData` or a loaders.gl `TileSource`. */
9013
7554
  constructor(opts) {
9014
- this.stats = new import_stats4.Stats({
7555
+ this.stats = new Stats({
9015
7556
  id: "Tileset2D",
9016
7557
  stats: [
9017
7558
  { name: "Tiles In Cache" },
@@ -9029,7 +7570,7 @@ var Tileset2D = class _Tileset2D {
9029
7570
  getTileData: opts.getTileData || (() => null),
9030
7571
  tileSource: opts.tileSource
9031
7572
  };
9032
- this._requestScheduler = new RequestScheduler({
7573
+ this._requestScheduler = new import_loader_utils8.RequestScheduler({
9033
7574
  throttleRequests: this.opts.maxRequests > 0 || this.opts.debounceTime > 0,
9034
7575
  maxRequests: this.opts.maxRequests,
9035
7576
  debounceTime: this.opts.debounceTime
@@ -9122,7 +7663,7 @@ var Tileset2D = class _Tileset2D {
9122
7663
  const previousDebounceTime = this.opts.debounceTime;
9123
7664
  this._applyResolvedOptions();
9124
7665
  if (previousMaxRequests !== this.opts.maxRequests || previousDebounceTime !== this.opts.debounceTime) {
9125
- this._requestScheduler = new RequestScheduler({
7666
+ this._requestScheduler = new import_loader_utils8.RequestScheduler({
9126
7667
  throttleRequests: this.opts.maxRequests > 0 || this.opts.debounceTime > 0,
9127
7668
  maxRequests: this.opts.maxRequests,
9128
7669
  debounceTime: this.opts.debounceTime
@@ -9306,51 +7847,45 @@ var Tileset2D = class _Tileset2D {
9306
7847
  }
9307
7848
  /** Handles successful tile loads. */
9308
7849
  _handleTileLoad(tile) {
9309
- var _a, _b, _c;
9310
- (_b = (_a = this.opts).onTileLoad) == null ? void 0 : _b.call(_a, tile);
7850
+ this.opts.onTileLoad?.(tile);
9311
7851
  this._cacheByteSize = this._getCacheByteSize();
9312
7852
  this._resizeCache();
9313
7853
  for (const listener of this._listeners) {
9314
- (_c = listener.onTileLoad) == null ? void 0 : _c.call(listener, tile);
7854
+ listener.onTileLoad?.(tile);
9315
7855
  }
9316
7856
  this._updateStats();
9317
7857
  }
9318
7858
  /** Handles tile load failures. */
9319
7859
  _handleTileError(error, tile) {
9320
- var _a, _b, _c;
9321
- (_b = (_a = this.opts).onTileError) == null ? void 0 : _b.call(_a, error, tile);
7860
+ this.opts.onTileError?.(error, tile);
9322
7861
  for (const listener of this._listeners) {
9323
- (_c = listener.onTileError) == null ? void 0 : _c.call(listener, error, tile);
7862
+ listener.onTileError?.(error, tile);
9324
7863
  }
9325
7864
  this._updateStats();
9326
7865
  }
9327
7866
  /** Handles tile eviction from cache. */
9328
7867
  _handleTileUnload(tile) {
9329
- var _a, _b, _c;
9330
7868
  this._unloadedTileCount++;
9331
- (_b = (_a = this.opts).onTileUnload) == null ? void 0 : _b.call(_a, tile);
7869
+ this.opts.onTileUnload?.(tile);
9332
7870
  for (const listener of this._listeners) {
9333
- (_c = listener.onTileUnload) == null ? void 0 : _c.call(listener, tile);
7871
+ listener.onTileUnload?.(tile);
9334
7872
  }
9335
7873
  this._updateStats();
9336
7874
  }
9337
7875
  /** Notifies listeners that metadata or effective options changed. */
9338
7876
  _notifyUpdate() {
9339
- var _a;
9340
7877
  for (const listener of this._listeners) {
9341
- (_a = listener.onUpdate) == null ? void 0 : _a.call(listener);
7878
+ listener.onUpdate?.();
9342
7879
  }
9343
7880
  }
9344
7881
  /** Notifies listeners about asynchronous metadata errors. */
9345
7882
  _notifyError(error) {
9346
- var _a;
9347
7883
  for (const listener of this._listeners) {
9348
- (_a = listener.onError) == null ? void 0 : _a.call(listener, error);
7884
+ listener.onError?.(error);
9349
7885
  }
9350
7886
  }
9351
7887
  /** Recomputes absolute counter stats and notifies listeners. */
9352
7888
  _updateStats() {
9353
- var _a;
9354
7889
  this._setStatCount("Tiles In Cache", this._cache.size);
9355
7890
  this._setStatCount("Cache Size", this.cacheByteSize);
9356
7891
  this._setStatCount("Visible Tiles", this.visibleTiles.length);
@@ -9359,7 +7894,7 @@ var Tileset2D = class _Tileset2D {
9359
7894
  this._setStatCount("Unloaded Tiles", this._unloadedTileCount);
9360
7895
  this._setStatCount("Consumers", this._consumers.size);
9361
7896
  for (const listener of this._listeners) {
9362
- (_a = listener.onStatsChange) == null ? void 0 : _a.call(listener, this.stats);
7897
+ listener.onStatsChange?.(this.stats);
9363
7898
  }
9364
7899
  }
9365
7900
  /** Writes an absolute count into a probe.gl stat. */
@@ -9433,7 +7968,7 @@ var Tileset2D = class _Tileset2D {
9433
7968
  for (const tile of this._cache.values()) {
9434
7969
  const parent = this._getNearestAncestor(tile);
9435
7970
  tile.parent = parent;
9436
- if (parent == null ? void 0 : parent.children) {
7971
+ if (parent?.children) {
9437
7972
  parent.children.push(tile);
9438
7973
  }
9439
7974
  }
@@ -9521,8 +8056,7 @@ var ImageSet = class _ImageSet {
9521
8056
  }
9522
8057
  /** Current accepted image, if any. */
9523
8058
  get image() {
9524
- var _a;
9525
- return ((_a = this._currentRequest) == null ? void 0 : _a.image) || null;
8059
+ return this._currentRequest?.image || null;
9526
8060
  }
9527
8061
  /** Current accepted request and image payload, if any. */
9528
8062
  get currentRequest() {
@@ -9554,7 +8088,6 @@ var ImageSet = class _ImageSet {
9554
8088
  }
9555
8089
  /** Loads metadata from the current image source or callbacks. */
9556
8090
  async loadMetadata() {
9557
- var _a, _b;
9558
8091
  this._startLoading();
9559
8092
  try {
9560
8093
  const metadata = await this._opts.getMetadata();
@@ -9563,7 +8096,7 @@ var ImageSet = class _ImageSet {
9563
8096
  }
9564
8097
  this.metadata = metadata;
9565
8098
  for (const listener of this._listeners) {
9566
- (_a = listener.onMetadataLoad) == null ? void 0 : _a.call(listener, metadata);
8099
+ listener.onMetadataLoad?.(metadata);
9567
8100
  }
9568
8101
  this._emitUpdate();
9569
8102
  return metadata;
@@ -9571,7 +8104,7 @@ var ImageSet = class _ImageSet {
9571
8104
  const normalizedError = normalizeImageSetError(error, "Image metadata request failed");
9572
8105
  if (!this._finalized) {
9573
8106
  for (const listener of this._listeners) {
9574
- (_b = listener.onMetadataLoadError) == null ? void 0 : _b.call(listener, normalizedError);
8107
+ listener.onMetadataLoadError?.(normalizedError);
9575
8108
  }
9576
8109
  }
9577
8110
  throw normalizedError;
@@ -9603,13 +8136,12 @@ var ImageSet = class _ImageSet {
9603
8136
  }
9604
8137
  /** Loads an image immediately and accepts it only if it is the newest completed request. */
9605
8138
  async _loadImage(requestId, parameters) {
9606
- var _a, _b, _c, _d;
9607
8139
  if (this._finalized) {
9608
8140
  return;
9609
8141
  }
9610
8142
  this._startLoading();
9611
8143
  for (const listener of this._listeners) {
9612
- (_a = listener.onImageLoadStart) == null ? void 0 : _a.call(listener, requestId, parameters);
8144
+ listener.onImageLoadStart?.(requestId, parameters);
9613
8145
  }
9614
8146
  try {
9615
8147
  const abortController = new AbortController();
@@ -9621,21 +8153,21 @@ var ImageSet = class _ImageSet {
9621
8153
  this._lastAcceptedRequestId = requestId;
9622
8154
  this._currentRequest = { requestId, parameters, image };
9623
8155
  for (const listener of this._listeners) {
9624
- (_b = listener.onImageLoad) == null ? void 0 : _b.call(listener, this._currentRequest);
8156
+ listener.onImageLoad?.(this._currentRequest);
9625
8157
  }
9626
8158
  this._emitUpdate();
9627
8159
  } catch (error) {
9628
- if (isAbortError2(error)) {
8160
+ if (isAbortError(error)) {
9629
8161
  return;
9630
8162
  }
9631
8163
  const normalizedError = normalizeImageSetError(error, "Image request failed");
9632
8164
  if (!this._finalized) {
9633
8165
  for (const listener of this._listeners) {
9634
- (_c = listener.onImageLoadError) == null ? void 0 : _c.call(listener, requestId, normalizedError, parameters);
8166
+ listener.onImageLoadError?.(requestId, normalizedError, parameters);
9635
8167
  }
9636
8168
  }
9637
8169
  } finally {
9638
- if (((_d = this._abortController) == null ? void 0 : _d.signal) === parameters.signal) {
8170
+ if (this._abortController?.signal === parameters.signal) {
9639
8171
  this._abortController = null;
9640
8172
  }
9641
8173
  this._finishLoading();
@@ -9665,9 +8197,8 @@ var ImageSet = class _ImageSet {
9665
8197
  }
9666
8198
  /** Notifies listeners that current metadata or image output changed. */
9667
8199
  _emitUpdate() {
9668
- var _a;
9669
8200
  for (const listener of this._listeners) {
9670
- (_a = listener.onUpdate) == null ? void 0 : _a.call(listener);
8201
+ listener.onUpdate?.();
9671
8202
  }
9672
8203
  }
9673
8204
  /** Increments the active load count and emits loading changes. */
@@ -9690,9 +8221,8 @@ var ImageSet = class _ImageSet {
9690
8221
  }
9691
8222
  /** Notifies listeners when the overall loading state changes. */
9692
8223
  _emitLoadingStateChange(isLoading) {
9693
- var _a;
9694
8224
  for (const listener of this._listeners) {
9695
- (_a = listener.onLoadingStateChange) == null ? void 0 : _a.call(listener, isLoading);
8225
+ listener.onLoadingStateChange?.(isLoading);
9696
8226
  }
9697
8227
  }
9698
8228
  /** Clears any pending debounced image request. */
@@ -9704,12 +8234,11 @@ var ImageSet = class _ImageSet {
9704
8234
  }
9705
8235
  /** Aborts the current in-flight image request, if any. */
9706
8236
  _abortActiveRequest() {
9707
- var _a;
9708
- (_a = this._abortController) == null ? void 0 : _a.abort();
8237
+ this._abortController?.abort();
9709
8238
  this._abortController = null;
9710
8239
  }
9711
8240
  };
9712
- function isAbortError2(error) {
8241
+ function isAbortError(error) {
9713
8242
  return error instanceof Error && error.name === "AbortError";
9714
8243
  }
9715
8244
  function normalizeImageSetError(error, message) {
@@ -9723,6 +8252,7 @@ function normalizeImageSetError(error, message) {
9723
8252
  }
9724
8253
 
9725
8254
  // dist/raster-set.js
8255
+ var import_loader_utils9 = require("@loaders.gl/loader-utils");
9726
8256
  var DEFAULT_RASTERSET_PROPS = {
9727
8257
  getMetadata: async () => ({
9728
8258
  width: 0,
@@ -9778,8 +8308,7 @@ var RasterSet = class _RasterSet {
9778
8308
  }
9779
8309
  /** Current accepted raster, if any. */
9780
8310
  get raster() {
9781
- var _a;
9782
- return ((_a = this._currentRequest) == null ? void 0 : _a.raster) || null;
8311
+ return this._currentRequest?.raster || null;
9783
8312
  }
9784
8313
  /** Current accepted request and raster payload, if any. */
9785
8314
  get currentRequest() {
@@ -9796,7 +8325,6 @@ var RasterSet = class _RasterSet {
9796
8325
  }
9797
8326
  /** Updates source callbacks or debounce settings, resetting state when the source changes. */
9798
8327
  setOptions(opts) {
9799
- var _a;
9800
8328
  const previousRasterSource = this._opts.rasterSource;
9801
8329
  const mergedOptions = { ...this._opts, ...opts };
9802
8330
  if (opts.rasterSource && opts.rasterSource !== previousRasterSource) {
@@ -9809,7 +8337,7 @@ var RasterSet = class _RasterSet {
9809
8337
  if (sourceChanged) {
9810
8338
  this._cancelScheduledRaster();
9811
8339
  this._abortActiveRequest();
9812
- (_a = this._metadataAbortController) == null ? void 0 : _a.abort();
8340
+ this._metadataAbortController?.abort();
9813
8341
  this._sourceGeneration++;
9814
8342
  this.metadata = null;
9815
8343
  this._currentRequest = null;
@@ -9818,48 +8346,44 @@ var RasterSet = class _RasterSet {
9818
8346
  }
9819
8347
  /** Loads metadata from the current raster source or callbacks. */
9820
8348
  async loadMetadata(options = {}) {
9821
- var _a, _b, _c, _d, _e, _f;
9822
8349
  if (this._finalized)
9823
8350
  throw new Error("RasterSet is finalized");
9824
- (_a = options.signal) == null ? void 0 : _a.throwIfAborted();
9825
- (_b = this._metadataAbortController) == null ? void 0 : _b.abort();
8351
+ options.signal?.throwIfAborted();
8352
+ this._metadataAbortController?.abort();
9826
8353
  const abortController = new AbortController();
9827
8354
  this._metadataAbortController = abortController;
9828
- const abortFromCaller = () => {
9829
- var _a2;
9830
- return abortController.abort((_a2 = options.signal) == null ? void 0 : _a2.reason);
9831
- };
9832
- (_c = options.signal) == null ? void 0 : _c.addEventListener("abort", abortFromCaller, { once: true });
8355
+ const abortFromCaller = () => abortController.abort(options.signal?.reason);
8356
+ options.signal?.addEventListener("abort", abortFromCaller, { once: true });
9833
8357
  const metadataRequestId = ++this._metadataRequestId;
9834
8358
  const generation = this._sourceGeneration;
9835
8359
  try {
9836
8360
  this._startLoading();
9837
8361
  abortController.signal.throwIfAborted();
9838
- const metadata = await waitForPromiseWithSignals((signal) => this._opts.getMetadata({ signal }), [abortController.signal]);
8362
+ const metadata = await (0, import_loader_utils9.waitForPromiseWithSignals)((signal) => this._opts.getMetadata({ signal }), [abortController.signal]);
9839
8363
  abortController.signal.throwIfAborted();
9840
8364
  if (this._finalized || generation !== this._sourceGeneration || metadataRequestId !== this._metadataRequestId) {
9841
8365
  return metadata;
9842
8366
  }
9843
8367
  this.metadata = metadata;
9844
8368
  for (const listener of this._listeners) {
9845
- (_d = listener.onMetadataLoad) == null ? void 0 : _d.call(listener, metadata);
8369
+ listener.onMetadataLoad?.(metadata);
9846
8370
  }
9847
8371
  this._emitUpdate();
9848
8372
  return metadata;
9849
8373
  } catch (error) {
9850
8374
  if (abortController.signal.aborted)
9851
8375
  throw abortController.signal.reason;
9852
- if (isAbortError3(error))
8376
+ if (isAbortError2(error))
9853
8377
  throw error;
9854
8378
  const normalizedError = normalizeRasterSetError(error, "Raster metadata request failed");
9855
8379
  if (!this._finalized && generation === this._sourceGeneration && metadataRequestId === this._metadataRequestId) {
9856
8380
  for (const listener of this._listeners) {
9857
- (_e = listener.onMetadataLoadError) == null ? void 0 : _e.call(listener, normalizedError);
8381
+ listener.onMetadataLoadError?.(normalizedError);
9858
8382
  }
9859
8383
  }
9860
8384
  throw normalizedError;
9861
8385
  } finally {
9862
- (_f = options.signal) == null ? void 0 : _f.removeEventListener("abort", abortFromCaller);
8386
+ options.signal?.removeEventListener("abort", abortFromCaller);
9863
8387
  if (this._metadataAbortController === abortController)
9864
8388
  this._metadataAbortController = null;
9865
8389
  this._finishLoading();
@@ -9867,14 +8391,13 @@ var RasterSet = class _RasterSet {
9867
8391
  }
9868
8392
  /** Debounces and issues a new raster request for the supplied parameters. */
9869
8393
  requestRaster(parameters, debounceTime = this._opts.debounceTime) {
9870
- var _a;
9871
8394
  if (this._finalized)
9872
8395
  return -1;
9873
8396
  if (!this.shouldRefetchRaster(parameters)) {
9874
8397
  this._cancelScheduledRaster();
9875
8398
  this._abortActiveRequest();
9876
8399
  this._nextRequestId++;
9877
- return ((_a = this._currentRequest) == null ? void 0 : _a.requestId) ?? -1;
8400
+ return this._currentRequest?.requestId ?? -1;
9878
8401
  }
9879
8402
  const requestId = this._nextRequestId++;
9880
8403
  this._cancelScheduledRaster();
@@ -9899,55 +8422,53 @@ var RasterSet = class _RasterSet {
9899
8422
  }
9900
8423
  /** Clears timers and listeners held by the manager. */
9901
8424
  finalize() {
9902
- var _a;
9903
8425
  this._finalized = true;
9904
8426
  this._cancelScheduledRaster();
9905
8427
  this._abortActiveRequest();
9906
- (_a = this._metadataAbortController) == null ? void 0 : _a.abort();
8428
+ this._metadataAbortController?.abort();
9907
8429
  this._metadataAbortController = null;
9908
8430
  this._loadCounter = 0;
9909
8431
  this._listeners.clear();
9910
8432
  }
9911
8433
  /** Loads a raster immediately and accepts it only if it is the newest completed request. */
9912
8434
  async _loadRaster(requestId, parameters) {
9913
- var _a, _b, _c;
9914
8435
  if (this._finalized) {
9915
8436
  return;
9916
8437
  }
9917
8438
  const callerSignal = parameters.signal;
9918
- if (callerSignal == null ? void 0 : callerSignal.aborted)
8439
+ if (callerSignal?.aborted)
9919
8440
  return;
9920
8441
  const abortController = new AbortController();
9921
8442
  this._abortController = abortController;
9922
- const abortFromCaller = () => abortController.abort(callerSignal == null ? void 0 : callerSignal.reason);
9923
- callerSignal == null ? void 0 : callerSignal.addEventListener("abort", abortFromCaller, { once: true });
8443
+ const abortFromCaller = () => abortController.abort(callerSignal?.reason);
8444
+ callerSignal?.addEventListener("abort", abortFromCaller, { once: true });
9924
8445
  this._startLoading();
9925
8446
  try {
9926
8447
  abortController.signal.throwIfAborted();
9927
8448
  for (const listener of this._listeners)
9928
- (_a = listener.onRasterLoadStart) == null ? void 0 : _a.call(listener, requestId, parameters);
8449
+ listener.onRasterLoadStart?.(requestId, parameters);
9929
8450
  abortController.signal.throwIfAborted();
9930
- const raster = await waitForPromiseWithSignals((signal) => this._opts.getRaster(withAbortSignal(parameters, signal)), [abortController.signal]);
8451
+ const raster = await (0, import_loader_utils9.waitForPromiseWithSignals)((signal) => this._opts.getRaster(withAbortSignal(parameters, signal)), [abortController.signal]);
9931
8452
  if (this._finalized || abortController.signal.aborted || requestId !== this._nextRequestId - 1) {
9932
8453
  return;
9933
8454
  }
9934
8455
  this._currentRequest = { requestId, parameters, raster };
9935
8456
  for (const listener of this._listeners) {
9936
- (_b = listener.onRasterLoad) == null ? void 0 : _b.call(listener, this._currentRequest);
8457
+ listener.onRasterLoad?.(this._currentRequest);
9937
8458
  }
9938
8459
  this._emitUpdate();
9939
8460
  } catch (error) {
9940
- if (abortController.signal.aborted || isAbortError3(error)) {
8461
+ if (abortController.signal.aborted || isAbortError2(error)) {
9941
8462
  return;
9942
8463
  }
9943
8464
  const normalizedError = normalizeRasterSetError(error, "Raster request failed");
9944
8465
  if (!this._finalized && requestId === this._nextRequestId - 1) {
9945
8466
  for (const listener of this._listeners) {
9946
- (_c = listener.onRasterLoadError) == null ? void 0 : _c.call(listener, requestId, normalizedError, parameters);
8467
+ listener.onRasterLoadError?.(requestId, normalizedError, parameters);
9947
8468
  }
9948
8469
  }
9949
8470
  } finally {
9950
- callerSignal == null ? void 0 : callerSignal.removeEventListener("abort", abortFromCaller);
8471
+ callerSignal?.removeEventListener("abort", abortFromCaller);
9951
8472
  if (this._abortController === abortController)
9952
8473
  this._abortController = null;
9953
8474
  this._finishLoading();
@@ -9978,20 +8499,18 @@ var RasterSet = class _RasterSet {
9978
8499
  }
9979
8500
  /** Emits one generic update notification to all subscribers. */
9980
8501
  _emitUpdate() {
9981
- var _a;
9982
8502
  if (this._finalized)
9983
8503
  return;
9984
8504
  for (const listener of this._listeners) {
9985
- (_a = listener.onUpdate) == null ? void 0 : _a.call(listener);
8505
+ listener.onUpdate?.();
9986
8506
  }
9987
8507
  }
9988
8508
  /** Emits one loading-state transition to all subscribers. */
9989
8509
  _emitLoadingStateChange(isLoading) {
9990
- var _a;
9991
8510
  if (this._finalized)
9992
8511
  return;
9993
8512
  for (const listener of this._listeners) {
9994
- (_a = listener.onLoadingStateChange) == null ? void 0 : _a.call(listener, isLoading);
8513
+ listener.onLoadingStateChange?.(isLoading);
9995
8514
  }
9996
8515
  }
9997
8516
  /** Increments the active load count and emits loading-state transitions. */
@@ -10021,8 +8540,7 @@ var RasterSet = class _RasterSet {
10021
8540
  }
10022
8541
  /** Aborts the currently active raster request, if one exists. */
10023
8542
  _abortActiveRequest() {
10024
- var _a;
10025
- (_a = this._abortController) == null ? void 0 : _a.abort();
8543
+ this._abortController?.abort();
10026
8544
  this._abortController = null;
10027
8545
  }
10028
8546
  };
@@ -10047,7 +8565,7 @@ function normalizeRasterSetError(error, message) {
10047
8565
  }
10048
8566
  return new Error(message);
10049
8567
  }
10050
- function isAbortError3(error) {
8568
+ function isAbortError2(error) {
10051
8569
  return error instanceof Error && error.name === "AbortError";
10052
8570
  }
10053
8571
 
@@ -10121,7 +8639,7 @@ var PointCloudTile = class {
10121
8639
  };
10122
8640
 
10123
8641
  // dist/point-cloud/point-cloud-tileset.js
10124
- var DEFAULT_PROPS5 = {
8642
+ var DEFAULT_PROPS3 = {
10125
8643
  debounceTime: 0,
10126
8644
  minimumNodePixelSize: 150,
10127
8645
  maximumScreenSpaceError: 1,
@@ -10153,7 +8671,7 @@ var PointCloudTileset = class {
10153
8671
  tilesMap = /* @__PURE__ */ new Map();
10154
8672
  constructor(dataSource, options = {}) {
10155
8673
  this.dataSource = dataSource;
10156
- this.options = { ...DEFAULT_PROPS5, ...options };
8674
+ this.options = { ...DEFAULT_PROPS3, ...options };
10157
8675
  this.tilesetInitializationPromise = this.initialize();
10158
8676
  }
10159
8677
  tilesetInitializationPromise;
@@ -10209,15 +8727,14 @@ var PointCloudTileset = class {
10209
8727
  * Initialize the underlying source and the root tile.
10210
8728
  */
10211
8729
  async initialize() {
10212
- var _a, _b;
10213
8730
  await this.dataSource.initialize();
10214
8731
  const rootHeader = await this.dataSource.getRootTile();
10215
8732
  this.root = this.getOrCreateTile(rootHeader, null);
10216
- const viewState = await ((_b = (_a = this.dataSource).getViewState) == null ? void 0 : _b.call(_a));
10217
- this.boundingVolume = (viewState == null ? void 0 : viewState.boundingVolume) || this.root.boundingVolume;
10218
- const center = (viewState == null ? void 0 : viewState.cartographicCenter) || this.root.boundingVolume.center;
8733
+ const viewState = await this.dataSource.getViewState?.();
8734
+ this.boundingVolume = viewState?.boundingVolume || this.root.boundingVolume;
8735
+ const center = viewState?.cartographicCenter || this.root.boundingVolume.center;
10219
8736
  this.cartographicCenter = new import_core15.Vector3(center);
10220
- this.zoom = (viewState == null ? void 0 : viewState.zoom) || this.estimateZoom(this.boundingVolume);
8737
+ this.zoom = viewState?.zoom || this.estimateZoom(this.boundingVolume);
10221
8738
  }
10222
8739
  /**
10223
8740
  * Debounced async tile selection.
@@ -10228,9 +8745,9 @@ var PointCloudTileset = class {
10228
8745
  this.lastUpdatedViewports = viewports;
10229
8746
  }
10230
8747
  if (!this.updatePromise) {
10231
- this.updatePromise = new Promise((resolve2, reject) => {
8748
+ this.updatePromise = new Promise((resolve, reject) => {
10232
8749
  setTimeout(() => {
10233
- this.doSelectTiles().then(() => resolve2(this.frameNumberValue)).catch(reject).finally(() => {
8750
+ this.doSelectTiles().then(() => resolve(this.frameNumberValue)).catch(reject).finally(() => {
10234
8751
  this.updatePromise = null;
10235
8752
  });
10236
8753
  }, this.options.debounceTime);
@@ -10568,8 +9085,7 @@ var PointCloudTileset = class {
10568
9085
  * Build a culling volume directly from the viewport frustum in common space.
10569
9086
  */
10570
9087
  getCullingVolume(viewport) {
10571
- var _a;
10572
- const getFrustumPlanes = (_a = viewport.getFrustumPlanes) == null ? void 0 : _a.bind(viewport);
9088
+ const getFrustumPlanes = viewport.getFrustumPlanes?.bind(viewport);
10573
9089
  if (!getFrustumPlanes) {
10574
9090
  return null;
10575
9091
  }
@@ -10589,8 +9105,7 @@ var PointCloudTileset = class {
10589
9105
  * Approximate a tile AABB by a common-space bounding sphere for frustum culling.
10590
9106
  */
10591
9107
  getCommonSpaceBoundingSphere(boundingVolume, viewport) {
10592
- var _a;
10593
- const projectPosition = (_a = viewport.projectPosition) == null ? void 0 : _a.bind(viewport);
9108
+ const projectPosition = viewport.projectPosition?.bind(viewport);
10594
9109
  if (!projectPosition) {
10595
9110
  return null;
10596
9111
  }
@@ -10623,4 +9138,82 @@ var PointCloudTileset = class {
10623
9138
  return new import_culling6.BoundingSphere().fromCornerPoints([minX, minY, minZ], [maxX, maxY, maxZ]);
10624
9139
  }
10625
9140
  };
9141
+
9142
+ // dist/point-cloud-tile-source-loader-types.js
9143
+ var VERSION = true ? "5.0.0-alpha.12" : "latest";
9144
+ async function preloadPointCloudTileSource() {
9145
+ const { PointCloudTileSourceLoaderWithParser } = await import("@loaders.gl/tiles/point-cloud-tile-source-loader");
9146
+ return PointCloudTileSourceLoaderWithParser;
9147
+ }
9148
+ var PointCloudTileSourceLoader = {
9149
+ dataType: null,
9150
+ batchType: null,
9151
+ name: "PointCloudTiler",
9152
+ id: "point-cloud-tiler",
9153
+ module: "tiles",
9154
+ version: VERSION,
9155
+ extensions: [],
9156
+ mimeTypes: [],
9157
+ type: "point-cloud",
9158
+ fromUrl: false,
9159
+ fromBlob: false,
9160
+ testURL: () => false,
9161
+ options: { pointCloudTiler: {} },
9162
+ defaultOptions: { pointCloudTiler: {} },
9163
+ preload: preloadPointCloudTileSource,
9164
+ /** Direct construction requires the runtime rather than this metadata export. */
9165
+ createDataSource(_input, _options = {}, _coreApi) {
9166
+ throw new Error("PointCloudTileSourceLoader requires preload() or @loaders.gl/tiles/point-cloud-tile-source-loader");
9167
+ }
9168
+ };
9169
+ // Annotate the CommonJS export names for ESM import in node:
9170
+ 0 && (module.exports = {
9171
+ I3SSource,
9172
+ I3SSpatialTransformer,
9173
+ ImageSet,
9174
+ IndexedArchiveTilesetSource,
9175
+ LOD_METRIC_TYPE,
9176
+ PointCloudTile,
9177
+ PointCloudTileSourceLoader,
9178
+ PointCloudTileset,
9179
+ RasterSet,
9180
+ STRATEGY_DEFAULT,
9181
+ STRATEGY_NEVER,
9182
+ STRATEGY_REPLACE,
9183
+ SharedTile2DHeader,
9184
+ SpatialCoordinateTransformer,
9185
+ TILESET_TYPE,
9186
+ TILE_CONTENT_STATE,
9187
+ TILE_REFINEMENT,
9188
+ TILE_TYPE,
9189
+ Tile3D,
9190
+ Tiles3DSource,
9191
+ Tiles3DSpatialTransformer,
9192
+ Tileset2D,
9193
+ Tileset3D,
9194
+ TilesetCache,
9195
+ TilesetTraverser,
9196
+ applyTilesetSpatialOptions,
9197
+ calculateTransformProps,
9198
+ convertS2BoundingVolumeToOBB,
9199
+ createBoundingVolume,
9200
+ createImplicitSubtreeReference,
9201
+ createTilesetSpatialReference,
9202
+ get3DTilesSpatialReference,
9203
+ getFrameState,
9204
+ getGeoidModel,
9205
+ getI3SSpatialReference,
9206
+ getLodStatus,
9207
+ getSpatialCoordinateFrame,
9208
+ getTileset3DTraversalSnapshot,
9209
+ isTileset3DSource,
9210
+ markTilesetSpatialReferenceTransformed,
9211
+ materializeImplicitSubtree,
9212
+ registerGeoidModel,
9213
+ registerGeoidModelFromPgm,
9214
+ registerSpatialCrs,
9215
+ registerSpatialDatumGrid,
9216
+ replaceImplicitUrlTemplate,
9217
+ traverseTilesetContents
9218
+ });
10626
9219
  //# sourceMappingURL=index.cjs.map