@loaders.gl/tiles 3.1.7 → 3.2.0-alpha.2

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 (73) hide show
  1. package/dist/dist.min.js +302 -318
  2. package/dist/es5/tileset/helpers/frame-state.js +79 -0
  3. package/dist/es5/tileset/helpers/frame-state.js.map +1 -1
  4. package/dist/es5/tileset/helpers/i3s-lod.js +17 -26
  5. package/dist/es5/tileset/helpers/i3s-lod.js.map +1 -1
  6. package/dist/es5/tileset/helpers/zoom.js +32 -0
  7. package/dist/es5/tileset/helpers/zoom.js.map +1 -1
  8. package/dist/es5/tileset/tile-3d.js +5 -0
  9. package/dist/es5/tileset/tile-3d.js.map +1 -1
  10. package/dist/es5/tileset/tileset-3d.js +244 -85
  11. package/dist/es5/tileset/tileset-3d.js.map +1 -1
  12. package/dist/es5/tileset/traversers/i3s-frame-counter.js +45 -0
  13. package/dist/es5/tileset/traversers/i3s-frame-counter.js.map +1 -0
  14. package/dist/es5/tileset/traversers/i3s-tile-manager.js +17 -0
  15. package/dist/es5/tileset/traversers/i3s-tile-manager.js.map +1 -1
  16. package/dist/es5/tileset/traversers/i3s-tileset-traverser.js +6 -1
  17. package/dist/es5/tileset/traversers/i3s-tileset-traverser.js.map +1 -1
  18. package/dist/es5/tileset/traversers/tileset-traverser.js +13 -1
  19. package/dist/es5/tileset/traversers/tileset-traverser.js.map +1 -1
  20. package/dist/esm/tileset/helpers/frame-state.js +52 -0
  21. package/dist/esm/tileset/helpers/frame-state.js.map +1 -1
  22. package/dist/esm/tileset/helpers/i3s-lod.js +17 -27
  23. package/dist/esm/tileset/helpers/i3s-lod.js.map +1 -1
  24. package/dist/esm/tileset/helpers/zoom.js +17 -0
  25. package/dist/esm/tileset/helpers/zoom.js.map +1 -1
  26. package/dist/esm/tileset/tile-3d.js +4 -0
  27. package/dist/esm/tileset/tile-3d.js.map +1 -1
  28. package/dist/esm/tileset/tileset-3d.js +95 -17
  29. package/dist/esm/tileset/tileset-3d.js.map +1 -1
  30. package/dist/esm/tileset/traversers/i3s-frame-counter.js +23 -0
  31. package/dist/esm/tileset/traversers/i3s-frame-counter.js.map +1 -0
  32. package/dist/esm/tileset/traversers/i3s-tile-manager.js +15 -0
  33. package/dist/esm/tileset/traversers/i3s-tile-manager.js.map +1 -1
  34. package/dist/esm/tileset/traversers/i3s-tileset-traverser.js +5 -1
  35. package/dist/esm/tileset/traversers/i3s-tileset-traverser.js.map +1 -1
  36. package/dist/esm/tileset/traversers/tileset-traverser.js +14 -1
  37. package/dist/esm/tileset/traversers/tileset-traverser.js.map +1 -1
  38. package/dist/tileset/helpers/frame-state.d.ts +14 -0
  39. package/dist/tileset/helpers/frame-state.d.ts.map +1 -1
  40. package/dist/tileset/helpers/frame-state.js +49 -1
  41. package/dist/tileset/helpers/i3s-lod.d.ts.map +1 -1
  42. package/dist/tileset/helpers/i3s-lod.js +17 -16
  43. package/dist/tileset/helpers/zoom.d.ts +35 -0
  44. package/dist/tileset/helpers/zoom.d.ts.map +1 -1
  45. package/dist/tileset/helpers/zoom.js +41 -1
  46. package/dist/tileset/tile-3d.d.ts +5 -0
  47. package/dist/tileset/tile-3d.d.ts.map +1 -1
  48. package/dist/tileset/tile-3d.js +7 -0
  49. package/dist/tileset/tileset-3d.d.ts +36 -4
  50. package/dist/tileset/tileset-3d.d.ts.map +1 -1
  51. package/dist/tileset/tileset-3d.js +99 -20
  52. package/dist/tileset/traversers/i3s-frame-counter.d.ts +24 -0
  53. package/dist/tileset/traversers/i3s-frame-counter.d.ts.map +1 -0
  54. package/dist/tileset/traversers/i3s-frame-counter.js +37 -0
  55. package/dist/tileset/traversers/i3s-tile-manager.d.ts +10 -2
  56. package/dist/tileset/traversers/i3s-tile-manager.d.ts.map +1 -1
  57. package/dist/tileset/traversers/i3s-tile-manager.js +24 -0
  58. package/dist/tileset/traversers/i3s-tileset-traverser.d.ts +9 -2
  59. package/dist/tileset/traversers/i3s-tileset-traverser.d.ts.map +1 -1
  60. package/dist/tileset/traversers/i3s-tileset-traverser.js +10 -1
  61. package/dist/tileset/traversers/tileset-traverser.d.ts +5 -1
  62. package/dist/tileset/traversers/tileset-traverser.d.ts.map +1 -1
  63. package/dist/tileset/traversers/tileset-traverser.js +10 -1
  64. package/package.json +5 -5
  65. package/src/tileset/helpers/frame-state.ts +56 -0
  66. package/src/tileset/helpers/i3s-lod.ts +18 -19
  67. package/src/tileset/helpers/zoom.ts +64 -0
  68. package/src/tileset/tile-3d.ts +8 -0
  69. package/src/tileset/tileset-3d.ts +123 -21
  70. package/src/tileset/traversers/i3s-frame-counter.ts +35 -0
  71. package/src/tileset/traversers/i3s-tile-manager.ts +26 -2
  72. package/src/tileset/traversers/i3s-tileset-traverser.ts +16 -3
  73. package/src/tileset/traversers/tileset-traverser.ts +13 -2
