@loaders.gl/tiles 4.4.2 → 5.0.0-alpha.1

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 (198) hide show
  1. package/README.md +110 -1
  2. package/dist/dist.dev.js +4359 -1950
  3. package/dist/dist.min.js +1 -1
  4. package/dist/image-set.d.ts +94 -0
  5. package/dist/image-set.d.ts.map +1 -0
  6. package/dist/image-set.js +243 -0
  7. package/dist/image-set.js.map +1 -0
  8. package/dist/index.cjs +4178 -1892
  9. package/dist/index.cjs.map +4 -4
  10. package/dist/index.d.ts +27 -9
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +17 -8
  13. package/dist/index.js.map +1 -1
  14. package/dist/point-cloud/point-cloud-tile.d.ts +47 -0
  15. package/dist/point-cloud/point-cloud-tile.d.ts.map +1 -0
  16. package/dist/point-cloud/point-cloud-tile.js +67 -0
  17. package/dist/point-cloud/point-cloud-tile.js.map +1 -0
  18. package/dist/point-cloud/point-cloud-tileset.d.ts +131 -0
  19. package/dist/point-cloud/point-cloud-tileset.d.ts.map +1 -0
  20. package/dist/point-cloud/point-cloud-tileset.js +507 -0
  21. package/dist/point-cloud/point-cloud-tileset.js.map +1 -0
  22. package/dist/point-cloud/types.d.ts +64 -0
  23. package/dist/point-cloud/types.d.ts.map +1 -0
  24. package/dist/point-cloud/types.js +2 -0
  25. package/dist/point-cloud/types.js.map +1 -0
  26. package/dist/raster-set.d.ts +107 -0
  27. package/dist/raster-set.d.ts.map +1 -0
  28. package/dist/raster-set.js +268 -0
  29. package/dist/raster-set.js.map +1 -0
  30. package/dist/tileset-2d/adapter.d.ts +38 -0
  31. package/dist/tileset-2d/adapter.d.ts.map +1 -0
  32. package/dist/tileset-2d/adapter.js +5 -0
  33. package/dist/tileset-2d/adapter.js.map +1 -0
  34. package/dist/tileset-2d/index.d.ts +7 -0
  35. package/dist/tileset-2d/index.d.ts.map +1 -0
  36. package/dist/tileset-2d/index.js +6 -0
  37. package/dist/tileset-2d/index.js.map +1 -0
  38. package/dist/tileset-2d/tile-2d-header.d.ts +68 -0
  39. package/dist/tileset-2d/tile-2d-header.d.ts.map +1 -0
  40. package/dist/tileset-2d/tile-2d-header.js +181 -0
  41. package/dist/tileset-2d/tile-2d-header.js.map +1 -0
  42. package/dist/tileset-2d/tileset-2d.d.ts +201 -0
  43. package/dist/tileset-2d/tileset-2d.d.ts.map +1 -0
  44. package/dist/tileset-2d/tileset-2d.js +532 -0
  45. package/dist/tileset-2d/tileset-2d.js.map +1 -0
  46. package/dist/tileset-2d/types.d.ts +44 -0
  47. package/dist/tileset-2d/types.d.ts.map +1 -0
  48. package/dist/tileset-2d/types.js +5 -0
  49. package/dist/tileset-2d/types.js.map +1 -0
  50. package/dist/tileset-2d.d.ts +2 -0
  51. package/dist/tileset-2d.d.ts.map +1 -0
  52. package/dist/tileset-2d.js +5 -0
  53. package/dist/tileset-2d.js.map +1 -0
  54. package/dist/tileset-3d/common/indexed-archive-tileset-source.d.ts +60 -0
  55. package/dist/tileset-3d/common/indexed-archive-tileset-source.d.ts.map +1 -0
  56. package/dist/tileset-3d/common/indexed-archive-tileset-source.js +125 -0
  57. package/dist/tileset-3d/common/indexed-archive-tileset-source.js.map +1 -0
  58. package/dist/{tileset → tileset-3d/common}/tile-3d.d.ts +36 -27
  59. package/dist/tileset-3d/common/tile-3d.d.ts.map +1 -0
  60. package/dist/{tileset → tileset-3d/common}/tile-3d.js +53 -62
  61. package/dist/tileset-3d/common/tile-3d.js.map +1 -0
  62. package/dist/tileset-3d/common/tileset-3d.d.ts +177 -0
  63. package/dist/tileset-3d/common/tileset-3d.d.ts.map +1 -0
  64. package/dist/tileset-3d/common/tileset-3d.js +566 -0
  65. package/dist/tileset-3d/common/tileset-3d.js.map +1 -0
  66. package/dist/tileset-3d/common/tileset-cache.d.ts.map +1 -0
  67. package/dist/{tileset → tileset-3d/common}/tileset-cache.js +1 -1
  68. package/dist/tileset-3d/common/tileset-cache.js.map +1 -0
  69. package/dist/tileset-3d/common/tileset-source.d.ts +186 -0
  70. package/dist/tileset-3d/common/tileset-source.d.ts.map +1 -0
  71. package/dist/tileset-3d/common/tileset-source.js +17 -0
  72. package/dist/tileset-3d/common/tileset-source.js.map +1 -0
  73. package/dist/{tileset → tileset-3d/common}/tileset-traverser.d.ts +2 -2
  74. package/dist/tileset-3d/common/tileset-traverser.d.ts.map +1 -0
  75. package/dist/{tileset → tileset-3d/common}/tileset-traverser.js +2 -2
  76. package/dist/tileset-3d/common/tileset-traverser.js.map +1 -0
  77. package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts +100 -0
  78. package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts.map +1 -0
  79. package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js +312 -0
  80. package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js.map +1 -0
  81. package/dist/{tileset → tileset-3d}/format-3d-tiles/tileset-3d-traverser.d.ts +1 -1
  82. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts.map +1 -0
  83. package/dist/{tileset → tileset-3d}/format-3d-tiles/tileset-3d-traverser.js +1 -1
  84. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js.map +1 -0
  85. package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.d.ts.map +1 -0
  86. package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.js.map +1 -0
  87. package/dist/tileset-3d/format-i3s/i3s-source.d.ts +99 -0
  88. package/dist/tileset-3d/format-i3s/i3s-source.d.ts.map +1 -0
  89. package/dist/tileset-3d/format-i3s/i3s-source.js +299 -0
  90. package/dist/tileset-3d/format-i3s/i3s-source.js.map +1 -0
  91. package/dist/tileset-3d/format-i3s/i3s-tile-manager.d.ts.map +1 -0
  92. package/dist/{tileset → tileset-3d}/format-i3s/i3s-tile-manager.js +2 -2
  93. package/dist/tileset-3d/format-i3s/i3s-tile-manager.js.map +1 -0
  94. package/dist/{tileset → tileset-3d}/format-i3s/i3s-tileset-traverser.d.ts +2 -2
  95. package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.d.ts.map +1 -0
  96. package/dist/{tileset → tileset-3d}/format-i3s/i3s-tileset-traverser.js +14 -23
  97. package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.js.map +1 -0
  98. package/dist/{tileset → tileset-3d}/helpers/3d-tiles-options.d.ts +1 -1
  99. package/dist/tileset-3d/helpers/3d-tiles-options.d.ts.map +1 -0
  100. package/dist/tileset-3d/helpers/3d-tiles-options.js.map +1 -0
  101. package/dist/tileset-3d/helpers/bounding-volume.d.ts.map +1 -0
  102. package/dist/tileset-3d/helpers/bounding-volume.js.map +1 -0
  103. package/dist/{tileset → tileset-3d}/helpers/frame-state.d.ts +1 -1
  104. package/dist/tileset-3d/helpers/frame-state.d.ts.map +1 -0
  105. package/dist/tileset-3d/helpers/frame-state.js.map +1 -0
  106. package/dist/{tileset → tileset-3d}/helpers/i3s-lod.d.ts +1 -1
  107. package/dist/tileset-3d/helpers/i3s-lod.d.ts.map +1 -0
  108. package/dist/{tileset → tileset-3d}/helpers/i3s-lod.js +1 -1
  109. package/dist/tileset-3d/helpers/i3s-lod.js.map +1 -0
  110. package/dist/tileset-3d/helpers/tiles-3d-lod.d.ts +20 -0
  111. package/dist/tileset-3d/helpers/tiles-3d-lod.d.ts.map +1 -0
  112. package/dist/{tileset → tileset-3d}/helpers/tiles-3d-lod.js +43 -4
  113. package/dist/tileset-3d/helpers/tiles-3d-lod.js.map +1 -0
  114. package/dist/{tileset → tileset-3d}/helpers/transform-utils.d.ts +1 -1
  115. package/dist/tileset-3d/helpers/transform-utils.d.ts.map +1 -0
  116. package/dist/tileset-3d/helpers/transform-utils.js.map +1 -0
  117. package/dist/tileset-3d/helpers/zoom.d.ts.map +1 -0
  118. package/dist/tileset-3d/helpers/zoom.js.map +1 -0
  119. package/dist/types.d.ts +7 -0
  120. package/dist/types.d.ts.map +1 -1
  121. package/package.json +7 -6
  122. package/src/image-set.ts +328 -0
  123. package/src/index.ts +80 -9
  124. package/src/point-cloud/point-cloud-tile.ts +76 -0
  125. package/src/point-cloud/point-cloud-tileset.ts +709 -0
  126. package/src/point-cloud/types.ts +78 -0
  127. package/src/raster-set.ts +374 -0
  128. package/src/tileset-2d/adapter.ts +47 -0
  129. package/src/tileset-2d/index.ts +33 -0
  130. package/src/tileset-2d/tile-2d-header.ts +224 -0
  131. package/src/tileset-2d/tileset-2d.ts +716 -0
  132. package/src/tileset-2d/types.ts +39 -0
  133. package/src/tileset-2d.ts +5 -0
  134. package/src/tileset-3d/common/indexed-archive-tileset-source.ts +205 -0
  135. package/src/{tileset → tileset-3d/common}/tile-3d.ts +64 -73
  136. package/src/tileset-3d/common/tileset-3d.ts +736 -0
  137. package/src/{tileset → tileset-3d/common}/tileset-cache.ts +1 -1
  138. package/src/tileset-3d/common/tileset-source.ts +234 -0
  139. package/src/{tileset → tileset-3d/common}/tileset-traverser.ts +3 -3
  140. package/src/tileset-3d/format-3d-tiles/tiles-3d-source.ts +379 -0
  141. package/src/{tileset → tileset-3d}/format-3d-tiles/tileset-3d-traverser.ts +1 -1
  142. package/src/tileset-3d/format-i3s/i3s-source.ts +366 -0
  143. package/src/{tileset → tileset-3d}/format-i3s/i3s-tile-manager.ts +2 -2
  144. package/src/{tileset → tileset-3d}/format-i3s/i3s-tileset-traverser.ts +15 -24
  145. package/src/{tileset → tileset-3d}/helpers/3d-tiles-options.ts +1 -1
  146. package/src/{tileset → tileset-3d}/helpers/frame-state.ts +1 -1
  147. package/src/{tileset → tileset-3d}/helpers/i3s-lod.ts +2 -2
  148. package/src/{tileset → tileset-3d}/helpers/tiles-3d-lod.ts +46 -4
  149. package/src/{tileset → tileset-3d}/helpers/transform-utils.ts +1 -1
  150. package/src/types.ts +7 -0
  151. package/dist/tileset/format-3d-tiles/tileset-3d-traverser.d.ts.map +0 -1
  152. package/dist/tileset/format-3d-tiles/tileset-3d-traverser.js.map +0 -1
  153. package/dist/tileset/format-i3s/i3s-pending-tiles-register.d.ts.map +0 -1
  154. package/dist/tileset/format-i3s/i3s-pending-tiles-register.js.map +0 -1
  155. package/dist/tileset/format-i3s/i3s-tile-manager.d.ts.map +0 -1
  156. package/dist/tileset/format-i3s/i3s-tile-manager.js.map +0 -1
  157. package/dist/tileset/format-i3s/i3s-tileset-traverser.d.ts.map +0 -1
  158. package/dist/tileset/format-i3s/i3s-tileset-traverser.js.map +0 -1
  159. package/dist/tileset/helpers/3d-tiles-options.d.ts.map +0 -1
  160. package/dist/tileset/helpers/3d-tiles-options.js.map +0 -1
  161. package/dist/tileset/helpers/bounding-volume.d.ts.map +0 -1
  162. package/dist/tileset/helpers/bounding-volume.js.map +0 -1
  163. package/dist/tileset/helpers/frame-state.d.ts.map +0 -1
  164. package/dist/tileset/helpers/frame-state.js.map +0 -1
  165. package/dist/tileset/helpers/i3s-lod.d.ts.map +0 -1
  166. package/dist/tileset/helpers/i3s-lod.js.map +0 -1
  167. package/dist/tileset/helpers/tiles-3d-lod.d.ts +0 -8
  168. package/dist/tileset/helpers/tiles-3d-lod.d.ts.map +0 -1
  169. package/dist/tileset/helpers/tiles-3d-lod.js.map +0 -1
  170. package/dist/tileset/helpers/transform-utils.d.ts.map +0 -1
  171. package/dist/tileset/helpers/transform-utils.js.map +0 -1
  172. package/dist/tileset/helpers/zoom.d.ts.map +0 -1
  173. package/dist/tileset/helpers/zoom.js.map +0 -1
  174. package/dist/tileset/tile-3d.d.ts.map +0 -1
  175. package/dist/tileset/tile-3d.js.map +0 -1
  176. package/dist/tileset/tileset-3d.d.ts +0 -284
  177. package/dist/tileset/tileset-3d.d.ts.map +0 -1
  178. package/dist/tileset/tileset-3d.js +0 -814
  179. package/dist/tileset/tileset-3d.js.map +0 -1
  180. package/dist/tileset/tileset-cache.d.ts.map +0 -1
  181. package/dist/tileset/tileset-cache.js.map +0 -1
  182. package/dist/tileset/tileset-traverser.d.ts.map +0 -1
  183. package/dist/tileset/tileset-traverser.js.map +0 -1
  184. package/src/tileset/tileset-3d.ts +0 -1037
  185. /package/dist/{tileset → tileset-3d/common}/tileset-cache.d.ts +0 -0
  186. /package/dist/{tileset → tileset-3d}/format-i3s/i3s-pending-tiles-register.d.ts +0 -0
  187. /package/dist/{tileset → tileset-3d}/format-i3s/i3s-pending-tiles-register.js +0 -0
  188. /package/dist/{tileset → tileset-3d}/format-i3s/i3s-tile-manager.d.ts +0 -0
  189. /package/dist/{tileset → tileset-3d}/helpers/3d-tiles-options.js +0 -0
  190. /package/dist/{tileset → tileset-3d}/helpers/bounding-volume.d.ts +0 -0
  191. /package/dist/{tileset → tileset-3d}/helpers/bounding-volume.js +0 -0
  192. /package/dist/{tileset → tileset-3d}/helpers/frame-state.js +0 -0
  193. /package/dist/{tileset → tileset-3d}/helpers/transform-utils.js +0 -0
  194. /package/dist/{tileset → tileset-3d}/helpers/zoom.d.ts +0 -0
  195. /package/dist/{tileset → tileset-3d}/helpers/zoom.js +0 -0
  196. /package/src/{tileset → tileset-3d}/format-i3s/i3s-pending-tiles-register.ts +0 -0
  197. /package/src/{tileset → tileset-3d}/helpers/bounding-volume.ts +0 -0
  198. /package/src/{tileset → tileset-3d}/helpers/zoom.ts +0 -0
