@loaders.gl/tiles 5.0.0-alpha.6 → 5.0.0-alpha.8

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 (114) hide show
  1. package/README.md +26 -0
  2. package/dist/dist.dev.js +10015 -8172
  3. package/dist/dist.min.js +3 -4
  4. package/dist/index.cjs +1676 -477
  5. package/dist/index.cjs.map +3 -3
  6. package/dist/index.d.ts +10 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +4 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/spatial/format-spatial-reference.d.ts +1 -0
  11. package/dist/spatial/format-spatial-reference.d.ts.map +1 -1
  12. package/dist/spatial/format-spatial-reference.js +104 -46
  13. package/dist/spatial/format-spatial-reference.js.map +1 -1
  14. package/dist/spatial/get-spatial-coordinate-frame.d.ts +12 -1
  15. package/dist/spatial/get-spatial-coordinate-frame.d.ts.map +1 -1
  16. package/dist/spatial/get-spatial-coordinate-frame.js +105 -24
  17. package/dist/spatial/get-spatial-coordinate-frame.js.map +1 -1
  18. package/dist/spatial/normalize-crs-identifier.d.ts +15 -0
  19. package/dist/spatial/normalize-crs-identifier.d.ts.map +1 -0
  20. package/dist/spatial/normalize-crs-identifier.js +22 -0
  21. package/dist/spatial/normalize-crs-identifier.js.map +1 -0
  22. package/dist/spatial/spatial-coordinate-transformer.d.ts +4 -0
  23. package/dist/spatial/spatial-coordinate-transformer.d.ts.map +1 -1
  24. package/dist/spatial/spatial-coordinate-transformer.js +102 -18
  25. package/dist/spatial/spatial-coordinate-transformer.js.map +1 -1
  26. package/dist/spatial/spatial-resource-registry.js +3 -3
  27. package/dist/spatial/spatial-resource-registry.js.map +1 -1
  28. package/dist/spatial/tiles-3d-spatial-transformer.d.ts +32 -0
  29. package/dist/spatial/tiles-3d-spatial-transformer.d.ts.map +1 -0
  30. package/dist/spatial/tiles-3d-spatial-transformer.js +175 -0
  31. package/dist/spatial/tiles-3d-spatial-transformer.js.map +1 -0
  32. package/dist/tileset-3d/common/tile-3d-contracts.d.ts +63 -0
  33. package/dist/tileset-3d/common/tile-3d-contracts.d.ts.map +1 -0
  34. package/dist/tileset-3d/common/tile-3d-contracts.js +51 -0
  35. package/dist/tileset-3d/common/tile-3d-contracts.js.map +1 -0
  36. package/dist/tileset-3d/common/tile-3d.d.ts +33 -5
  37. package/dist/tileset-3d/common/tile-3d.d.ts.map +1 -1
  38. package/dist/tileset-3d/common/tile-3d.js +179 -29
  39. package/dist/tileset-3d/common/tile-3d.js.map +1 -1
  40. package/dist/tileset-3d/common/tileset-3d.d.ts +15 -25
  41. package/dist/tileset-3d/common/tileset-3d.d.ts.map +1 -1
  42. package/dist/tileset-3d/common/tileset-3d.js +35 -42
  43. package/dist/tileset-3d/common/tileset-3d.js.map +1 -1
  44. package/dist/tileset-3d/common/tileset-content-traversal.d.ts +37 -0
  45. package/dist/tileset-3d/common/tileset-content-traversal.d.ts.map +1 -0
  46. package/dist/tileset-3d/common/tileset-content-traversal.js +80 -0
  47. package/dist/tileset-3d/common/tileset-content-traversal.js.map +1 -0
  48. package/dist/tileset-3d/common/tileset-observability.d.ts +60 -0
  49. package/dist/tileset-3d/common/tileset-observability.d.ts.map +1 -0
  50. package/dist/tileset-3d/common/tileset-observability.js +39 -0
  51. package/dist/tileset-3d/common/tileset-observability.js.map +1 -0
  52. package/dist/tileset-3d/common/tileset-source.d.ts +11 -1
  53. package/dist/tileset-3d/common/tileset-source.d.ts.map +1 -1
  54. package/dist/tileset-3d/common/tileset-source.js.map +1 -1
  55. package/dist/tileset-3d/common/tileset-traverser.d.ts.map +1 -1
  56. package/dist/tileset-3d/common/tileset-traverser.js +4 -3
  57. package/dist/tileset-3d/common/tileset-traverser.js.map +1 -1
  58. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts +47 -1
  59. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts.map +1 -1
  60. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js +327 -30
  61. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js.map +1 -1
  62. package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts +34 -0
  63. package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts.map +1 -1
  64. package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js +278 -14
  65. package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js.map +1 -1
  66. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts +5 -3
  67. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts.map +1 -1
  68. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js +7 -4
  69. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js.map +1 -1
  70. package/dist/tileset-3d/format-i3s/i3s-source.d.ts +4 -2
  71. package/dist/tileset-3d/format-i3s/i3s-source.d.ts.map +1 -1
  72. package/dist/tileset-3d/format-i3s/i3s-source.js +60 -9
  73. package/dist/tileset-3d/format-i3s/i3s-source.js.map +1 -1
  74. package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.d.ts.map +1 -1
  75. package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.js +1 -1
  76. package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.js.map +1 -1
  77. package/dist/tileset-3d/helpers/bounding-volume.d.ts +7 -3
  78. package/dist/tileset-3d/helpers/bounding-volume.d.ts.map +1 -1
  79. package/dist/tileset-3d/helpers/bounding-volume.js +19 -61
  80. package/dist/tileset-3d/helpers/bounding-volume.js.map +1 -1
  81. package/dist/tileset-3d/helpers/frame-state.d.ts +5 -0
  82. package/dist/tileset-3d/helpers/frame-state.d.ts.map +1 -1
  83. package/dist/tileset-3d/helpers/frame-state.js +11 -5
  84. package/dist/tileset-3d/helpers/frame-state.js.map +1 -1
  85. package/dist/tileset-3d/helpers/s2-bounding-volume.d.ts +17 -0
  86. package/dist/tileset-3d/helpers/s2-bounding-volume.d.ts.map +1 -0
  87. package/dist/tileset-3d/helpers/s2-bounding-volume.js +20 -0
  88. package/dist/tileset-3d/helpers/s2-bounding-volume.js.map +1 -0
  89. package/dist/types.d.ts +2 -0
  90. package/dist/types.d.ts.map +1 -1
  91. package/package.json +11 -12
  92. package/src/index.ts +18 -1
  93. package/src/spatial/format-spatial-reference.ts +127 -53
  94. package/src/spatial/get-spatial-coordinate-frame.ts +126 -31
  95. package/src/spatial/normalize-crs-identifier.ts +26 -0
  96. package/src/spatial/spatial-coordinate-transformer.ts +124 -24
  97. package/src/spatial/spatial-resource-registry.ts +3 -3
  98. package/src/spatial/tiles-3d-spatial-transformer.ts +206 -0
  99. package/src/tileset-3d/common/tile-3d-contracts.ts +115 -0
  100. package/src/tileset-3d/common/tile-3d.ts +208 -32
  101. package/src/tileset-3d/common/tileset-3d.ts +37 -61
  102. package/src/tileset-3d/common/tileset-content-traversal.ts +114 -0
  103. package/src/tileset-3d/common/tileset-observability.ts +100 -0
  104. package/src/tileset-3d/common/tileset-source.ts +19 -1
  105. package/src/tileset-3d/common/tileset-traverser.ts +4 -3
  106. package/src/tileset-3d/format-3d-tiles/implicit-tiling.ts +481 -34
  107. package/src/tileset-3d/format-3d-tiles/tiles-3d-source.ts +405 -14
  108. package/src/tileset-3d/format-3d-tiles/tileset-3d-traverser.ts +7 -4
  109. package/src/tileset-3d/format-i3s/i3s-source.ts +84 -13
  110. package/src/tileset-3d/format-i3s/i3s-tileset-traverser.ts +2 -1
  111. package/src/tileset-3d/helpers/bounding-volume.ts +29 -62
  112. package/src/tileset-3d/helpers/frame-state.ts +15 -7
  113. package/src/tileset-3d/helpers/s2-bounding-volume.ts +35 -0
  114. package/src/types.ts +2 -0