@@ -62,6 +62,10 @@ const DEFAULT_PROPS = {
62
62
  // Number of simultaneous requsts, if throttleRequests is true
63
63
  maxRequests: 64,
64
64
  maximumMemoryUsage: 32,
65
+ /** Maximum number limit of tiles selected for show. 0 means no limit */
66
+ maximumTilesSelected: 0,
67
+ /** Delay time before the tileset traversal. It prevents traversal requests spam.*/
68
+ debounceTime: 0,
65
69
  /**
66
70
  * Callback. Indicates this a tile's content was loaded
67
71
  * @param tile {TileHeader}
@@ -83,7 +87,6 @@ const DEFAULT_PROPS = {
83
87
  contentLoader: undefined,
84
88
  // View distance scale modifier
85
89
  viewDistanceScale: 1.0,
86
- // TODO CESIUM
87
90
  // The maximum screen space error used to drive level of detail refinement.
88
91
  maximumScreenSpaceError: 8,
89
92
  loadTiles: true,
@@ -113,6 +116,7 @@ class Tileset3D {
113
116
  */
114
117
  // eslint-disable-next-line max-statements
115
118
  constructor(json, options) {
119
+ this.updatePromise = null;
116
120
  (0, loader_utils_1.assert)(json);
117
121
  // PUBLIC MEMBERS
118
122
  this.options = { ...DEFAULT_PROPS, ...options };
@@ -177,7 +181,7 @@ class Tileset3D {
177
181
  this.asset = {};
178
182
  this.credits = {};
179
183
  this.description = this.options.description || '';
180
- this._initializeTileSet(json);
184
+ this.tilesetInitializationPromise = this._initializeTileSet(json);
181
185
  }
182
186
  /** Release resources */
183
187
  destroy() {
@@ -225,21 +229,54 @@ class Tileset3D {
225
229
  /**
226
230
  * Update visible tiles relying on a list of viewports
227
231
  * @param viewports - list of viewports
232
+ * @deprecated
233
+ */
234
+ update(viewports = null) {
235
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
236
+ this.tilesetInitializationPromise.then(() => {
237
+ if (!viewports && this.lastUpdatedVieports) {
238
+ viewports = this.lastUpdatedVieports;
239
+ }
240
+ else {
241
+ this.lastUpdatedVieports = viewports;
242
+ }
243
+ this.doUpdate(viewports);
244
+ });
245
+ }
246
+ /**
247
+ * Update visible tiles relying on a list of viewports.
248
+ * Do it with debounce delay to prevent update spam
249
+ * @param viewports viewports
250
+ * @returns Promise of new frameNumber
251
+ */
252
+ async selectTiles(viewports = null) {
253
+ await this.tilesetInitializationPromise;
254
+ if (viewports) {
255
+ this.lastUpdatedVieports = viewports;
256
+ }
257
+ if (!this.updatePromise) {
258
+ this.updatePromise = new Promise((resolve) => {
259
+ setTimeout(() => {
260
+ this.doUpdate(this.lastUpdatedVieports);
261
+ resolve(this._frameNumber);
262
+ this.updatePromise = null;
263
+ }, this.options.debounceTime);
264
+ });
265
+ }
266
+ return this.updatePromise;
267
+ }
268
+ /**
269
+ * Update visible tiles relying on a list of viewports
270
+ * @param viewports viewports
228
271
  */
229
272
  // eslint-disable-next-line max-statements, complexity
230
- update(viewports) {
273
+ doUpdate(viewports = null) {
231
274
  if ('loadTiles' in this.options && !this.options.loadTiles) {
232
275
  return;
233
276
  }
234
277
  if (this.traverseCounter > 0) {
235
278
  return;
236
279
  }
237
- if (!viewports && this.lastUpdatedVieports) {
238
- viewports = this.lastUpdatedVieports;
239
- }
240
- else {
241
- this.lastUpdatedVieports = viewports;
242
- }
243
280
  if (!(viewports instanceof Array)) {
244
281
  viewports = [viewports];
245
282
  }
@@ -296,7 +333,11 @@ class Tileset3D {
296
333
  }
297
334
  const currentFrameStateData = this.frameStateData[id];
298
335
  const selectedTiles = Object.values(this._traverser.selectedTiles);
299
- currentFrameStateData.selectedTiles = selectedTiles;
336
+ const [filteredSelectedTiles, unselectedTiles] = (0, frame_state_1.limitSelectedTiles)(selectedTiles, frameState, this.options.maximumTilesSelected);
337
+ currentFrameStateData.selectedTiles = filteredSelectedTiles;
338
+ for (const tile of unselectedTiles) {
339
+ tile.unselect();
340
+ }
300
341
  currentFrameStateData._requestedTiles = Object.values(this._traverser.requestedTiles);
301
342
  currentFrameStateData._emptyTiles = Object.values(this._traverser.emptyTiles);
302
343
  this.traverseCounter--;
@@ -366,26 +407,64 @@ class Tileset3D {
366
407
  this.stats.get(TILES_RENDERABLE).count = tilesRenderable;
367
408
  this.stats.get(POINTS_COUNT).count = pointsRenderable;
368
409
  }
369
- _initializeTileSet(tilesetJson) {
410
+ async _initializeTileSet(tilesetJson) {
411
+ if (this.type === constants_1.TILESET_TYPE.I3S) {
412
+ this.calculateViewPropsI3S();
413
+ tilesetJson.root = await tilesetJson.root;
414
+ }
370
415
  this.root = this._initializeTileHeaders(tilesetJson, null);
371
- // TODO CESIUM Specific
372
416
  if (this.type === constants_1.TILESET_TYPE.TILES3D) {
373
- this._initializeCesiumTileset(tilesetJson);
417
+ this._initializeTiles3DTileset(tilesetJson);
418
+ this.calculateViewPropsTiles3D();
374
419
  }
375
420
  if (this.type === constants_1.TILESET_TYPE.I3S) {
376
421
  this._initializeI3STileset();
377
422
  }
378
- // Calculate cartographicCenter & zoom props to help apps center view on tileset
379
- this._calculateViewProps();
380
423
  }
381
- // Called during initialize Tileset to initialize the tileset's cartographic center (longitude, latitude) and zoom.
382
- _calculateViewProps() {
424
+ /**
425
+ * Called during initialize Tileset to initialize the tileset's cartographic center (longitude, latitude) and zoom.
426
+ * These metrics help apps center view on tileset
427
+ * For I3S there is extent (<1.8 version) or fullExtent (>=1.8 version) to calculate view props
428
+ * @returns
429
+ */
430
+ calculateViewPropsI3S() {
431
+ // for I3S 1.8 try to calculate with fullExtent
432
+ const fullExtent = this.tileset.fullExtent;
433
+ if (fullExtent) {
434
+ const { xmin, xmax, ymin, ymax, zmin, zmax } = fullExtent;
435
+ this.cartographicCenter = new core_1.Vector3(xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2, zmin + (zmax - zmin) / 2);
436
+ this.cartesianCenter = geospatial_1.Ellipsoid.WGS84.cartographicToCartesian(this.cartographicCenter, new core_1.Vector3());
437
+ this.zoom = (0, zoom_1.getZoomFromFullExtent)(fullExtent, this.cartographicCenter, this.cartesianCenter);
438
+ return;
439
+ }
440
+ // for I3S 1.6-1.7 try to calculate with extent
441
+ const extent = this.tileset.store?.extent;
442
+ if (extent) {
443
+ const [xmin, ymin, xmax, ymax] = extent;
444
+ this.cartographicCenter = new core_1.Vector3(xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2, 0);
445
+ this.cartesianCenter = geospatial_1.Ellipsoid.WGS84.cartographicToCartesian(this.cartographicCenter, new core_1.Vector3());
446
+ this.zoom = (0, zoom_1.getZoomFromExtent)(extent, this.cartographicCenter, this.cartesianCenter);
447
+ return;
448
+ }
449
+ // eslint-disable-next-line no-console
450
+ console.warn('Extent is not defined in the tileset header');
451
+ this.cartographicCenter = new core_1.Vector3();
452
+ this.zoom = 1;
453
+ return;
454
+ }
455
+ /**
456
+ * Called during initialize Tileset to initialize the tileset's cartographic center (longitude, latitude) and zoom.
457
+ * These metrics help apps center view on tileset.
458
+ * For 3DTiles the root tile data is used to calculate view props.
459
+ * @returns
460
+ */
461
+ calculateViewPropsTiles3D() {
383
462
  const root = this.root;
384
463
  (0, loader_utils_1.assert)(root);
385
464
  const { center } = root.boundingVolume;
386
465
  // TODO - handle all cases
387
466
  if (!center) {
388
- // eslint-disable-next-line
467
+ // eslint-disable-next-line no-console
389
468
  console.warn('center was not pre-calculated for the root tile');
390
469
  this.cartographicCenter = new core_1.Vector3();
391
470
  this.zoom = 1;
@@ -419,7 +498,7 @@ class Tileset3D {
419
498
  parentTileHeader.children.push(rootTile);
420
499
  rootTile.depth = parentTileHeader.depth + 1;
421
500
  }
422
- // Cesium 3d tiles knows the hierarchy beforehand
501
+ // 3DTiles knows the hierarchy beforehand
423
502
  if (this.type === constants_1.TILESET_TYPE.TILES3D) {
424
503
  const stack = [];
425
504
  stack.push(rootTile);
@@ -553,7 +632,7 @@ class Tileset3D {
553
632
  this._unloadTile(tile);
554
633
  tile.destroy();
555
634
  }
556
- _initializeCesiumTileset(tilesetJson) {
635
+ _initializeTiles3DTileset(tilesetJson) {
557
636
  this.asset = tilesetJson.asset;
558
637
  if (!this.asset) {
559
638
  throw new Error('Tileset must have an asset property.');
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Counter to register pending tile headers for the particular frameNumber
3
+ * Until all tiles are loaded we won't call `onTraversalEnd` callback
4
+ */
5
+ export default class I3SPendingTilesRegister {
6
+ private frameNumberMap;
7
+ /**
8
+ * Register a new pending tile header for the particular frameNumber
9
+ * @param frameNumber
10
+ */
11
+ register(frameNumber: number): void;
12
+ /**
13
+ * Deregister a pending tile header for the particular frameNumber
14
+ * @param frameNumber
15
+ */
16
+ deregister(frameNumber: number): void;
17
+ /**
18
+ * Check is there are no pending tile headers registered for the particular frameNumber
19
+ * @param frameNumber
20
+ * @returns
21
+ */
22
+ isZero(frameNumber: number): boolean;
23
+ }
24
+ //# sourceMappingURL=i3s-frame-counter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i3s-frame-counter.d.ts","sourceRoot":"","sources":["../../../src/tileset/traversers/i3s-frame-counter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC1C,OAAO,CAAC,cAAc,CAAkC;IAExD;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM;IAK5B;;;OAGG;IACH,UAAU,CAAC,WAAW,EAAE,MAAM;IAK9B;;;;OAIG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM;CAI3B"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * Counter to register pending tile headers for the particular frameNumber
5
+ * Until all tiles are loaded we won't call `onTraversalEnd` callback
6
+ */
7
+ class I3SPendingTilesRegister {
8
+ constructor() {
9
+ this.frameNumberMap = new Map();
10
+ }
11
+ /**
12
+ * Register a new pending tile header for the particular frameNumber
13
+ * @param frameNumber
14
+ */
15
+ register(frameNumber) {
16
+ const oldCount = this.frameNumberMap.get(frameNumber) || 0;
17
+ this.frameNumberMap.set(frameNumber, (oldCount || 0) + 1);
18
+ }
19
+ /**
20
+ * Deregister a pending tile header for the particular frameNumber
21
+ * @param frameNumber
22
+ */
23
+ deregister(frameNumber) {
24
+ const oldCount = this.frameNumberMap.get(frameNumber) || 1;
25
+ this.frameNumberMap.set(frameNumber, (oldCount || 0) - 1);
26
+ }
27
+ /**
28
+ * Check is there are no pending tile headers registered for the particular frameNumber
29
+ * @param frameNumber
30
+ * @returns
31
+ */
32
+ isZero(frameNumber) {
33
+ const count = this.frameNumberMap.get(frameNumber) || 0;
34
+ return count === 0;
35
+ }
36
+ }
37
+ exports.default = I3SPendingTilesRegister;
@@ -1,8 +1,16 @@
1
+ import { FrameState } from '../helpers/frame-state';
1
2
  export default class I3STileManager {
2
3
  private _statusMap;
4
+ private pendingTilesRegister;
3
5
  constructor();
4
- add(request: any, key: any, callback: any, frameState: any): void;
5
- update(key: any, frameState: any): void;
6
+ add(request: any, key: any, callback: any, frameState: FrameState): void;
7
+ update(key: any, frameState: FrameState): void;
6
8
  find(key: any): any;
9
+ /**
10
+ * Check it there are pending tile headers for the particular frameNumber
11
+ * @param frameNumber
12
+ * @returns
13
+ */
14
+ hasPendingTiles(frameNumber: number): boolean;
7
15
  }
8
16
  //# sourceMappingURL=i3s-tile-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"i3s-tile-manager.d.ts","sourceRoot":"","sources":["../../../src/tileset/traversers/i3s-tile-manager.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,UAAU,CAAS;;IAM3B,GAAG,CAAC,OAAO,KAAA,EAAE,GAAG,KAAA,EAAE,QAAQ,KAAA,EAAE,UAAU,KAAA;IAetC,MAAM,CAAC,GAAG,KAAA,EAAE,UAAU,KAAA;IAMtB,IAAI,CAAC,GAAG,KAAA;CAGT"}
1
+ {"version":3,"file":"i3s-tile-manager.d.ts","sourceRoot":"","sources":["../../../src/tileset/traversers/i3s-tile-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAUlD,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,oBAAoB,CAAiC;;IAM7D,GAAG,CAAC,OAAO,KAAA,EAAE,GAAG,KAAA,EAAE,QAAQ,KAAA,EAAE,UAAU,EAAE,UAAU;IAsBlD,MAAM,CAAC,GAAG,KAAA,EAAE,UAAU,EAAE,UAAU;IAUlC,IAAI,CAAC,GAAG,KAAA;IAIR;;;;OAIG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;CAG9C"}
@@ -1,5 +1,9 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const i3s_frame_counter_1 = __importDefault(require("./i3s-frame-counter"));
3
7
  const STATUS = {
4
8
  REQUESTED: 'REQUESTED',
5
9
  COMPLETED: 'COMPLETED',
@@ -8,29 +12,49 @@ const STATUS = {
8
12
  // A helper class to manage tile metadata fetching
9
13
  class I3STileManager {
10
14
  constructor() {
15
+ this.pendingTilesRegister = new i3s_frame_counter_1.default();
11
16
  this._statusMap = {};
12
17
  }
13
18
  add(request, key, callback, frameState) {
14
19
  if (!this._statusMap[key]) {
20
+ const { frameNumber } = frameState;
15
21
  this._statusMap[key] = { request, callback, key, frameState, status: STATUS.REQUESTED };
22
+ // Register pending request for the frameNumber
23
+ this.pendingTilesRegister.register(frameNumber);
16
24
  request()
17
25
  .then((data) => {
18
26
  this._statusMap[key].status = STATUS.COMPLETED;
27
+ // Deregister pending request for the frameNumber
28
+ this.pendingTilesRegister.deregister(frameNumber);
19
29
  this._statusMap[key].callback(data, frameState);
20
30
  })
21
31
  .catch((error) => {
22
32
  this._statusMap[key].status = STATUS.ERROR;
33
+ // Deregister pending request for the frameNumber
34
+ this.pendingTilesRegister.deregister(frameNumber);
23
35
  callback(error);
24
36
  });
25
37
  }
26
38
  }
27
39
  update(key, frameState) {
28
40
  if (this._statusMap[key]) {
41
+ // Deregister pending request for the old frameNumber
42
+ this.pendingTilesRegister.deregister(this._statusMap[key].frameState.frameNumber);
43
+ // Register pending request for the new frameNumber
44
+ this.pendingTilesRegister.register(frameState.frameNumber);
29
45
  this._statusMap[key].frameState = frameState;
30
46
  }
31
47
  }
32
48
  find(key) {
33
49
  return this._statusMap[key];
34
50
  }
51
+ /**
52
+ * Check it there are pending tile headers for the particular frameNumber
53
+ * @param frameNumber
54
+ * @returns
55
+ */
56
+ hasPendingTiles(frameNumber) {
57
+ return !this.pendingTilesRegister.isZero(frameNumber);
58
+ }
35
59
  }
36
60
  exports.default = I3STileManager;
@@ -1,9 +1,16 @@
1
1
  import TilesetTraverser from './tileset-traverser';
2
+ import { FrameState } from '../helpers/frame-state';
2
3
  export default class I3STilesetTraverser extends TilesetTraverser {
3
4
  private _tileManager;
5
+ /**
6
+ * Check if there are no penging tile header requests,
7
+ * that means the traversal is finished and we can call
8
+ * following-up callbacks.
9
+ */
10
+ protected get traversalFinished(): boolean;
4
11
  constructor(options: any);
5
- shouldRefine(tile: any, frameState: any): boolean;
6
- updateChildTiles(tile: any, frameState: any): boolean;
12
+ shouldRefine(tile: any, frameState: FrameState): boolean;
13
+ updateChildTiles(tile: any, frameState: FrameState): boolean;
7
14
  _loadTile(nodeId: any, tileset: any): Promise<any>;
8
15
  /**
9
16
  * The callback to init TileHeader instance after loading the tile JSON
@@ -1 +1 @@
1
- {"version":3,"file":"i3s-tileset-traverser.d.ts","sourceRoot":"","sources":["../../../src/tileset/traversers/i3s-tileset-traverser.ts"],"names":[],"mappings":"AACA,OAAO,gBAAgB,MAAM,qBAAqB,CAAC;AAMnD,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,gBAAgB;IAC/D,OAAO,CAAC,YAAY,CAAiB;gBAEzB,OAAO,KAAA;IAKnB,YAAY,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAK7B,gBAAgB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA,GAAG,OAAO;IAoCrC,SAAS,CAAC,MAAM,KAAA,EAAE,OAAO,KAAA;IAgB/B;;;;;;;OAOG;IACH,WAAW,CAAC,MAAM,KAAA,EAAE,IAAI,KAAA,EAAE,UAAU,KAAA;CAYrC"}
1
+ {"version":3,"file":"i3s-tileset-traverser.d.ts","sourceRoot":"","sources":["../../../src/tileset/traversers/i3s-tileset-traverser.ts"],"names":[],"mappings":"AACA,OAAO,gBAAgB,MAAM,qBAAqB,CAAC;AAKnD,OAAO,EAAC,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAElD,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,gBAAgB;IAC/D,OAAO,CAAC,YAAY,CAAiB;IAErC;;;;OAIG;IACH,SAAS,KAAK,iBAAiB,IAAI,OAAO,CAEzC;gBAEW,OAAO,KAAA;IAKnB,YAAY,CAAC,IAAI,KAAA,EAAE,UAAU,EAAE,UAAU;IAKzC,gBAAgB,CAAC,IAAI,KAAA,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO;IAoCjD,SAAS,CAAC,MAAM,KAAA,EAAE,OAAO,KAAA;IAgB/B;;;;;;;OAOG;IACH,WAAW,CAAC,MAAM,KAAA,EAAE,IAAI,KAAA,EAAE,UAAU,KAAA;CAerC"}
@@ -13,6 +13,14 @@ class I3STilesetTraverser extends tileset_traverser_1.default {
13
13
  super(options);
14
14
  this._tileManager = new i3s_tile_manager_1.default();
15
15
  }
16
+ /**
17
+ * Check if there are no penging tile header requests,
18
+ * that means the traversal is finished and we can call
19
+ * following-up callbacks.
20
+ */
21
+ get traversalFinished() {
22
+ return !this._tileManager.hasPendingTiles(this._frameNumber || 0);
23
+ }
16
24
  shouldRefine(tile, frameState) {
17
25
  tile._lodJudge = (0, i3s_lod_1.getLodStatus)(tile, frameState);
18
26
  return tile._lodJudge === 'DIG';
@@ -77,7 +85,8 @@ class I3STilesetTraverser extends tileset_traverser_1.default {
77
85
  const frameState = this._tileManager.find(childTile.id).frameState;
78
86
  this.updateTile(childTile, frameState);
79
87
  // after tile fetched, resume traversal if still in current update/traversal frame
80
- if (this._frameNumber === frameState.frameNumber) {
88
+ if (this._frameNumber === frameState.frameNumber &&
89
+ (this.traversalFinished || new Date().getTime() - this.lastUpdate > this.updateDebounceTime)) {
81
90
  this.executeTraversal(childTile, frameState);
82
91
  }
83
92
  }
@@ -1,4 +1,5 @@
1
1
  import ManagedArray from '../../utils/managed-array';
2
+ import { FrameState } from '../helpers/frame-state';
2
3
  export declare type TilesetTraverserProps = {
3
4
  loadSiblings?: boolean;
4
5
  skipLevelOfDetail?: boolean;
@@ -27,13 +28,16 @@ export default class TilesetTraverser {
27
28
  requestedTiles: object;
28
29
  selectedTiles: object;
29
30
  emptyTiles: object;
31
+ protected lastUpdate: number;
32
+ protected readonly updateDebounceTime = 1000;
30
33
  protected _traversalStack: ManagedArray;
31
34
  protected _emptyTraversalStack: ManagedArray;
32
35
  protected _frameNumber: number | null;
36
+ protected get traversalFinished(): boolean;
33
37
  constructor(options: TilesetTraverserProps);
34
38
  traverse(root: any, frameState: any, options: any): void;
35
39
  reset(): void;
36
- executeTraversal(root: any, frameState: any): void;
40
+ executeTraversal(root: any, frameState: FrameState): void;
37
41
  updateChildTiles(tile: any, frameState: any): boolean;
38
42
  updateAndPushChildren(tile: any, frameState: any, stack: any, depth: any): boolean;
39
43
  updateTile(tile: any, frameState: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"tileset-traverser.d.ts","sourceRoot":"","sources":["../../../src/tileset/traversers/tileset-traverser.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,2BAA2B,CAAC;AAGrD,oBAAY,qBAAqB,GAAG;IAClC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,UAAU,KAAA,KAAK,GAAG,CAAC;IACrC,qBAAqB,CAAC,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,oBAAY,KAAK,GAAG;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uBAAuB,EAAE,MAAM,CAAC;IAChC,cAAc,EAAE,CAAC,UAAU,KAAA,KAAK,GAAG,CAAC;IACpC,qBAAqB,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAQ3B,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC,OAAO,EAAE,KAAK,CAAC;IAEf,IAAI,EAAE,GAAG,CAAC;IACV,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,eAAe,EAAE,YAAY,CAAC;IACxC,SAAS,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC7C,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;gBAG1B,OAAO,EAAE,qBAAqB;IAuB1C,QAAQ,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA,EAAE,OAAO,KAAA;IAclC,KAAK;IAgBL,gBAAgB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IA+DjC,gBAAgB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IASjC,qBAAqB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA,EAAE,KAAK,KAAA,EAAE,KAAK,KAAA;IAuDpD,UAAU,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAK3B,UAAU,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAS3B,QAAQ,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IASzB,SAAS,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAQ1B,WAAW,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA,EAAE,eAAe,UAAQ,EAAE,gBAAgB,UAAQ;IAmB/E,cAAc,CAAC,IAAI,KAAA;IAMnB,gBAAgB,CAAC,IAAI,KAAA;IAOrB,YAAY,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA,EAAE,eAAe,KAAA;IAS9C,oBAAoB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAiBrC,uBAAuB,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA;IAI5B,kBAAkB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAWnC,qBAAqB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;CAqCvC"}
1
+ {"version":3,"file":"tileset-traverser.d.ts","sourceRoot":"","sources":["../../../src/tileset/traversers/tileset-traverser.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,2BAA2B,CAAC;AAErD,OAAO,EAAC,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAElD,oBAAY,qBAAqB,GAAG;IAClC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,UAAU,KAAA,KAAK,GAAG,CAAC;IACrC,qBAAqB,CAAC,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,oBAAY,KAAK,GAAG;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uBAAuB,EAAE,MAAM,CAAC;IAChC,cAAc,EAAE,CAAC,UAAU,KAAA,KAAK,GAAG,CAAC;IACpC,qBAAqB,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAQ3B,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC,OAAO,EAAE,KAAK,CAAC;IAEf,IAAI,EAAE,GAAG,CAAC;IACV,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,UAAU,EAAE,MAAM,CAAwB;IACpD,SAAS,CAAC,QAAQ,CAAC,kBAAkB,QAAQ;IAC7C,SAAS,CAAC,eAAe,EAAE,YAAY,CAAC;IACxC,SAAS,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC7C,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtC,SAAS,KAAK,iBAAiB,IAAI,OAAO,CAEzC;gBAGW,OAAO,EAAE,qBAAqB;IAuB1C,QAAQ,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA,EAAE,OAAO,KAAA;IAclC,KAAK;IAgBL,gBAAgB,CAAC,IAAI,KAAA,EAAE,UAAU,EAAE,UAAU;IAmE7C,gBAAgB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IASjC,qBAAqB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA,EAAE,KAAK,KAAA,EAAE,KAAK,KAAA;IAuDpD,UAAU,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAK3B,UAAU,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAS3B,QAAQ,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IASzB,SAAS,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAQ1B,WAAW,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA,EAAE,eAAe,UAAQ,EAAE,gBAAgB,UAAQ;IAmB/E,cAAc,CAAC,IAAI,KAAA;IAMnB,gBAAgB,CAAC,IAAI,KAAA;IAOrB,YAAY,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA,EAAE,eAAe,KAAA;IAS9C,oBAAoB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAiBrC,uBAAuB,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA;IAI5B,kBAAkB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;IAWnC,qBAAqB,CAAC,IAAI,KAAA,EAAE,UAAU,KAAA;CAqCvC"}
@@ -18,6 +18,8 @@ exports.DEFAULT_PROPS = {
18
18
  class TilesetTraverser {
19
19
  // TODO nested props
20
20
  constructor(options) {
21
+ this.lastUpdate = new Date().getTime();
22
+ this.updateDebounceTime = 1000;
21
23
  this.options = { ...exports.DEFAULT_PROPS, ...options };
22
24
  // TRAVERSAL
23
25
  // temporary storage to hold the traversed tiles during a traversal
@@ -35,6 +37,9 @@ class TilesetTraverser {
35
37
  // tiles does not have render content
36
38
  this.emptyTiles = {};
37
39
  }
40
+ get traversalFinished() {
41
+ return true;
42
+ }
38
43
  // tiles should be visible
39
44
  traverse(root, frameState, options) {
40
45
  this.root = root; // for root screen space error
@@ -110,7 +115,11 @@ class TilesetTraverser {
110
115
  // 4. update tile refine prop and parent refinement status to trickle down to the descendants
111
116
  tile._shouldRefine = shouldRefine && parentRefines;
112
117
  }
113
- this.options.onTraversalEnd(frameState);
118
+ const newTime = new Date().getTime();
119
+ if (this.traversalFinished || newTime - this.lastUpdate > this.updateDebounceTime) {
120
+ this.lastUpdate = newTime;
121
+ this.options.onTraversalEnd(frameState);
122
+ }
114
123
  }
115
124
  updateChildTiles(tile, frameState) {
116
125
  const children = tile.children;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/tiles",
3
- "version": "3.1.7",
3
+ "version": "3.2.0-alpha.2",
4
4
  "description": "Common components for different tiles loaders.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -33,8 +33,8 @@
33
33
  "build-bundle": "esbuild src/bundle.ts --bundle --outfile=dist/dist.min.js"
34
34
  },
35
35
  "dependencies": {
36
- "@loaders.gl/loader-utils": "3.1.7",
37
- "@loaders.gl/math": "3.1.7",
36
+ "@loaders.gl/loader-utils": "3.2.0-alpha.2",
37
+ "@loaders.gl/math": "3.2.0-alpha.2",
38
38
  "@math.gl/core": "^3.5.1",
39
39
  "@math.gl/culling": "^3.5.1",
40
40
  "@math.gl/geospatial": "^3.5.1",
@@ -42,7 +42,7 @@
42
42
  "@probe.gl/stats": "^3.5.0"
43
43
  },
44
44
  "peerDependencies": {
45
- "@loaders.gl/core": "^3.1.0"
45
+ "@loaders.gl/core": "3.2.0-alpha.1"
46
46
  },
47
- "gitHead": "e48d29e426e9f23879875763e73efc5c58345be1"
47
+ "gitHead": "52a602739cbfce60fc314f474efc984d199dff78"
48
48
  }
@@ -1,3 +1,4 @@
1
+ import {Tile3D} from '@loaders.gl/tiles';
1
2
  import {Vector3} from '@math.gl/core';
2
3
  import {CullingVolume, Plane} from '@math.gl/culling';
3
4
  import {Ellipsoid} from '@math.gl/geospatial';
@@ -9,6 +10,7 @@ export type FrameState = {
9
10
  up: number[];
10
11
  };
11
12
  viewport: {[key: string]: any};
13
+ topDownViewport: {[key: string]: any}; // Use it to calculate projected radius for a tile
12
14
  height: number;
13
15
  cullingVolume: CullingVolume;
14
16
  frameNumber: number; // TODO: This can be the same between updates, what number is unique for between updates?
@@ -60,6 +62,19 @@ export function getFrameState(viewport, frameNumber: number): FrameState {
60
62
 
61
63
  commonSpacePlanesToWGS84(viewport, viewportCenterCartesian);
62
64
 
65
+ const ViewportClass = viewport.constructor;
66
+ const {longitude, latitude, width, bearing, zoom} = viewport;
67
+ // @ts-ignore
68
+ const topDownViewport = new ViewportClass({
69
+ longitude,
70
+ latitude,
71
+ height,
72
+ width,
73
+ bearing,
74
+ zoom,
75
+ pitch: 0
76
+ });
77
+
63
78
  // TODO: make a file/class for frameState and document what needs to be attached to this so that traversal can function
64
79
  return {
65
80
  camera: {
@@ -68,6 +83,7 @@ export function getFrameState(viewport, frameNumber: number): FrameState {
68
83
  up: cameraUpCartesian
69
84
  },
70
85
  viewport,
86
+ topDownViewport,
71
87
  height,
72
88
  cullingVolume,
73
89
  frameNumber, // TODO: This can be the same between updates, what number is unique for between updates?
@@ -75,6 +91,46 @@ export function getFrameState(viewport, frameNumber: number): FrameState {
75
91
  };
76
92
  }
77
93
 
94
+ /**
95
+ * Limit `tiles` array length with `maximumTilesSelected` number.
96
+ * The criteria for this filtering is distance of a tile center
97
+ * to the `frameState.viewport`'s longitude and latitude
98
+ * @param tiles - tiles array to filter
99
+ * @param frameState - frameState to calculate distances
100
+ * @param maximumTilesSelected - maximal amount of tiles in the output array
101
+ * @returns new tiles array
102
+ */
103
+ export function limitSelectedTiles(
104
+ tiles: Tile3D[],
105
+ frameState: FrameState,
106
+ maximumTilesSelected: number
107
+ ): [Tile3D[], Tile3D[]] {
108
+ if (maximumTilesSelected === 0 || tiles.length <= maximumTilesSelected) {
109
+ return [tiles, []];
110
+ }
111
+ // Accumulate distances in couples array: [tileIndex: number, distanceToViewport: number]
112
+ const tuples: [number, number][] = [];
113
+ const {longitude: viewportLongitude, latitude: viewportLatitude} = frameState.viewport;
114
+ for (const [index, tile] of tiles.entries()) {
115
+ const [longitude, latitude] = tile.header.mbs;
116
+ const deltaLon = Math.abs(viewportLongitude - longitude);
117
+ const deltaLat = Math.abs(viewportLatitude - latitude);
118
+ const distance = Math.sqrt(deltaLat * deltaLat + deltaLon * deltaLon);
119
+ tuples.push([index, distance]);
120
+ }
121
+ const tuplesSorted = tuples.sort((a, b) => a[1] - b[1]);
122
+ const selectedTiles: Tile3D[] = [];
123
+ for (let i = 0; i < maximumTilesSelected; i++) {
124
+ selectedTiles.push(tiles[tuplesSorted[i][0]]);
125
+ }
126
+ const unselectedTiles: Tile3D[] = [];
127
+ for (let i = maximumTilesSelected; i < tuplesSorted.length; i++) {
128
+ unselectedTiles.push(tiles[tuplesSorted[i][0]]);
129
+ }
130
+
131
+ return [selectedTiles, unselectedTiles];
132
+ }
133
+
78
134
  function commonSpacePlanesToWGS84(viewport, viewportCenterCartesian) {
79
135
  // Extract frustum planes based on current view.
80
136
  const frustumPlanes = viewport.getFrustumPlanes();