@@ -0,0 +1,39 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ /** Inclusive minimum and maximum elevation bounds used during tile selection. */
6
+ export type ZRange = [minZ: number, maxZ: number];
7
+
8
+ /** Axis-aligned bounding box represented as `[minX, minY, maxX, maxY]`. */
9
+ export type Bounds = [minX: number, minY: number, maxX: number, maxY: number];
10
+
11
+ /** Geographic tile bounds in longitude/latitude coordinates. */
12
+ export type GeoBoundingBox = {west: number; north: number; east: number; south: number};
13
+
14
+ /** Cartesian tile bounds in layer/world coordinates. */
15
+ export type NonGeoBoundingBox = {left: number; top: number; right: number; bottom: number};
16
+
17
+ /** Tile bounds for either geospatial or cartesian views. */
18
+ export type TileBoundingBox = NonGeoBoundingBox | GeoBoundingBox;
19
+
20
+ /** Tile coordinate in an x/y/z pyramid. */
21
+ export type TileIndex = {x: number; y: number; z: number};
22
+
23
+ /** Information passed to a tile loader for fetching tile content. */
24
+ export type TileLoadProps = {
25
+ /** x/y/z tile coordinate. */
26
+ index: TileIndex;
27
+ /** Stable cache identifier for the tile. */
28
+ id: string;
29
+ /** Bounds covered by the tile in the active coordinate system. */
30
+ bbox: TileBoundingBox;
31
+ /** URL derived from a URL template, if applicable. */
32
+ url?: string | null;
33
+ /** Abort signal for cancelling an in-flight tile request. */
34
+ signal?: AbortSignal;
35
+ /** Optional application metadata associated with the tile. */
36
+ userData?: Record<string, any>;
37
+ /** Resolved zoom level used to request this tile. */
38
+ zoom?: number;
39
+ };
@@ -0,0 +1,5 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ export * from './tileset-2d/index';
@@ -0,0 +1,205 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {BlobFile, HttpFile, path} from '@loaders.gl/loader-utils';
6
+ import type {
7
+ CoreAPI,
8
+ LoaderOptions,
9
+ LoaderWithParser,
10
+ ReadableFile
11
+ } from '@loaders.gl/loader-utils';
12
+ import type {TilesetSourceResolver} from './tileset-source';
13
+
14
+ /** Options for {@link IndexedArchiveTilesetSource}. */
15
+ export type IndexedArchiveTilesetSourceOptions<ArchiveT> = {
16
+ /** Archive URL or Blob. */
17
+ data: string | Blob;
18
+ /** Filename to expose for Blob inputs that do not provide a name. */
19
+ fallbackFilename: string;
20
+ /** Archive file extension used as the URL path marker. */
21
+ archiveExtension: string;
22
+ /** Path to the root metadata resource inside the archive. */
23
+ rootPath: string;
24
+ /** Optional mode passed when loading the root metadata resource. */
25
+ rootMode?: string;
26
+ /** Parses an opened readable file into an indexed archive object. */
27
+ parseArchive: (file: ReadableFile) => Promise<ArchiveT>;
28
+ /** Loads one resource from the parsed archive. */
29
+ getFile: (archive: ArchiveT, pathInArchive: string, mode?: string) => Promise<ArrayBuffer>;
30
+ /** Returns the core API used for local file loading and nested resource parsing. */
31
+ getCoreApi: () => CoreAPI | undefined;
32
+ /** Error message to throw when the core API is required but unavailable. */
33
+ missingCoreApiMessage: string;
34
+ };
35
+
36
+ /**
37
+ * Tileset source resolver backed by an indexed archive such as 3TZ or SLPK.
38
+ *
39
+ * The source owns archive opening, archive caching, path resolution, and archive-backed `fetch`
40
+ * injection. Format-specific parsing and file lookup stay in the owning format module.
41
+ */
42
+ export class IndexedArchiveTilesetSource<ArchiveT> implements TilesetSourceResolver {
43
+ /** URL exposed to the tileset source that owns this archive source. */
44
+ readonly sourceUrl: string;
45
+
46
+ private readonly options: IndexedArchiveTilesetSourceOptions<ArchiveT>;
47
+ private archivePromise?: Promise<ArchiveT>;
48
+
49
+ /**
50
+ * Creates an indexed archive tileset source.
51
+ * @param options Archive source options
52
+ */
53
+ constructor(options: IndexedArchiveTilesetSourceOptions<ArchiveT>) {
54
+ this.options = options;
55
+ this.sourceUrl = getArchiveSourceUrl(options.data, options.fallbackFilename);
56
+ }
57
+
58
+ /**
59
+ * Loads and parses the archive root metadata resource.
60
+ * @param url Root URL, ignored because the archive root path is configured explicitly
61
+ * @param loader Loader used to parse the root metadata
62
+ * @param loadOptions Loader options forwarded to parsing
63
+ */
64
+ async loadRoot<DataT>(
65
+ url: string,
66
+ loader: LoaderWithParser<DataT>,
67
+ loadOptions: LoaderOptions
68
+ ): Promise<DataT> {
69
+ return await this.parseArchiveResource(
70
+ url,
71
+ this.options.rootPath,
72
+ loader,
73
+ loadOptions,
74
+ this.options.rootMode
75
+ );
76
+ }
77
+
78
+ /**
79
+ * Loads and parses an archive resource relative to a requesting resource URL.
80
+ * @param url Resource URL
81
+ * @param loader Loader used to parse the resource
82
+ * @param loadOptions Loader options forwarded to parsing
83
+ */
84
+ async loadResource<DataT>(
85
+ url: string,
86
+ loader: LoaderWithParser<DataT>,
87
+ loadOptions: LoaderOptions
88
+ ): Promise<DataT> {
89
+ const pathInArchive = this.resolveArchivePath(url, url);
90
+ return await this.parseArchiveResource(url, pathInArchive, loader, loadOptions);
91
+ }
92
+
93
+ private async parseArchiveResource<DataT>(
94
+ resourceUrl: string,
95
+ pathInArchive: string,
96
+ loader: LoaderWithParser<DataT>,
97
+ loadOptions: LoaderOptions,
98
+ mode?: string
99
+ ): Promise<DataT> {
100
+ const coreApi = this.options.getCoreApi();
101
+ if (!coreApi) {
102
+ throw new Error(this.options.missingCoreApiMessage);
103
+ }
104
+
105
+ const data = await this.loadFile(pathInArchive, mode);
106
+ const archiveFetch = this.createArchiveFetch(resourceUrl);
107
+ return (await coreApi.parse(
108
+ data,
109
+ loader,
110
+ {
111
+ ...loadOptions,
112
+ fetch: archiveFetch
113
+ },
114
+ {
115
+ url: resourceUrl,
116
+ fetch: archiveFetch,
117
+ _parse: coreApi.parse,
118
+ loaders: [loader],
119
+ coreApi
120
+ } as any
121
+ )) as DataT;
122
+ }
123
+
124
+ private createArchiveFetch(contextUrl: string): typeof fetch {
125
+ return async (input: RequestInfo | URL): Promise<Response> => {
126
+ const requestUrl =
127
+ typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;
128
+ const pathInArchive = this.resolveArchivePath(requestUrl, contextUrl);
129
+ const data = await this.loadFile(pathInArchive);
130
+ return new Response(data, {status: 200});
131
+ };
132
+ }
133
+
134
+ private async loadFile(pathInArchive: string, mode?: string): Promise<ArrayBuffer> {
135
+ this.archivePromise ||= this.openArchiveReadableFile().then(file =>
136
+ this.options.parseArchive(file)
137
+ );
138
+ const archive = await this.archivePromise;
139
+ return await this.options.getFile(archive, pathInArchive, mode);
140
+ }
141
+
142
+ private async openArchiveReadableFile(): Promise<ReadableFile> {
143
+ const {data} = this.options;
144
+ if (typeof data !== 'string') {
145
+ return new BlobFile(data);
146
+ }
147
+
148
+ if (/^https?:\/\//i.test(data)) {
149
+ return new HttpFile(data);
150
+ }
151
+
152
+ const coreApi = this.options.getCoreApi();
153
+ if (!coreApi) {
154
+ throw new Error(this.options.missingCoreApiMessage);
155
+ }
156
+ const response = await coreApi.fetchFile(data);
157
+ return new BlobFile(await response.arrayBuffer());
158
+ }
159
+
160
+ private resolveArchivePath(request: string, baseUrl: string): string {
161
+ const requestWithoutQuery = stripQueryString(request);
162
+ const archiveRoot = stripQueryString(this.sourceUrl);
163
+ const baseWithoutQuery = stripQueryString(baseUrl);
164
+ const basePath =
165
+ baseWithoutQuery === archiveRoot ? archiveRoot : path.dirname(baseWithoutQuery);
166
+ const markerExpression = new RegExp(`\\.${this.options.archiveExtension}/(.*)$`, 'i');
167
+ const markerMatch = requestWithoutQuery.match(markerExpression);
168
+ if (markerMatch?.[1]) {
169
+ return markerMatch[1];
170
+ }
171
+
172
+ const isAbsoluteRequest =
173
+ /^[a-z][a-z0-9+.-]*:/i.test(requestWithoutQuery) || requestWithoutQuery.startsWith('/');
174
+ const absoluteRequest = requestWithoutQuery.startsWith(archiveRoot)
175
+ ? requestWithoutQuery
176
+ : baseWithoutQuery === archiveRoot && !isAbsoluteRequest
177
+ ? `${archiveRoot}/${requestWithoutQuery}`
178
+ : path.resolve(basePath, requestWithoutQuery);
179
+
180
+ if (absoluteRequest === archiveRoot) {
181
+ return '';
182
+ }
183
+
184
+ if (absoluteRequest.startsWith(`${archiveRoot}/`)) {
185
+ return absoluteRequest.slice(archiveRoot.length + 1);
186
+ }
187
+
188
+ return absoluteRequest.replace(/^\/+/, '');
189
+ }
190
+ }
191
+
192
+ function getArchiveSourceUrl(data: string | Blob, fallbackFilename: string): string {
193
+ if (typeof data === 'string') {
194
+ return data;
195
+ }
196
+
197
+ const fileName =
198
+ 'name' in data && typeof data.name === 'string' && data.name ? data.name : fallbackFilename;
199
+ return `memory://${fileName}`;
200
+ }
201
+
202
+ function stripQueryString(url: string): string {
203
+ const queryIndex = url.indexOf('?');
204
+ return queryIndex >= 0 ? url.slice(0, queryIndex) : url;
205
+ }
@@ -8,22 +8,20 @@
8
8
  import {Vector3, Matrix4} from '@math.gl/core';