@@ -0,0 +1,114 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {Tile3D} from './tile-3d';
6
+ import type {Tileset3D} from './tileset-3d';
7
+ import type {TileContentLoadResult} from './tileset-source';
8
+ import type {Tile3DContent} from './tile-3d-contracts';
9
+ import {TILESET_TYPE} from '../../constants';
10
+
11
+ /** Options for complete camera-independent tileset content traversal. */
12
+ export interface TraverseTilesetContentsOptions {
13
+ /** Cancel traversal and stop issuing further source requests. */
14
+ readonly signal?: AbortSignal;
15
+ /**
16
+ * Unload content loaded by this traversal when iteration advances or closes, including on error.
17
+ * Defaults to false. Preloaded content is retained. Use a runtime dedicated to this traversal;
18
+ * consume payloads before advancing and do not retain them or update the runtime concurrently.
19
+ */
20
+ readonly unloadContent?: boolean;
21
+ }
22
+
23
+ /** One tile placement and its ordered content entries from a completed source read. */
24
+ export interface TilesetContentTraversalItem {
25
+ /** Runtime tile placement. Shared content resources are yielded once per placement. */
26
+ readonly tile: Tile3D;
27
+ /** Ordered content entries, including multiple contents declared by a single tile. */
28
+ readonly contents: readonly Tile3DContent[];
29
+ }
30
+
31
+ /**
32
+ * Walks every declared tile placement and its loaded content without a camera or visibility test.
33
+ *
34
+ * Source implementations remain responsible for lazy subtree and node-page resolution. Children
35
+ * are visited in declaration order, nested tilesets are installed by the source before descent,
36
+ * and repeated resource URLs are not deduplicated because each placement can have a distinct
37
+ * transform. Content stays attached unless `unloadContent` is enabled. In that mode, newly loaded
38
+ * payloads are valid until iteration advances or closes. Tile placements and children remain
39
+ * available; callers still own the tileset, source, and archive lifetime.
40
+ *
41
+ * @param tileset - Initialized or initializing source-backed tileset runtime.
42
+ * @param options - Cancellation and decoded-content lifetime options.
43
+ * @returns One item for each visited tile placement in deterministic depth-first order.
44
+ */
45
+ export async function* traverseTilesetContents(
46
+ tileset: Tileset3D,
47
+ options: TraverseTilesetContentsOptions = {}
48
+ ): AsyncGenerator<TilesetContentTraversalItem> {
49
+ await tileset.tilesetInitializationPromise;
50
+ throwIfAborted(options.signal);
51
+ if (!tileset.root) {
52
+ throw new Error('Tileset initialization completed without a root tile');
53
+ }
54
+
55
+ const stack: Tile3D[] = [tileset.root];
56
+ const visitedTiles = new Set<Tile3D>();
57
+ while (stack.length > 0) {
58
+ throwIfAborted(options.signal);
59
+ const tile = stack.pop() as Tile3D;
60
+ if (visitedTiles.has(tile)) {
61
+ continue;
62
+ }
63
+ visitedTiles.add(tile);
64
+
65
+ if (tile.header.implicitSubtree && tile.childrenState !== 'ready') {
66
+ const loadChildren = tileset.source.loadTileChildrenForTraversal;
67
+ if (!loadChildren) {
68
+ throw new Error('Tileset source does not support camera-independent subtree loading');
69
+ }
70
+ const result = await loadChildren.call(tileset.source, tile, options.signal);
71
+ if (!result.loaded) {
72
+ throw new Error(`Unable to load implicit subtree for tile ${tile.id}`);
73
+ }
74
+ tile.childrenState = 'ready';
75
+ }
76
+
77
+ if (tileset.type === TILESET_TYPE.I3S && tileset.source.loadTileChildrenForTraversal) {
78
+ const result = await tileset.source.loadTileChildrenForTraversal(tile, options.signal);
79
+ if (!result.loaded) {
80
+ throw new Error(`Unable to load I3S child nodes for tile ${tile.id}`);
81
+ }
82
+ }
83
+
84
+ throwIfAborted(options.signal);
85
+ const loadsContent = tile.contentUrls.length > 0 && !tile.content;
86
+ try {
87
+ if (loadsContent) {
88
+ const loadResult: TileContentLoadResult = await tile.loadContentForTraversal();
89
+ throwIfAborted(options.signal);
90
+ if (!loadResult.loaded) {
91
+ throw new Error(`Unable to load tile content for tile ${tile.id}`);
92
+ }
93
+ tileset.source.onTileLoaded?.(tileset, tile, loadResult);
94
+ }
95
+
96
+ yield {tile, contents: tile.contentEntries};
97
+ } finally {
98
+ if (options.unloadContent && loadsContent) {
99
+ tile.unloadContent();
100
+ }
101
+ }
102
+
103
+ for (let childIndex = tile.children.length - 1; childIndex >= 0; childIndex--) {
104
+ stack.push(tile.children[childIndex]);
105
+ }
106
+ }
107
+ }
108
+
109
+ /** Throws the signal reason when traversal is cancelled. */
110
+ function throwIfAborted(signal?: AbortSignal): void {
111
+ if (signal?.aborted) {
112
+ throw signal.reason ?? new DOMException('The operation was aborted', 'AbortError');
113
+ }
114
+ }
@@ -0,0 +1,100 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) vis.gl contributors
3
+
4
+ import type {Tileset3D} from './tileset-3d';
5
+ import type {Tile3D} from './tile-3d';
6
+
7
+ /**
8
+ * A deterministic, renderer-neutral snapshot of one {@link Tileset3D} traversal.
9
+ *
10
+ * Tile IDs are sorted so snapshots can be compared across runs even when child requests complete
11
+ * in a different order. Counts are reported for the completed traversal frame and cache values are
12
+ * expressed in bytes. This is an inspection contract; it does not alter traversal or request policy.
13
+ */
14
+ export type Tileset3DTraversalSnapshot = {
15
+ /** Monotonically increasing traversal frame number. */
16
+ frameNumber: number;
17
+ /** IDs selected for rendering, sorted for stable comparisons. */
18
+ selectedTileIds: string[];
19
+ /** IDs whose content was requested, sorted for stable comparisons. */
20
+ requestedTileIds: string[];
21
+ /** IDs visited as hierarchy-only or empty tiles, sorted for stable comparisons. */
22
+ emptyTileIds: string[];
23
+ /** Number of selected tiles in the completed frame. */
24
+ visibleTileCount: number;
25
+ /** Number of selected tiles with renderable content. */
26
+ renderableTileCount: number;
27
+ /** Number of tile or subtree loads currently in flight. */
28
+ loadingTileCount: number;
29
+ /** Cumulative number of tiles loaded into the runtime cache. */
30
+ loadedTileCount: number;
31
+ /** Cumulative number of failed tile loads. */
32
+ failedTileCount: number;
33
+ /** Number of tiles currently retained in the runtime cache. */
34
+ cachedTileCount: number;
35
+ /** Estimated cached content bytes. */
36
+ cacheBytes: number;
37
+ /** Active memory-adjusted maximum SSE in logical/CSS pixels. */
38
+ maximumScreenSpaceError: number;
39
+ /** Source-specific implicit subtree counters, when the source exposes them. */
40
+ implicitTiling?: {
41
+ /** Number of subtree resources requested from the source. */
42
+ requestedSubtrees: number;
43
+ /** Number of subtree resources successfully materialized. */
44
+ loadedSubtrees: number;
45
+ /** Number of requests served by the parsed-subtree cache. */
46
+ cacheHits: number;
47
+ /** Number of parsed subtrees currently retained for reuse. */
48
+ cachedSubtrees: number;
49
+ /** Number of subtree requests currently in flight. */
50
+ pendingSubtrees: number;
51
+ /** Number of runtime tile headers created from materialized subtrees. */
52
+ materializedTiles: number;
53
+ };
54
+ };
55
+
56
+ /**
57
+ * Creates a stable observability snapshot from public {@link Tileset3D} state.
58
+ *
59
+ * The helper intentionally reads only public runtime fields and source diagnostics. It is safe to
60
+ * call from an instrumentation loop and does not retain tile or content references.
61
+ *
62
+ * @param tileset - Runtime whose most recent traversal should be inspected.
63
+ * @returns A serializable snapshot suitable for logs, regression fixtures, and benchmark output.
64
+ */
65
+ export function getTileset3DTraversalSnapshot(tileset: Tileset3D): Tileset3DTraversalSnapshot {
66
+ const selectedTiles = tileset.selectedTiles.slice();
67
+ const requestedTiles = tileset.requestedTiles.slice();
68
+ const emptyTiles = tileset.emptyTiles.slice();
69
+
70
+ const getTileIds = (tiles: readonly Tile3D[]): string[] =>
71
+ tiles.map(tile => String(tile.id)).sort();
72
+
73
+ const getStatCount = (name: string): number => {
74
+ const count = tileset.stats.get(name).count;
75
+ return typeof count === 'number' && Number.isFinite(count) ? count : 0;
76
+ };
77
+
78
+ const implicitTilingSource = tileset.source as Tileset3D['source'] & {
79
+ getImplicitTilingStats?: () => Tileset3DTraversalSnapshot['implicitTiling'];
80
+ };
81
+ const implicitTiling = implicitTilingSource.getImplicitTilingStats?.();
82
+
83
+ return {
84
+ frameNumber: tileset.frameNumber,
85
+ selectedTileIds: getTileIds(selectedTiles),
86
+ requestedTileIds: getTileIds(requestedTiles),
87
+ emptyTileIds: getTileIds(emptyTiles),
88
+ visibleTileCount: selectedTiles.length,
89
+ renderableTileCount: selectedTiles.filter(
90
+ tile => tile.contentAvailable && Boolean(tile.content)
91
+ ).length,
92
+ loadingTileCount: getStatCount('Tiles Loading'),
93
+ loadedTileCount: getStatCount('Tiles Loaded'),
94
+ failedTileCount: getStatCount('Failed Tile Loads'),
95
+ cachedTileCount: getStatCount('Tiles In Memory'),
96
+ cacheBytes: tileset.gpuMemoryUsageInBytes,
97
+ maximumScreenSpaceError: tileset.memoryAdjustedScreenSpaceError,
98
+ ...(implicitTiling ? {implicitTiling} : {})
99
+ };
100
+ }
@@ -10,6 +10,7 @@ import type {Tileset3D} from './tileset-3d';
10
10
  import type {FrameState} from '../helpers/frame-state';