9
9
  import {CullingVolume} from '@math.gl/culling';
10
10
 
11
- import {load} from '@loaders.gl/core';
12
-
13
11
  // Note: circular dependency
14
12
  import type {Tileset3D} from './tileset-3d';
15
- import type {DoublyLinkedListNode} from '../utils/doubly-linked-list-node';
16
- import {TILE_REFINEMENT, TILE_CONTENT_STATE, TILESET_TYPE} from '../constants';
13
+ import type {DoublyLinkedListNode} from '../../utils/doubly-linked-list-node';
14
+ import {LOD_METRIC_TYPE, TILE_REFINEMENT, TILE_CONTENT_STATE, TILESET_TYPE} from '../../constants';
15
+ import type {TileContentLoadResult} from './tileset-source';
17
16
 
18
- import {FrameState} from './helpers/frame-state';
17
+ import {FrameState} from '../helpers/frame-state';
19
18
  import {
20
19
  createBoundingVolume,
21
20
  getCartographicBounds,
22
21
  CartographicBounds
23
- } from './helpers/bounding-volume';
24
- import {getTiles3DScreenSpaceError} from './helpers/tiles-3d-lod';
25
- import {getProjectedRadius} from './helpers/i3s-lod';
26
- import {get3dTilesOptions} from './helpers/3d-tiles-options';
22
+ } from '../helpers/bounding-volume';
23
+ import {getTiles3DScreenSpaceError} from '../helpers/tiles-3d-lod';
24
+ import {getProjectedRadius} from '../helpers/i3s-lod';
27
25
  import {TilesetTraverser} from './tileset-traverser';
28
26
 
29
27
  const scratchVector = new Vector3();
@@ -62,10 +60,19 @@ export class Tile3D {
62
60
  type: string;
63
61
  contentUrl: string;
64
62
  /** Different refinement algorithms used by I3S and 3D tiles */
65
- lodMetricType: 'geometricError' | 'maxScreenThreshold' = 'geometricError';
66
- /** The error, in meters, introduced if this tile is rendered and its children are not. */
63
+ lodMetricType = 'geometricError';
64
+ /**
65
+ * The world-space geometric error, in meters, introduced if this tile is rendered and its
66
+ * children are not. For I3S this stores the format's unscaled screen-threshold metric instead.
67
+ */
67
68
  lodMetricValue: number = 0;
68
69
 
70
+ /**
71
+ * The source LOD metric before applying the tile's computed transform. Keeping the source value
72
+ * separate ensures transform updates never compound an already-scaled geometric error.
73
+ */
74
+ private _unscaledLodMetricValue: number = 0;
75
+
69
76
  /** @todo math.gl is not exporting BoundingVolume base type? */
70
77
  boundingVolume: any = null;
71
78
 
@@ -172,6 +179,7 @@ export class Tile3D {
172
179
 
173
180
  this._initializeLodMetric(header);
174
181
  this._initializeTransforms(header);
182
+ this._updateLodMetricScale();
175
183
  this._initializeBoundingVolumes(header);
176
184
  this._initializeContent(header);
177
185
  this._initializeRenderingState(header);
@@ -355,13 +363,13 @@ export class Tile3D {
355
363
  * The request may not be made if the Request Scheduler can't prioritize it.
356
364
  */
357
365
  // eslint-disable-next-line max-statements, complexity
358
- async loadContent(): Promise<boolean> {
366
+ async loadContent(): Promise<TileContentLoadResult> {
359
367
  if (this.hasEmptyContent) {
360
- return false;
368
+ return {loaded: false};
361
369
  }
362
370
 
363
371
  if (this.content) {
364
- return true;
372
+ return {loaded: true};
365
373
  }
366
374
 
367
375
  const expired = this.contentExpired;
@@ -380,40 +388,19 @@ export class Tile3D {
380
388
  if (!requestToken) {
381
389
  // cancelled
382
390
  this.contentState = TILE_CONTENT_STATE.UNLOADED;
383
- return false;
391
+ return {loaded: false};
384
392
  }
385
393
 
386
394
  try {
387
- const contentUrl = this.tileset.getTileUrl(this.contentUrl);
388
- // The content can be a binary tile ot a JSON tileset
389
- const loader = this.tileset.loader;
390
- const tilesetLoaderOptions =
391
- (this.tileset.loadOptions[loader.id] as Record<string, unknown>) || {};
392
- const options = {
393
- ...this.tileset.loadOptions,
394
- [loader.id]: {
395
- ...tilesetLoaderOptions,
396
- isTileset: this.type === 'json',
397
- ...this._getLoaderSpecificOptions(loader.id)
398
- } // TODO add typecheck - as const satisfies ...
399
- };
400
-
401
- this.content = await load(contentUrl, loader, options);
395
+ const loadResult = await this.tileset.source.loadTileContent(this);
402
396
 
403
397
  if (this.tileset.options.contentLoader) {
404
398
  await this.tileset.options.contentLoader(this);
405
399
  }
406
400
 
407
- if (this._isTileset()) {
408
- // Add tile headers for the nested tilset's subtree
409
- // Async update of the tree should be fine since there would never be edits to the same node
410
- // TODO - we need to capture the child tileset's URL
411
- this.tileset._initializeTileHeaders(this.content, this);
412
- }
413
-
414
401
  this.contentState = TILE_CONTENT_STATE.READY;
415
402
  this._onContentLoaded();
416
- return true;
403
+ return loadResult;
417
404
  } catch (error) {
418
405
  // Tile is unloaded before the content finishes loading
419
406
  this.contentState = TILE_CONTENT_STATE.FAILED;
@@ -592,7 +579,8 @@ export class Tile3D {
592
579
 
593
580
  // INTERNAL METHODS
594
581
 
595
- _initializeLodMetric(header) {
582
+ /** Initializes the tile's LOD metric from its header or its nearest available ancestor. */
583
+ _initializeLodMetric(header: {[key: string]: any}): void {
596
584
  if ('lodMetricType' in header) {
597
585
  this.lodMetricType = header.lodMetricType;
598
586
  } else {
@@ -603,15 +591,20 @@ export class Tile3D {
603
591
 
604
592
  // This is used to compute screen space error, i.e., the error measured in pixels.
605
593
  if ('lodMetricValue' in header) {
606
- this.lodMetricValue = header.lodMetricValue;
594
+ this._unscaledLodMetricValue = header.lodMetricValue;
607
595
  } else {
608
- this.lodMetricValue =
609
- (this.parent && this.parent.lodMetricValue) || this.tileset.lodMetricValue;
596
+ // Inherit the source value, not the parent's world-space value. The child's complete
597
+ // transform will be applied after transform initialization below.
598
+ this._unscaledLodMetricValue = this.parent
599
+ ? this.parent._unscaledLodMetricValue
600
+ : this.tileset.lodMetricValue;
610
601
  // eslint-disable-next-line
611
602
  console.warn(
612
603
  '3D Tile: Required prop lodMetricValue is undefined. Using parent lodMetricValue'
613
604
  );
614
605
  }
606
+
607
+ this.lodMetricValue = this._unscaledLodMetricValue;
615
608
  }
616
609
 
617
610
  _initializeTransforms(tileHeader) {
@@ -632,6 +625,28 @@ export class Tile3D {
632
625
  this._initialTransform = new Matrix4(parentInitialTransform).multiplyRight(this.transform);
633
626
  }
634
627
 
628
+ /**
629
+ * Updates the world-space LOD metric from the source metric and the complete tile transform.
630
+ *
631
+ * 3D Tiles geometric error is a distance in the tile's local meters. Screen-space error (SSE)
632
+ * compares that distance with a world-space camera distance, so both quantities must use the
633
+ * same scale. For non-uniform transforms the largest axis scale is deliberately used: this is
634
+ * conservative and prevents refinement from stopping while any transformed dimension can still
635
+ * exceed the requested visual error. Rotation and translation do not affect the scale.
636
+ *
637
+ * I3S `maxScreenThreshold` is already a screen-space metric and must not be transform-scaled.
638
+ */
639
+ _updateLodMetricScale(): void {
640
+ if (this.lodMetricType !== LOD_METRIC_TYPE.GEOMETRIC_ERROR) {
641
+ this.lodMetricValue = this._unscaledLodMetricValue;
642
+ return;
643
+ }
644
+
645
+ const transformScale = this.computedTransform.getScale(scratchVector);
646
+ const maximumScale = Math.max(transformScale[0], transformScale[1], transformScale[2]);
647
+ this.lodMetricValue = this._unscaledLodMetricValue * maximumScale;
648
+ }
649
+
635
650
  _initializeBoundingVolumes(tileHeader) {
636
651
  this._contentBoundingVolume = null;
637
652
  this._viewerRequestVolume = null;
@@ -743,8 +758,11 @@ export class Tile3D {
743
758
  }
744
759
  }
745
760
 
746
- // Update the tile's transform. The transform is applied to the tile's bounding volumes.
747
- _updateTransform(parentTransform = new Matrix4()) {
761
+ /**
762
+ * Updates the tile's computed transform, world-space geometric error, and bounding volumes.
763
+ * @param parentTransform - Current computed transform of the parent tile or tileset.
764
+ */
765
+ _updateTransform(parentTransform = new Matrix4()): void {
748
766
  const computedTransform = parentTransform.clone().multiplyRight(this.transform);
749
767
  const didTransformChange = !computedTransform.equals(this.computedTransform);
750
768
 
@@ -754,35 +772,8 @@ export class Tile3D {
754
772
 
755
773
  this.computedTransform = computedTransform;
756
774
 
775
+ // Recalculate from the unscaled source metric so repeated model-matrix changes never compound.
776
+ this._updateLodMetricScale();
757
777
  this._updateBoundingVolume(this.header);
758
778
  }
759
-
760
- // Get options which are applicable only for the particular loader
761
- _getLoaderSpecificOptions(loaderId) {
762
- switch (loaderId) {
763
- case 'i3s':
764
- return {
765
- ...this.tileset.options.i3s,
766
- _tileOptions: {
767
- attributeUrls: this.header.attributeUrls,
768
- textureUrl: this.header.textureUrl,
769
- textureFormat: this.header.textureFormat,
770
- textureLoaderOptions: this.header.textureLoaderOptions,
771
- materialDefinition: this.header.materialDefinition,
772
- isDracoGeometry: this.header.isDracoGeometry,
773
- mbs: this.header.mbs
774
- },
775
- _tilesetOptions: {
776
- store: this.tileset.tileset.store,
777
- attributeStorageInfo: this.tileset.tileset.attributeStorageInfo,
778
- fields: this.tileset.tileset.fields
779
- },
780
- isTileHeader: false
781
- };
782
- case '3d-tiles':
783
- case 'cesium-ion':
784
- default:
785
- return get3dTilesOptions(this.tileset.tileset);
786
- }
787
- }
788
779
  }