11
11
  import type {TILESET_TYPE} from '../../constants';
12
12
  import type {TilesetSpatialReference} from '../../spatial/spatial-types';
13
+ import type {Tile3DContent} from './tile-3d-contracts';
13
14
 
14
15
  /**
15
16
  * Parsed top-level tileset payload consumed by {@link Tileset3D} or a {@link Tileset3DSource}.
@@ -68,6 +69,8 @@ export type TileContentLoadResult = {
68
69
  loaded: boolean;
69
70
  /** All payloads loaded for a tile, in source order. */
70
71
  contents?: any[];
72
+ /** Optional normalized renderer-neutral descriptors for each content entry. */
73
+ contentEntries?: Tile3DContent[];
71
74
  /** Nested tileset metadata to install below the loaded tile, if any. */
72
75
  nestedTileset?: TilesetJSON;
73
76
  /** Nested tilesets found among multiple content payloads. */
@@ -218,6 +221,17 @@ export interface Tileset3DSource {
218
221
  */
219
222
  loadTileChildren?(tile: Tile3D, frameState: FrameState): Promise<TileChildrenLoadResult>;
220
223
 
224
+ /**
225
+ * Loads all source-managed child headers without requiring camera or visibility state.
226
+ *
227
+ * This hook is used by complete dataset operations such as conversion. Implementations retain
228
+ * ownership of implicit subtrees, node pages, archive resolution, and query inheritance.
229
+ */
230
+ loadTileChildrenForTraversal?(
231
+ tile: Tile3D,
232
+ signal?: AbortSignal
233
+ ): Promise<TileChildrenLoadResult>;
234
+
221
235
  /**
222
236
  * Resolves a tile-relative path to the final request URL.
223
237
  */
@@ -236,7 +250,11 @@ export interface Tileset3DSource {
236
250
  /**
237
251
  * Loads child tile metadata on demand for formats that do not expose the full tree up front.
238
252
  */
239
- loadChildTileHeader?(parentTile: Tile3D, childId: string, frameState: FrameState): Promise<any>;
253
+ loadChildTileHeader?(
254
+ parentTile: Tile3D,
255
+ childId: string,
256
+ frameState: FrameState | null
257
+ ): Promise<any>;
240
258
 
241
259
  /**
242
260
  * Updates source-managed bookkeeping after a tile finishes loading.
@@ -219,9 +219,10 @@ export class TilesetTraverser {
219
219
  }
220
220
  stack.push(child);
221
221
  hasVisibleChild = true;
222
- } else if (checkRefines || loadSiblings) {
223
- // Keep non-visible children loaded since they are still needed before the parent can refine.
224
- // Or loadSiblings is true so always load tiles regardless of visibility.
222
+ } else if ((checkRefines || loadSiblings) && child._inRequestVolume) {
223
+ // Keep non-visible children loaded when they are inside their viewer request volume;
224
+ // they may still be needed before a replacement parent can refine. The request-volume
225
+ // check intentionally applies to sibling loading as well, preventing off-volume work.
225
226
  this.loadTile(child, frameState);
226
227
  this.touchTile(child, frameState);
227
228
  }