@loaders.gl/tiles 5.0.0-alpha.5 → 5.0.0-alpha.7
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.
- package/dist/dist.dev.js +5122 -2641
- package/dist/dist.min.js +4 -2
- package/dist/index.cjs +1670 -403
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/spatial/format-spatial-reference.d.ts +1 -0
- package/dist/spatial/format-spatial-reference.d.ts.map +1 -1
- package/dist/spatial/format-spatial-reference.js +104 -46
- package/dist/spatial/format-spatial-reference.js.map +1 -1
- package/dist/spatial/get-spatial-coordinate-frame.d.ts +12 -1
- package/dist/spatial/get-spatial-coordinate-frame.d.ts.map +1 -1
- package/dist/spatial/get-spatial-coordinate-frame.js +105 -24
- package/dist/spatial/get-spatial-coordinate-frame.js.map +1 -1
- package/dist/spatial/normalize-crs-identifier.d.ts +15 -0
- package/dist/spatial/normalize-crs-identifier.d.ts.map +1 -0
- package/dist/spatial/normalize-crs-identifier.js +22 -0
- package/dist/spatial/normalize-crs-identifier.js.map +1 -0
- package/dist/spatial/spatial-coordinate-transformer.d.ts +4 -0
- package/dist/spatial/spatial-coordinate-transformer.d.ts.map +1 -1
- package/dist/spatial/spatial-coordinate-transformer.js +89 -12
- package/dist/spatial/spatial-coordinate-transformer.js.map +1 -1
- package/dist/spatial/tiles-3d-spatial-transformer.d.ts +32 -0
- package/dist/spatial/tiles-3d-spatial-transformer.d.ts.map +1 -0
- package/dist/spatial/tiles-3d-spatial-transformer.js +175 -0
- package/dist/spatial/tiles-3d-spatial-transformer.js.map +1 -0
- package/dist/tileset-3d/common/indexed-archive-tileset-source.d.ts +3 -3
- package/dist/tileset-3d/common/indexed-archive-tileset-source.d.ts.map +1 -1
- package/dist/tileset-3d/common/indexed-archive-tileset-source.js.map +1 -1
- package/dist/tileset-3d/common/tile-3d-contracts.d.ts +63 -0
- package/dist/tileset-3d/common/tile-3d-contracts.d.ts.map +1 -0
- package/dist/tileset-3d/common/tile-3d-contracts.js +51 -0
- package/dist/tileset-3d/common/tile-3d-contracts.js.map +1 -0
- package/dist/tileset-3d/common/tile-3d.d.ts +29 -5
- package/dist/tileset-3d/common/tile-3d.d.ts.map +1 -1
- package/dist/tileset-3d/common/tile-3d.js +151 -20
- package/dist/tileset-3d/common/tile-3d.js.map +1 -1
- package/dist/tileset-3d/common/tileset-3d.d.ts +44 -2
- package/dist/tileset-3d/common/tileset-3d.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-3d.js +31 -1
- package/dist/tileset-3d/common/tileset-3d.js.map +1 -1
- package/dist/tileset-3d/common/tileset-observability.d.ts +60 -0
- package/dist/tileset-3d/common/tileset-observability.d.ts.map +1 -0
- package/dist/tileset-3d/common/tileset-observability.js +39 -0
- package/dist/tileset-3d/common/tileset-observability.js.map +1 -0
- package/dist/tileset-3d/common/tileset-source.d.ts +11 -8
- package/dist/tileset-3d/common/tileset-source.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-source.js.map +1 -1
- package/dist/tileset-3d/common/tileset-traverser.d.ts +14 -0
- package/dist/tileset-3d/common/tileset-traverser.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-traverser.js +21 -5
- package/dist/tileset-3d/common/tileset-traverser.js.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts +47 -1
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js +327 -30
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts +34 -2
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js +265 -14
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts +70 -3
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js +216 -4
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-source.d.ts +5 -3
- package/dist/tileset-3d/format-i3s/i3s-source.d.ts.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-source.js +14 -7
- package/dist/tileset-3d/format-i3s/i3s-source.js.map +1 -1
- package/dist/tileset-3d/helpers/bounding-volume.d.ts +7 -3
- package/dist/tileset-3d/helpers/bounding-volume.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/bounding-volume.js +19 -61
- package/dist/tileset-3d/helpers/bounding-volume.js.map +1 -1
- package/dist/tileset-3d/helpers/frame-state.d.ts +4 -0
- package/dist/tileset-3d/helpers/frame-state.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/frame-state.js +6 -1
- package/dist/tileset-3d/helpers/frame-state.js.map +1 -1
- package/dist/tileset-3d/helpers/s2-bounding-volume.d.ts +17 -0
- package/dist/tileset-3d/helpers/s2-bounding-volume.d.ts.map +1 -0
- package/dist/tileset-3d/helpers/s2-bounding-volume.js +20 -0
- package/dist/tileset-3d/helpers/s2-bounding-volume.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +14 -13
- package/src/index.ts +13 -1
- package/src/spatial/format-spatial-reference.ts +127 -53
- package/src/spatial/get-spatial-coordinate-frame.ts +126 -31
- package/src/spatial/normalize-crs-identifier.ts +26 -0
- package/src/spatial/spatial-coordinate-transformer.ts +106 -15
- package/src/spatial/tiles-3d-spatial-transformer.ts +206 -0
- package/src/tileset-3d/common/indexed-archive-tileset-source.ts +4 -9
- package/src/tileset-3d/common/tile-3d-contracts.ts +115 -0
- package/src/tileset-3d/common/tile-3d.ts +178 -20
- package/src/tileset-3d/common/tileset-3d.ts +63 -3
- package/src/tileset-3d/common/tileset-observability.ts +100 -0
- package/src/tileset-3d/common/tileset-source.ts +11 -12
- package/src/tileset-3d/common/tileset-traverser.ts +32 -5
- package/src/tileset-3d/format-3d-tiles/implicit-tiling.ts +481 -34
- package/src/tileset-3d/format-3d-tiles/tiles-3d-source.ts +390 -17
- package/src/tileset-3d/format-3d-tiles/tileset-3d-traverser.ts +243 -4
- package/src/tileset-3d/format-i3s/i3s-source.ts +25 -9
- package/src/tileset-3d/helpers/bounding-volume.ts +29 -62
- package/src/tileset-3d/helpers/frame-state.ts +6 -1
- package/src/tileset-3d/helpers/s2-bounding-volume.ts +35 -0
- package/src/types.ts +2 -0
package/dist/index.cjs
CHANGED
|
@@ -39,12 +39,14 @@ __export(index_exports, {
|
|
|
39
39
|
TILE_TYPE: () => TILE_TYPE,
|
|
40
40
|
Tile3D: () => Tile3D,
|
|
41
41
|
Tiles3DSource: () => Tiles3DSource,
|
|
42
|
+
Tiles3DSpatialTransformer: () => Tiles3DSpatialTransformer,
|
|
42
43
|
Tileset2D: () => Tileset2D,
|
|
43
44
|
Tileset3D: () => Tileset3D,
|
|
44
45
|
TilesetCache: () => TilesetCache,
|
|
45
46
|
TilesetTraverser: () => TilesetTraverser,
|
|
46
47
|
applyTilesetSpatialOptions: () => applyTilesetSpatialOptions,
|
|
47
48
|
calculateTransformProps: () => calculateTransformProps,
|
|
49
|
+
convertS2BoundingVolumeToOBB: () => convertS2BoundingVolumeToOBB,
|
|
48
50
|
createBoundingVolume: () => createBoundingVolume,
|
|
49
51
|
createImplicitSubtreeReference: () => createImplicitSubtreeReference,
|
|
50
52
|
createTilesetSpatialReference: () => createTilesetSpatialReference,
|
|
@@ -54,6 +56,7 @@ __export(index_exports, {
|
|
|
54
56
|
getI3SSpatialReference: () => getI3SSpatialReference,
|
|
55
57
|
getLodStatus: () => getLodStatus,
|
|
56
58
|
getSpatialCoordinateFrame: () => getSpatialCoordinateFrame,
|
|
59
|
+
getTileset3DTraversalSnapshot: () => getTileset3DTraversalSnapshot,
|
|
57
60
|
isTileset3DSource: () => isTileset3DSource,
|
|
58
61
|
markTilesetSpatialReferenceTransformed: () => markTilesetSpatialReferenceTransformed,
|
|
59
62
|
materializeImplicitSubtree: () => materializeImplicitSubtree,
|
|
@@ -77,6 +80,13 @@ function assert(condition, message) {
|
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
82
|
|
|
83
|
+
// ../loader-utils/src/lib/binary-utils/array-buffer-utils.ts
|
|
84
|
+
function sliceArrayBuffer(arrayBuffer, byteOffset, byteLength) {
|
|
85
|
+
const subArray = byteLength !== void 0 ? new Uint8Array(arrayBuffer).subarray(byteOffset, byteOffset + byteLength) : new Uint8Array(arrayBuffer).subarray(byteOffset);
|
|
86
|
+
const arrayCopy = new Uint8Array(subArray);
|
|
87
|
+
return arrayCopy.buffer;
|
|
88
|
+
}
|
|
89
|
+
|
|
80
90
|
// ../loader-utils/src/lib/request-utils/request-scheduler.ts
|
|
81
91
|
var import_stats = require("@probe.gl/stats");
|
|
82
92
|
var STAT_QUEUED_REQUESTS = "Queued Requests";
|
|
@@ -1900,7 +1910,7 @@ function getFrameState(viewport, frameNumber, options = {}) {
|
|
|
1900
1910
|
).normalize();
|
|
1901
1911
|
commonSpacePlanesToWGS84(viewport);
|
|
1902
1912
|
const ViewportClass = viewport.constructor;
|
|
1903
|
-
const { longitude, latitude, width, bearing, zoom } = viewport;
|
|
1913
|
+
const { longitude, latitude, width, bearing, zoom, position } = viewport;
|
|
1904
1914
|
const topDownViewport = new ViewportClass({
|
|
1905
1915
|
longitude,
|
|
1906
1916
|
latitude,
|
|
@@ -1908,6 +1918,7 @@ function getFrameState(viewport, frameNumber, options = {}) {
|
|
|
1908
1918
|
width,
|
|
1909
1919
|
bearing,
|
|
1910
1920
|
zoom,
|
|
1921
|
+
position,
|
|
1911
1922
|
pitch: 0
|
|
1912
1923
|
});
|
|
1913
1924
|
return {
|
|
@@ -2265,30 +2276,32 @@ function calculateTileRequestPriority(parameters) {
|
|
|
2265
2276
|
}
|
|
2266
2277
|
|
|
2267
2278
|
// dist/spatial/spatial-types.js
|
|
2268
|
-
var
|
|
2279
|
+
var import_crs2 = require("@math.gl/crs");
|
|
2269
2280
|
|
|
2270
2281
|
// dist/spatial/get-spatial-coordinate-frame.js
|
|
2271
|
-
var
|
|
2272
|
-
|
|
2282
|
+
var import_crs = require("@math.gl/crs");
|
|
2283
|
+
|
|
2284
|
+
// dist/spatial/normalize-crs-identifier.js
|
|
2285
|
+
var WGS84_GEOGRAPHIC_CRS = "EPSG:4326";
|
|
2286
|
+
var WGS84_GEOCENTRIC_CRS = "EPSG:4978";
|
|
2273
2287
|
function normalizeCrsIdentifier(identifier) {
|
|
2274
2288
|
const normalizedIdentifier = identifier.trim().toUpperCase();
|
|
2275
2289
|
const ogcMatch = normalizedIdentifier.match(/(?:\/DEF\/CRS\/|URN:OGC:DEF:CRS:)([A-Z0-9_-]+)(?:\/|::)(?:[^/:]*[/:])?([A-Z0-9_.-]+)$/);
|
|
2276
2290
|
return ogcMatch ? `${ogcMatch[1]}:${ogcMatch[2]}` : normalizedIdentifier;
|
|
2277
2291
|
}
|
|
2292
|
+
|
|
2293
|
+
// dist/spatial/get-spatial-coordinate-frame.js
|
|
2278
2294
|
function getSpatialCoordinateFrame(definition) {
|
|
2279
2295
|
var _a, _b;
|
|
2280
2296
|
if (typeof definition === "string") {
|
|
2281
|
-
const
|
|
2282
|
-
if (
|
|
2283
|
-
return
|
|
2297
|
+
const representation = (0, import_crs.inferCRSRepresentation)(definition);
|
|
2298
|
+
if (representation === "wkt") {
|
|
2299
|
+
return getWktCoordinateFrame(definition);
|
|
2284
2300
|
}
|
|
2285
|
-
if (
|
|
2286
|
-
return
|
|
2287
|
-
}
|
|
2288
|
-
if (/^(?:GEODCRS|GEODETICCRS)\s*[\[(]/.test(normalized)) {
|
|
2289
|
-
return /CS\s*[\[(]\s*CARTESIAN/.test(normalized) ? "geocentric" : "geographic";
|
|
2301
|
+
if (representation === "proj-string") {
|
|
2302
|
+
return getProjStringCoordinateFrame(definition);
|
|
2290
2303
|
}
|
|
2291
|
-
return "projected";
|
|
2304
|
+
return getKnownCrsIdentifierCoordinateFrame(definition) || "projected";
|
|
2292
2305
|
}
|
|
2293
2306
|
const projJsonDefinition = definition;
|
|
2294
2307
|
if (projJsonDefinition.type === "BoundCRS" && projJsonDefinition.source_crs) {
|
|
@@ -2306,7 +2319,84 @@ function getSpatialCoordinateFrame(definition) {
|
|
|
2306
2319
|
if (String(projJsonDefinition.type).includes("Geodetic")) {
|
|
2307
2320
|
return ((_b = projJsonDefinition.coordinate_system) == null ? void 0 : _b.subtype) === "Cartesian" ? "geocentric" : "geographic";
|
|
2308
2321
|
}
|
|
2309
|
-
return "
|
|
2322
|
+
return "unknown";
|
|
2323
|
+
}
|
|
2324
|
+
function getKnownCrsIdentifierCoordinateFrame(definition) {
|
|
2325
|
+
if (typeof definition !== "string") {
|
|
2326
|
+
return void 0;
|
|
2327
|
+
}
|
|
2328
|
+
const normalized = normalizeCrsIdentifier(definition);
|
|
2329
|
+
if (normalized === WGS84_GEOCENTRIC_CRS) {
|
|
2330
|
+
return "geocentric";
|
|
2331
|
+
}
|
|
2332
|
+
if (normalized === WGS84_GEOGRAPHIC_CRS || normalized === "OGC:CRS84") {
|
|
2333
|
+
return "geographic";
|
|
2334
|
+
}
|
|
2335
|
+
const epsgMatch = /^EPSG:(\d+)$/.exec(normalized);
|
|
2336
|
+
if (!epsgMatch) {
|
|
2337
|
+
return void 0;
|
|
2338
|
+
}
|
|
2339
|
+
const identifier = Number(epsgMatch[1]);
|
|
2340
|
+
if (identifier === 7789) {
|
|
2341
|
+
return "geocentric";
|
|
2342
|
+
}
|
|
2343
|
+
if (identifier === 4490 || identifier === 4979) {
|
|
2344
|
+
return "geographic";
|
|
2345
|
+
}
|
|
2346
|
+
if (identifier === 3857 || identifier >= 32601 && identifier <= 32660 || identifier >= 32701 && identifier <= 32760) {
|
|
2347
|
+
return "projected";
|
|
2348
|
+
}
|
|
2349
|
+
return void 0;
|
|
2350
|
+
}
|
|
2351
|
+
function getWktCoordinateFrame(definition) {
|
|
2352
|
+
let root;
|
|
2353
|
+
try {
|
|
2354
|
+
root = (0, import_crs.parseWKTCRS)(definition).root;
|
|
2355
|
+
} catch {
|
|
2356
|
+
return "unknown";
|
|
2357
|
+
}
|
|
2358
|
+
switch (root.keyword.toUpperCase()) {
|
|
2359
|
+
case "GEOCCS":
|
|
2360
|
+
return "geocentric";
|
|
2361
|
+
case "GEOGCS":
|
|
2362
|
+
case "GEOGCRS":
|
|
2363
|
+
case "GEOGRAPHICCRS":
|
|
2364
|
+
case "GEOGRAPHIC2DCRS":
|
|
2365
|
+
case "GEOGRAPHIC3DCRS":
|
|
2366
|
+
return "geographic";
|
|
2367
|
+
case "PROJCS":
|
|
2368
|
+
case "PROJCRS":
|
|
2369
|
+
case "PROJECTEDCRS":
|
|
2370
|
+
return "projected";
|
|
2371
|
+
case "GEODCRS":
|
|
2372
|
+
case "GEODETICCRS": {
|
|
2373
|
+
const coordinateSystem = root.values.find((value) => value.type === "node" && value.keyword.toUpperCase() === "CS");
|
|
2374
|
+
const subtype = coordinateSystem == null ? void 0 : coordinateSystem.values[0];
|
|
2375
|
+
if ((subtype == null ? void 0 : subtype.type) !== "enumeration" && (subtype == null ? void 0 : subtype.type) !== "string") {
|
|
2376
|
+
return "unknown";
|
|
2377
|
+
}
|
|
2378
|
+
return subtype.value.toUpperCase() === "CARTESIAN" ? "geocentric" : subtype.value.toUpperCase() === "ELLIPSOIDAL" ? "geographic" : "unknown";
|
|
2379
|
+
}
|
|
2380
|
+
default:
|
|
2381
|
+
return "unknown";
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
function getProjStringCoordinateFrame(definition) {
|
|
2385
|
+
var _a;
|
|
2386
|
+
try {
|
|
2387
|
+
const projection = (_a = (0, import_crs.parsePROJString)(definition).parameters.find((parameter) => parameter.name.toLowerCase() === "proj")) == null ? void 0 : _a.value;
|
|
2388
|
+
switch (projection == null ? void 0 : projection.toLowerCase()) {
|
|
2389
|
+
case "longlat":
|
|
2390
|
+
case "latlong":
|
|
2391
|
+
return "geographic";
|
|
2392
|
+
case "geocent":
|
|
2393
|
+
return "geocentric";
|
|
2394
|
+
default:
|
|
2395
|
+
return projection ? "projected" : "unknown";
|
|
2396
|
+
}
|
|
2397
|
+
} catch {
|
|
2398
|
+
return "unknown";
|
|
2399
|
+
}
|
|
2310
2400
|
}
|
|
2311
2401
|
|
|
2312
2402
|
// dist/spatial/spatial-types.js
|
|
@@ -2331,11 +2421,11 @@ function createTilesetSpatialReference(discovered, options = {}) {
|
|
|
2331
2421
|
const provenance = hasSourceCrsOverride ? "caller-override" : discovered.provenance || "unknown";
|
|
2332
2422
|
const coordinateFrame = hasSourceCrsOverride && sourceCrs ? getSpatialCoordinateFrame(sourceCrs) : discovered.coordinateFrame;
|
|
2333
2423
|
const sourceCrsState = hasSourceCrsOverride ? "explicit" : discovered.sourceCrsState || (sourceCrs ? provenance === "format-default" ? "default" : "explicit" : "absent");
|
|
2334
|
-
const spatialReference = (0,
|
|
2424
|
+
const spatialReference = (0, import_crs2.createSpatialReference)({
|
|
2335
2425
|
crs: sourceCrs ? {
|
|
2336
2426
|
state: sourceCrsState === "default" ? "default" : "explicit",
|
|
2337
2427
|
definition: sourceCrs,
|
|
2338
|
-
representation: !hasSourceCrsOverride && discovered.sourceCrsRepresentation || (0,
|
|
2428
|
+
representation: !hasSourceCrsOverride && discovered.sourceCrsRepresentation || (0, import_crs2.inferCRSRepresentation)(sourceCrs),
|
|
2339
2429
|
provenance,
|
|
2340
2430
|
alternatives: hasSourceCrsOverride ? void 0 : discovered.sourceCrsAlternatives
|
|
2341
2431
|
} : {
|
|
@@ -2345,7 +2435,7 @@ function createTilesetSpatialReference(discovered, options = {}) {
|
|
|
2345
2435
|
vertical: discovered.verticalCrs ? {
|
|
2346
2436
|
state: "explicit",
|
|
2347
2437
|
definition: discovered.verticalCrs,
|
|
2348
|
-
representation: (0,
|
|
2438
|
+
representation: (0, import_crs2.inferCRSRepresentation)(discovered.verticalCrs),
|
|
2349
2439
|
provenance: discovered.provenance || "metadata"
|
|
2350
2440
|
} : void 0,
|
|
2351
2441
|
coordinateEpoch: options.coordinateEpoch ?? discovered.coordinateEpoch,
|
|
@@ -2402,11 +2492,11 @@ function getKnownCRSDefinition(reference) {
|
|
|
2402
2492
|
return reference.state === "explicit" || reference.state === "default" ? reference.definition : void 0;
|
|
2403
2493
|
}
|
|
2404
2494
|
function cloneReadonlyCRSDefinition(definition) {
|
|
2405
|
-
const spatialReference = (0,
|
|
2495
|
+
const spatialReference = (0, import_crs2.createSpatialReference)({
|
|
2406
2496
|
crs: {
|
|
2407
2497
|
state: "explicit",
|
|
2408
2498
|
definition,
|
|
2409
|
-
representation: (0,
|
|
2499
|
+
representation: (0, import_crs2.inferCRSRepresentation)(definition),
|
|
2410
2500
|
provenance: "caller-override"
|
|
2411
2501
|
}
|
|
2412
2502
|
});
|
|
@@ -2495,6 +2585,10 @@ var DEFAULT_PROPS3 = {
|
|
|
2495
2585
|
foveatedTimeDelay: 0.2,
|
|
2496
2586
|
maximumScreenSpaceError: 8,
|
|
2497
2587
|
skipLevelOfDetail: false,
|
|
2588
|
+
baseScreenSpaceError: 1024,
|
|
2589
|
+
skipScreenSpaceErrorFactor: 16,
|
|
2590
|
+
skipLevels: 1,
|
|
2591
|
+
immediatelyLoadDesiredLevelOfDetail: false,
|
|
2498
2592
|
dynamicScreenSpaceError: true,
|
|
2499
2593
|
dynamicScreenSpaceErrorDensity: 2e-4,
|
|
2500
2594
|
dynamicScreenSpaceErrorFactor: 24,
|
|
@@ -2657,6 +2751,24 @@ var Tileset3D = class {
|
|
|
2657
2751
|
get frameNumber() {
|
|
2658
2752
|
return this._frameNumber;
|
|
2659
2753
|
}
|
|
2754
|
+
/**
|
|
2755
|
+
* Returns the tiles requested during the most recent completed traversal.
|
|
2756
|
+
*
|
|
2757
|
+
* A defensive copy makes request ordering deterministic for diagnostics and prevents callers
|
|
2758
|
+
* from mutating the scheduler's working set.
|
|
2759
|
+
*/
|
|
2760
|
+
get requestedTiles() {
|
|
2761
|
+
return this._requestedTiles.slice();
|
|
2762
|
+
}
|
|
2763
|
+
/**
|
|
2764
|
+
* Returns empty tiles considered during the most recent completed traversal.
|
|
2765
|
+
*
|
|
2766
|
+
* Empty tiles can still be useful hierarchy placeholders, but their IDs are included in
|
|
2767
|
+
* observability snapshots so applications can distinguish traversal work from render content.
|
|
2768
|
+
*/
|
|
2769
|
+
get emptyTiles() {
|
|
2770
|
+
return this._emptyTiles.slice();
|
|
2771
|
+
}
|
|
2660
2772
|
/**
|
|
2661
2773
|
* Gets or sets the soft target, in bytes, for cached tile content not needed this frame.
|
|
2662
2774
|
*
|
|
@@ -2784,6 +2896,12 @@ var Tileset3D = class {
|
|
|
2784
2896
|
return;
|
|
2785
2897
|
}
|
|
2786
2898
|
const preparedViewports = viewports instanceof Array ? viewports : [viewports];
|
|
2899
|
+
const activeViewportIds = new Set(preparedViewports.map((viewport) => viewport.id));
|
|
2900
|
+
for (const frameStateId of Object.keys(this.frameStateData)) {
|
|
2901
|
+
if (!activeViewportIds.has(frameStateId)) {
|
|
2902
|
+
delete this.frameStateData[frameStateId];
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2787
2905
|
this._cache.reset();
|
|
2788
2906
|
this._frameNumber++;
|
|
2789
2907
|
this.traverseCounter = preparedViewports.length;
|
|
@@ -2972,21 +3090,21 @@ var Tileset3D = class {
|
|
|
2972
3090
|
this.stats.get(MAXIMUM_SSE).count = this.memoryAdjustedScreenSpaceError;
|
|
2973
3091
|
}
|
|
2974
3092
|
async _initializeTileSet() {
|
|
2975
|
-
var _a, _b, _c;
|
|
3093
|
+
var _a, _b, _c, _d;
|
|
2976
3094
|
try {
|
|
2977
3095
|
const initializePromise = this.source.initialize();
|
|
2978
3096
|
const initialMetadata = this._getSourceMetadata();
|
|
2979
3097
|
if (initialMetadata) {
|
|
2980
3098
|
this._syncSourceState(initialMetadata);
|
|
2981
3099
|
}
|
|
2982
|
-
if (((_a = initialMetadata == null ? void 0 : initialMetadata.tileset) == null ? void 0 : _a.root) && typeof initialMetadata.tileset.root.then !== "function" && !this.source.prepareTileset) {
|
|
3100
|
+
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")) {
|
|
2983
3101
|
this.root = this._initializeTileHeaders(initialMetadata.tileset, null);
|
|
2984
3102
|
this._applyViewState();
|
|
2985
3103
|
}
|
|
2986
3104
|
await initializePromise;
|
|
2987
3105
|
const metadata = this.source.getMetadata();
|
|
2988
3106
|
this._syncSourceState(metadata);
|
|
2989
|
-
await ((
|
|
3107
|
+
await ((_d = (_c = this.source).prepareTileset) == null ? void 0 : _d.call(_c, this));
|
|
2990
3108
|
if (!this.root) {
|
|
2991
3109
|
this.root = this._initializeTileHeaders(metadata.tileset, null);
|
|
2992
3110
|
}
|
|
@@ -3207,6 +3325,36 @@ function preserveTransformedSpatialReference(current, next) {
|
|
|
3207
3325
|
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;
|
|
3208
3326
|
}
|
|
3209
3327
|
|
|
3328
|
+
// dist/tileset-3d/common/tileset-observability.js
|
|
3329
|
+
function getTileset3DTraversalSnapshot(tileset) {
|
|
3330
|
+
var _a;
|
|
3331
|
+
const selectedTiles = tileset.selectedTiles.slice();
|
|
3332
|
+
const requestedTiles = tileset.requestedTiles.slice();
|
|
3333
|
+
const emptyTiles = tileset.emptyTiles.slice();
|
|
3334
|
+
const getTileIds = (tiles) => tiles.map((tile) => String(tile.id)).sort();
|
|
3335
|
+
const getStatCount = (name) => {
|
|
3336
|
+
const count = tileset.stats.get(name).count;
|
|
3337
|
+
return typeof count === "number" && Number.isFinite(count) ? count : 0;
|
|
3338
|
+
};
|
|
3339
|
+
const implicitTilingSource = tileset.source;
|
|
3340
|
+
const implicitTiling = (_a = implicitTilingSource.getImplicitTilingStats) == null ? void 0 : _a.call(implicitTilingSource);
|
|
3341
|
+
return {
|
|
3342
|
+
frameNumber: tileset.frameNumber,
|
|
3343
|
+
selectedTileIds: getTileIds(selectedTiles),
|
|
3344
|
+
requestedTileIds: getTileIds(requestedTiles),
|
|
3345
|
+
emptyTileIds: getTileIds(emptyTiles),
|
|
3346
|
+
visibleTileCount: selectedTiles.length,
|
|
3347
|
+
renderableTileCount: selectedTiles.filter((tile) => tile.contentAvailable && Boolean(tile.content)).length,
|
|
3348
|
+
loadingTileCount: getStatCount("Tiles Loading"),
|
|
3349
|
+
loadedTileCount: getStatCount("Tiles Loaded"),
|
|
3350
|
+
failedTileCount: getStatCount("Failed Tile Loads"),
|
|
3351
|
+
cachedTileCount: getStatCount("Tiles In Memory"),
|
|
3352
|
+
cacheBytes: tileset.gpuMemoryUsageInBytes,
|
|
3353
|
+
maximumScreenSpaceError: tileset.memoryAdjustedScreenSpaceError,
|
|
3354
|
+
...implicitTiling ? { implicitTiling } : {}
|
|
3355
|
+
};
|
|
3356
|
+
}
|
|
3357
|
+
|
|
3210
3358
|
// dist/tileset-3d/common/indexed-archive-tileset-source.js
|
|
3211
3359
|
var IndexedArchiveTilesetSource = class {
|
|
3212
3360
|
/** URL exposed to the tileset source that owns this archive source. */
|
|
@@ -3323,6 +3471,47 @@ function stripQueryString(url) {
|
|
|
3323
3471
|
var import_core8 = require("@math.gl/core");
|
|
3324
3472
|
var import_culling4 = require("@math.gl/culling");
|
|
3325
3473
|
|
|
3474
|
+
// dist/tileset-3d/common/tile-3d-contracts.js
|
|
3475
|
+
function getTile3DFeatureIdSets(payload) {
|
|
3476
|
+
const featureIdSets = [];
|
|
3477
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3478
|
+
const visit = (value) => {
|
|
3479
|
+
var _a, _b;
|
|
3480
|
+
if (!value || typeof value !== "object") {
|
|
3481
|
+
return;
|
|
3482
|
+
}
|
|
3483
|
+
if (visited.has(value)) {
|
|
3484
|
+
return;
|
|
3485
|
+
}
|
|
3486
|
+
visited.add(value);
|
|
3487
|
+
const record = value;
|
|
3488
|
+
const declarations = (_b = (_a = record.extensions) == null ? void 0 : _a.EXT_mesh_features) == null ? void 0 : _b.featureIds;
|
|
3489
|
+
if (Array.isArray(declarations)) {
|
|
3490
|
+
for (const declaration of declarations) {
|
|
3491
|
+
if (!declaration || typeof declaration !== "object") {
|
|
3492
|
+
continue;
|
|
3493
|
+
}
|
|
3494
|
+
const source = declaration.texture ? "texture" : declaration.implicit ? "implicit" : declaration.attribute !== void 0 ? "attribute" : declaration.propertyTable !== void 0 ? "property-table" : "constant";
|
|
3495
|
+
featureIdSets.push({
|
|
3496
|
+
source,
|
|
3497
|
+
attribute: declaration.attribute,
|
|
3498
|
+
propertyTable: declaration.propertyTable,
|
|
3499
|
+
constant: declaration.constant,
|
|
3500
|
+
texture: declaration.texture,
|
|
3501
|
+
implicit: declaration.implicit,
|
|
3502
|
+
values: declaration.values,
|
|
3503
|
+
details: declaration
|
|
3504
|
+
});
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
for (const child of Object.values(record)) {
|
|
3508
|
+
visit(child);
|
|
3509
|
+
}
|
|
3510
|
+
};
|
|
3511
|
+
visit(payload);
|
|
3512
|
+
return featureIdSets;
|
|
3513
|
+
}
|
|
3514
|
+
|
|
3326
3515
|
// dist/tileset-3d/helpers/bounding-volume.js
|
|
3327
3516
|
var import_core6 = require("@math.gl/core");
|
|
3328
3517
|
var import_culling3 = require("@math.gl/culling");
|
|
@@ -3332,21 +3521,25 @@ function defined(x) {
|
|
|
3332
3521
|
}
|
|
3333
3522
|
var scratchPoint = new import_core6.Vector3();
|
|
3334
3523
|
var scratchScale = new import_core6.Vector3();
|
|
3335
|
-
|
|
3524
|
+
var identityTransform = new import_core6.Matrix4();
|
|
3525
|
+
function createBoundingVolume(boundingVolumeHeader, transform, result, initialTransform = transform) {
|
|
3336
3526
|
assert(boundingVolumeHeader, "3D Tile: boundingVolume must be defined");
|
|
3337
3527
|
if (boundingVolumeHeader.box) {
|
|
3338
|
-
|
|
3528
|
+
const boxTransform = boundingVolumeHeader.s2VolumeInfo ? identityTransform : transform;
|
|
3529
|
+
return createBox(boundingVolumeHeader.box, boxTransform, result);
|
|
3339
3530
|
}
|
|
3340
3531
|
if (boundingVolumeHeader.region) {
|
|
3341
|
-
|
|
3532
|
+
const boundingVolume = (0, import_geospatial4.makeOBBFromRegion)(boundingVolumeHeader.region);
|
|
3533
|
+
const regionTransform = transform.equals(initialTransform) ? identityTransform : transform.clone().multiplyRight(initialTransform.clone().invert());
|
|
3534
|
+
return createBox([...boundingVolume.center, ...boundingVolume.halfAxes], regionTransform, result);
|
|
3342
3535
|
}
|
|
3343
3536
|
if (boundingVolumeHeader.sphere) {
|
|
3344
3537
|
return createSphere(boundingVolumeHeader.sphere, transform, result);
|
|
3345
3538
|
}
|
|
3346
3539
|
throw new Error("3D Tile: boundingVolume must contain a sphere, region, or box");
|
|
3347
3540
|
}
|
|
3348
|
-
function getCartographicBounds(boundingVolumeHeader, boundingVolume) {
|
|
3349
|
-
if (boundingVolumeHeader.box) {
|
|
3541
|
+
function getCartographicBounds(boundingVolumeHeader, boundingVolume, isRegionTransformed = false) {
|
|
3542
|
+
if (boundingVolumeHeader.box || boundingVolumeHeader.region && isRegionTransformed) {
|
|
3350
3543
|
return orientedBoundingBoxToCartographicBounds(boundingVolume);
|
|
3351
3544
|
}
|
|
3352
3545
|
if (boundingVolumeHeader.region) {
|
|
@@ -3691,6 +3884,10 @@ var ManagedArray = class {
|
|
|
3691
3884
|
var DEFAULT_PROPS4 = {
|
|
3692
3885
|
loadSiblings: false,
|
|
3693
3886
|
skipLevelOfDetail: false,
|
|
3887
|
+
baseScreenSpaceError: 1024,
|
|
3888
|
+
skipScreenSpaceErrorFactor: 16,
|
|
3889
|
+
skipLevels: 1,
|
|
3890
|
+
immediatelyLoadDesiredLevelOfDetail: false,
|
|
3694
3891
|
updateTransforms: true,
|
|
3695
3892
|
onTraversalEnd: () => {
|
|
3696
3893
|
},
|
|
@@ -3699,6 +3896,8 @@ var DEFAULT_PROPS4 = {
|
|
|
3699
3896
|
};
|
|
3700
3897
|
var TilesetTraverser = class {
|
|
3701
3898
|
options;
|
|
3899
|
+
/** Whether loaded content has disabled skip-LOD traversal for this tileset. */
|
|
3900
|
+
disableSkipLevelOfDetail = false;
|
|
3702
3901
|
// fulfill in traverse call
|
|
3703
3902
|
root = null;
|
|
3704
3903
|
// tiles should be rendered
|
|
@@ -3724,6 +3923,10 @@ var TilesetTraverser = class {
|
|
|
3724
3923
|
constructor(options) {
|
|
3725
3924
|
this.options = { ...DEFAULT_PROPS4, ...options };
|
|
3726
3925
|
}
|
|
3926
|
+
/** Returns whether skip-LOD traversal is enabled and supported by the loaded content. */
|
|
3927
|
+
isSkipLevelOfDetailEnabled() {
|
|
3928
|
+
return this.options.skipLevelOfDetail && !this.disableSkipLevelOfDetail;
|
|
3929
|
+
}
|
|
3727
3930
|
// tiles should be visible
|
|
3728
3931
|
traverse(root, frameState, options) {
|
|
3729
3932
|
this.root = root;
|
|
@@ -3776,13 +3979,17 @@ var TilesetTraverser = class {
|
|
|
3776
3979
|
this.selectTile(tile, frameState);
|
|
3777
3980
|
} else if (tile.refine === TILE_REFINEMENT.REPLACE) {
|
|
3778
3981
|
this.loadTile(tile, frameState);
|
|
3779
|
-
if (stoppedRefining || this.
|
|
3982
|
+
if (stoppedRefining || this.isSkipLevelOfDetailEnabled()) {
|
|
3780
3983
|
this.selectTile(tile, frameState);
|
|
3781
3984
|
}
|
|
3782
3985
|
}
|
|
3783
3986
|
this.touchTile(tile, frameState);
|
|
3784
3987
|
tile._shouldRefine = shouldRefine && parentRefines;
|
|
3785
3988
|
}
|
|
3989
|
+
this.completeTraversal(frameState);
|
|
3990
|
+
}
|
|
3991
|
+
/** Notifies the owning tileset when traversal is complete or its debounce interval expires. */
|
|
3992
|
+
completeTraversal(frameState) {
|
|
3786
3993
|
const newTime = (/* @__PURE__ */ new Date()).getTime();
|
|
3787
3994
|
if (this.traversalFinished(frameState) || newTime - this.lastUpdate > this.updateDebounceTime) {
|
|
3788
3995
|
this.lastUpdate = newTime;
|
|
@@ -3797,7 +4004,8 @@ var TilesetTraverser = class {
|
|
|
3797
4004
|
}
|
|
3798
4005
|
/* eslint-disable complexity, max-statements */
|
|
3799
4006
|
updateAndPushChildren(tile, frameState, stack, depth) {
|
|
3800
|
-
const { loadSiblings
|
|
4007
|
+
const { loadSiblings } = this.options;
|
|
4008
|
+
const skipLevelOfDetail = this.isSkipLevelOfDetailEnabled();
|
|
3801
4009
|
const children = tile.children;
|
|
3802
4010
|
children.sort(this.compareDistanceToCamera.bind(this));
|
|
3803
4011
|
const checkRefines = tile.refine === TILE_REFINEMENT.REPLACE && tile.hasRenderContent && !skipLevelOfDetail;
|
|
@@ -3811,7 +4019,7 @@ var TilesetTraverser = class {
|
|
|
3811
4019
|
}
|
|
3812
4020
|
stack.push(child);
|
|
3813
4021
|
hasVisibleChild = true;
|
|
3814
|
-
} else if (checkRefines || loadSiblings) {
|
|
4022
|
+
} else if ((checkRefines || loadSiblings) && child._inRequestVolume) {
|
|
3815
4023
|
this.loadTile(child, frameState);
|
|
3816
4024
|
this.touchTile(child, frameState);
|
|
3817
4025
|
}
|
|
@@ -3998,6 +4206,13 @@ function getContentVisibility(contentVolumes, fallbackVolume, cullingVolume2, vi
|
|
|
3998
4206
|
}
|
|
3999
4207
|
return intersectingVolume ? "intersecting" : "inside";
|
|
4000
4208
|
}
|
|
4209
|
+
function isNestedTilesetPayload(payload) {
|
|
4210
|
+
if (!payload || typeof payload !== "object") {
|
|
4211
|
+
return false;
|
|
4212
|
+
}
|
|
4213
|
+
const record = payload;
|
|
4214
|
+
return record.shape === "tileset3d" || record.type === "tileset3d" || Boolean(record.tileset);
|
|
4215
|
+
}
|
|
4001
4216
|
function defined2(x) {
|
|
4002
4217
|
return x !== void 0 && x !== null;
|
|
4003
4218
|
}
|
|
@@ -4025,6 +4240,8 @@ var Tile3D = class {
|
|
|
4025
4240
|
* separate ensures transform updates never compound an already-scaled geometric error.
|
|
4026
4241
|
*/
|
|
4027
4242
|
_unscaledLodMetricValue = 0;
|
|
4243
|
+
/** Whether the source format defines geometric error in transform-local units. */
|
|
4244
|
+
_scaleGeometricError = true;
|
|
4028
4245
|
/** @todo math.gl is not exporting BoundingVolume base type? */
|
|
4029
4246
|
boundingVolume = null;
|
|
4030
4247
|
/**
|
|
@@ -4034,6 +4251,14 @@ var Tile3D = class {
|
|
|
4034
4251
|
content = null;
|
|
4035
4252
|
/** Loaded payloads in the same order as {@link contentUrls}; `content` remains the primary payload. */
|
|
4036
4253
|
contents = [];
|
|
4254
|
+
/** Ordered renderer-neutral descriptors for each source content entry. */
|
|
4255
|
+
contentEntries = [];
|
|
4256
|
+
/** Raw metadata references inherited by this tile and its content. */
|
|
4257
|
+
metadataContext = {};
|
|
4258
|
+
/** Feature-id declarations normalized from supported content extensions. */
|
|
4259
|
+
featureIdSets = [];
|
|
4260
|
+
/** Decoded 3D Tiles vector topology for the primary loaded content, when present. */
|
|
4261
|
+
vectorContent = null;
|
|
4037
4262
|
/**
|
|
4038
4263
|
* Metadata entity attached to this tile in the source tileset, if present.
|
|
4039
4264
|
*
|
|
@@ -4100,6 +4325,7 @@ var Tile3D = class {
|
|
|
4100
4325
|
get viewerRequestVolume() {
|
|
4101
4326
|
return this._viewerRequestVolume;
|
|
4102
4327
|
}
|
|
4328
|
+
/** Accumulated tile transforms from the source JSON, excluding the tileset model matrix. */
|
|
4103
4329
|
_initialTransform = new import_core8.Matrix4();
|
|
4104
4330
|
// Used by traverser, cannot be marked private
|
|
4105
4331
|
_priority = 0;
|
|
@@ -4141,15 +4367,14 @@ var Tile3D = class {
|
|
|
4141
4367
|
this.type = header.type;
|
|
4142
4368
|
this.contentUrl = header.contentUrl;
|
|
4143
4369
|
this.contentUrls = header.contentUrls || (header.contentUrl ? [header.contentUrl] : []);
|
|
4144
|
-
this.
|
|
4145
|
-
const contentHeaders = Array.isArray(header.content) ? header.content : [header.content];
|
|
4146
|
-
this.contentMetadata = contentHeaders.filter(Boolean).map((contentHeader) => contentHeader.metadata || null);
|
|
4370
|
+
this._initializeMetadata(header);
|
|
4147
4371
|
this.childrenState = header.implicitSubtree ? "unloaded" : "ready";
|
|
4148
4372
|
this._initializeLodMetric(header);
|
|
4149
4373
|
this._initializeTransforms(header);
|
|
4150
4374
|
this._updateLodMetricScale();
|
|
4151
4375
|
this._initializeBoundingVolumes(header);
|
|
4152
4376
|
this._initializeContent(header);
|
|
4377
|
+
this._initializeContentEntries(header);
|
|
4153
4378
|
this._initializeRenderingState(header);
|
|
4154
4379
|
Object.seal(this);
|
|
4155
4380
|
}
|
|
@@ -4234,12 +4459,12 @@ var Tile3D = class {
|
|
|
4234
4459
|
return this._screenSpaceError;
|
|
4235
4460
|
}
|
|
4236
4461
|
/**
|
|
4237
|
-
* Get bounding
|
|
4462
|
+
* Get the current world-space bounding volume in cartographic coordinates.
|
|
4238
4463
|
* @returns [min, max] each in [longitude, latitude, altitude]
|
|
4239
4464
|
*/
|
|
4240
4465
|
get boundingBox() {
|
|
4241
4466
|
if (!this._boundingBox) {
|
|
4242
|
-
this._boundingBox = getCartographicBounds(this.header.boundingVolume, this.boundingVolume);
|
|
4467
|
+
this._boundingBox = getCartographicBounds(this.header.boundingVolume, this.boundingVolume, !this.computedTransform.equals(this._initialTransform));
|
|
4243
4468
|
}
|
|
4244
4469
|
return this._boundingBox;
|
|
4245
4470
|
}
|
|
@@ -4307,7 +4532,7 @@ var Tile3D = class {
|
|
|
4307
4532
|
// eslint-disable-next-line complexity
|
|
4308
4533
|
_calculateRequestPriority(allowUnloadedContent) {
|
|
4309
4534
|
const traverser = this.tileset._traverser;
|
|
4310
|
-
const
|
|
4535
|
+
const skipLevelOfDetail = traverser.options.skipLevelOfDetail && !traverser.disableSkipLevelOfDetail;
|
|
4311
4536
|
const maySkipTile = this.refine === TILE_REFINEMENT.ADD || skipLevelOfDetail;
|
|
4312
4537
|
if (maySkipTile && !this.isVisible && this._visible !== void 0) {
|
|
4313
4538
|
return -1;
|
|
@@ -4339,6 +4564,7 @@ var Tile3D = class {
|
|
|
4339
4564
|
*/
|
|
4340
4565
|
// eslint-disable-next-line max-statements, complexity
|
|
4341
4566
|
async loadContent() {
|
|
4567
|
+
var _a;
|
|
4342
4568
|
if (this.hasEmptyContent) {
|
|
4343
4569
|
return { loaded: false };
|
|
4344
4570
|
}
|
|
@@ -4361,11 +4587,13 @@ var Tile3D = class {
|
|
|
4361
4587
|
this.contents = loadResult.contents;
|
|
4362
4588
|
this.content = this.contents[0] || null;
|
|
4363
4589
|
}
|
|
4590
|
+
this.vectorContent = ((_a = this.contents.find((content) => Boolean(content == null ? void 0 : content.vectorContent))) == null ? void 0 : _a.vectorContent) || null;
|
|
4364
4591
|
if (this.tileset.options.contentLoader) {
|
|
4365
4592
|
await this.tileset.options.contentLoader(this);
|
|
4366
4593
|
}
|
|
4367
4594
|
this.contentState = TILE_CONTENT_STATE.READY;
|
|
4368
4595
|
this._onContentLoaded();
|
|
4596
|
+
this._updateContentEntriesAfterLoad(loadResult);
|
|
4369
4597
|
return loadResult;
|
|
4370
4598
|
} catch (error) {
|
|
4371
4599
|
this.contentState = TILE_CONTENT_STATE.FAILED;
|
|
@@ -4428,30 +4656,114 @@ var Tile3D = class {
|
|
|
4428
4656
|
/**
|
|
4429
4657
|
* Replaces a contentless implicit placeholder with its materialized subtree-root header.
|
|
4430
4658
|
*
|
|
4431
|
-
*
|
|
4432
|
-
* transform
|
|
4433
|
-
*
|
|
4659
|
+
* The placeholder transform is preserved when the subtree omits a root transform. An explicit
|
|
4660
|
+
* subtree-root transform replaces it and is recomposed against the runtime parent. Content,
|
|
4661
|
+
* metadata, bounds, and raw geometric error are reinitialized from the available header.
|
|
4434
4662
|
*
|
|
4435
4663
|
* @param materializedHeader - Available root header produced from one subtree resource.
|
|
4436
4664
|
*/
|
|
4437
4665
|
applyImplicitSubtreeHeader(materializedHeader) {
|
|
4438
4666
|
const existingTransform = this.header.transform;
|
|
4439
4667
|
const existingTransformMatrix = this.header.transformMatrix;
|
|
4668
|
+
const hasMaterializedTransform = materializedHeader.transform !== void 0;
|
|
4440
4669
|
this.header = {
|
|
4441
4670
|
...this.header,
|
|
4442
4671
|
...materializedHeader,
|
|
4443
|
-
transform: existingTransform,
|
|
4444
|
-
transformMatrix: existingTransformMatrix,
|
|
4672
|
+
transform: hasMaterializedTransform ? materializedHeader.transform : existingTransform,
|
|
4673
|
+
transformMatrix: hasMaterializedTransform ? materializedHeader.transformMatrix : existingTransformMatrix,
|
|
4445
4674
|
implicitSubtree: void 0
|
|
4446
4675
|
};
|
|
4676
|
+
if (hasMaterializedTransform) {
|
|
4677
|
+
this._initializeTransforms(this.header);
|
|
4678
|
+
}
|
|
4447
4679
|
this.refine = this._getRefine(materializedHeader.refine);
|
|
4448
4680
|
this.type = materializedHeader.type;
|
|
4449
4681
|
this.contentUrl = materializedHeader.contentUrl;
|
|
4450
4682
|
this.contentUrls = materializedHeader.contentUrls || (materializedHeader.contentUrl ? [materializedHeader.contentUrl] : []);
|
|
4683
|
+
this._initializeMetadata(this.header);
|
|
4451
4684
|
this._initializeLodMetric(materializedHeader);
|
|
4452
4685
|
this._updateLodMetricScale();
|
|
4453
4686
|
this._initializeBoundingVolumes(this.header);
|
|
4687
|
+
this._boundingBox = void 0;
|
|
4454
4688
|
this._initializeContent(this.header);
|
|
4689
|
+
this._initializeContentEntries(this.header);
|
|
4690
|
+
}
|
|
4691
|
+
/** Refreshes tile and content metadata from a source or materialized tile header. */
|
|
4692
|
+
_initializeMetadata(header) {
|
|
4693
|
+
var _a;
|
|
4694
|
+
this.metadata = header.metadata || null;
|
|
4695
|
+
const contentHeaders = Array.isArray(header.content) ? header.content : [header.content];
|
|
4696
|
+
this.contentMetadata = contentHeaders.filter(Boolean).map((contentHeader) => contentHeader.metadata || null);
|
|
4697
|
+
const firstContentHeader = contentHeaders.find(Boolean) || {};
|
|
4698
|
+
const groupReference = firstContentHeader.group;
|
|
4699
|
+
const group = typeof groupReference === "number" ? ((_a = this.tileset.groups) == null ? void 0 : _a[groupReference]) || null : groupReference || null;
|
|
4700
|
+
const metadataContext = {
|
|
4701
|
+
tileset: this.tileset.metadata || null,
|
|
4702
|
+
group,
|
|
4703
|
+
tile: this.metadata,
|
|
4704
|
+
content: this.contentMetadata[0] || null,
|
|
4705
|
+
subtree: header.implicitMetadata || null
|
|
4706
|
+
};
|
|
4707
|
+
if (this.tileset.groups) {
|
|
4708
|
+
metadataContext.groups = this.tileset.groups;
|
|
4709
|
+
}
|
|
4710
|
+
this.metadataContext = metadataContext;
|
|
4711
|
+
}
|
|
4712
|
+
/** Updates payload and renderability while retaining immutable metadata descriptors. */
|
|
4713
|
+
_updateContentEntriesAfterLoad(loadResult) {
|
|
4714
|
+
if (loadResult.contentEntries) {
|
|
4715
|
+
this.contentEntries = loadResult.contentEntries.map((entry, index) => {
|
|
4716
|
+
var _a;
|
|
4717
|
+
return {
|
|
4718
|
+
...entry,
|
|
4719
|
+
index,
|
|
4720
|
+
boundingVolume: entry.boundingVolume || this._contentBoundingVolumes[index] || this.boundingVolume,
|
|
4721
|
+
payload: entry.payload ?? this.contents[index] ?? null,
|
|
4722
|
+
featureIds: ((_a = entry.featureIds) == null ? void 0 : _a.length) ? entry.featureIds : getTile3DFeatureIdSets(entry.payload ?? this.contents[index]),
|
|
4723
|
+
renderable: Boolean(entry.renderable !== false && (entry.payload ?? this.contents[index]) && !isNestedTilesetPayload(entry.payload ?? this.contents[index]))
|
|
4724
|
+
};
|
|
4725
|
+
});
|
|
4726
|
+
this.featureIdSets = this.contentEntries.flatMap((entry) => entry.featureIds);
|
|
4727
|
+
return;
|
|
4728
|
+
}
|
|
4729
|
+
this.contentEntries = this.contentEntries.map((entry, index) => ({
|
|
4730
|
+
...entry,
|
|
4731
|
+
payload: this.contents[index] ?? null,
|
|
4732
|
+
featureIds: getTile3DFeatureIdSets(this.contents[index]),
|
|
4733
|
+
renderable: Boolean(this.contents[index]) && !isNestedTilesetPayload(this.contents[index])
|
|
4734
|
+
}));
|
|
4735
|
+
this.featureIdSets = this.contentEntries.flatMap((entry) => entry.featureIds);
|
|
4736
|
+
}
|
|
4737
|
+
/** Returns one ordered content descriptor, or null when the index is out of range. */
|
|
4738
|
+
getContentEntry(index) {
|
|
4739
|
+
return this.contentEntries[index] || null;
|
|
4740
|
+
}
|
|
4741
|
+
/** Returns whether an ordered content entry currently has renderable payload. */
|
|
4742
|
+
isContentRenderable(index) {
|
|
4743
|
+
var _a;
|
|
4744
|
+
return Boolean((_a = this.contentEntries[index]) == null ? void 0 : _a.renderable);
|
|
4745
|
+
}
|
|
4746
|
+
/** Initializes additive renderer-neutral descriptors from a normalized tile header. */
|
|
4747
|
+
_initializeContentEntries(tileHeader) {
|
|
4748
|
+
const headers = Array.isArray(tileHeader.content) ? tileHeader.content : tileHeader.content ? [tileHeader.content] : [];
|
|
4749
|
+
this.contentEntries = headers.map((contentHeader, index) => {
|
|
4750
|
+
const normalizedContentHeader = contentHeader || {};
|
|
4751
|
+
return {
|
|
4752
|
+
index,
|
|
4753
|
+
uri: this.contentUrls[index] || normalizedContentHeader.uri || normalizedContentHeader.url,
|
|
4754
|
+
group: normalizedContentHeader.group,
|
|
4755
|
+
type: normalizedContentHeader.type,
|
|
4756
|
+
payload: null,
|
|
4757
|
+
metadata: normalizedContentHeader.metadata || null,
|
|
4758
|
+
boundingVolume: this._contentBoundingVolumes[index] || this.boundingVolume,
|
|
4759
|
+
featureIds: this._getFeatureIdSets(normalizedContentHeader),
|
|
4760
|
+
renderable: false
|
|
4761
|
+
};
|
|
4762
|
+
});
|
|
4763
|
+
}
|
|
4764
|
+
/** Extracts renderer-neutral feature-id declarations without decoding property values. */
|
|
4765
|
+
_getFeatureIdSets(contentHeader) {
|
|
4766
|
+
return getTile3DFeatureIdSets(contentHeader);
|
|
4455
4767
|
}
|
|
4456
4768
|
// Unloads the tile's content.
|
|
4457
4769
|
unloadContent() {
|
|
@@ -4462,6 +4774,13 @@ var Tile3D = class {
|
|
|
4462
4774
|
}
|
|
4463
4775
|
this.contents = [];
|
|
4464
4776
|
this.content = null;
|
|
4777
|
+
this.vectorContent = null;
|
|
4778
|
+
this.contentEntries = this.contentEntries.map((entry) => ({
|
|
4779
|
+
...entry,
|
|
4780
|
+
payload: null,
|
|
4781
|
+
renderable: false
|
|
4782
|
+
}));
|
|
4783
|
+
this.featureIdSets = this.contentEntries.flatMap((entry) => entry.featureIds);
|
|
4465
4784
|
if (this.header.content && this.header.content.destroy) {
|
|
4466
4785
|
this.header.content.destroy();
|
|
4467
4786
|
}
|
|
@@ -4523,9 +4842,11 @@ var Tile3D = class {
|
|
|
4523
4842
|
return;
|
|
4524
4843
|
}
|
|
4525
4844
|
this._foveatedFactor = calculateFoveatedFactor(this.boundingVolume, frameState.camera);
|
|
4845
|
+
const traverser = this.tileset._traverser;
|
|
4846
|
+
const skipLevelOfDetail = traverser.options.skipLevelOfDetail && !traverser.disableSkipLevelOfDetail;
|
|
4526
4847
|
const deferralEligible = isFoveatedRequestDeferred({
|
|
4527
4848
|
refinement: this.refine,
|
|
4528
|
-
skipLevelOfDetail
|
|
4849
|
+
skipLevelOfDetail,
|
|
4529
4850
|
foveatedScreenSpaceError: options.foveatedScreenSpaceError,
|
|
4530
4851
|
foveatedConeSize: options.foveatedConeSize,
|
|
4531
4852
|
minimumScreenSpaceErrorRelaxation: options.foveatedMinimumScreenSpaceErrorRelaxation,
|
|
@@ -4556,8 +4877,9 @@ var Tile3D = class {
|
|
|
4556
4877
|
* @param frameState Current camera, culling, and optional clipping-plane state.
|
|
4557
4878
|
* @returns The content visibility classification.
|
|
4558
4879
|
*/
|
|
4559
|
-
contentVisibility(frameState) {
|
|
4560
|
-
|
|
4880
|
+
contentVisibility(frameState, contentIndex) {
|
|
4881
|
+
const contentVolumes = contentIndex === void 0 ? this._contentBoundingVolumes : this._contentBoundingVolumes[contentIndex] ? [this._contentBoundingVolumes[contentIndex]] : [];
|
|
4882
|
+
return getContentVisibility(contentVolumes, this.boundingVolume, frameState.cullingVolume, this._visibilityPlaneMask, frameState.clippingPlanes);
|
|
4561
4883
|
}
|
|
4562
4884
|
/**
|
|
4563
4885
|
* Computes the (potentially approximate) distance from the closest point of the tile's bounding volume to the camera.
|
|
@@ -4604,6 +4926,8 @@ var Tile3D = class {
|
|
|
4604
4926
|
// INTERNAL METHODS
|
|
4605
4927
|
/** Initializes the tile's LOD metric from its header or its nearest available ancestor. */
|
|
4606
4928
|
_initializeLodMetric(header) {
|
|
4929
|
+
var _a;
|
|
4930
|
+
this._scaleGeometricError = typeof header._scaleGeometricError === "boolean" ? header._scaleGeometricError : ((_a = this.parent) == null ? void 0 : _a._scaleGeometricError) ?? true;
|
|
4607
4931
|
if ("lodMetricType" in header) {
|
|
4608
4932
|
this.lodMetricType = header.lodMetricType;
|
|
4609
4933
|
} else {
|
|
@@ -4639,7 +4963,7 @@ var Tile3D = class {
|
|
|
4639
4963
|
* I3S `maxScreenThreshold` is already a screen-space metric and must not be transform-scaled.
|
|
4640
4964
|
*/
|
|
4641
4965
|
_updateLodMetricScale() {
|
|
4642
|
-
if (this.lodMetricType !== LOD_METRIC_TYPE.GEOMETRIC_ERROR) {
|
|
4966
|
+
if (this.lodMetricType !== LOD_METRIC_TYPE.GEOMETRIC_ERROR || !this._scaleGeometricError) {
|
|
4643
4967
|
this.lodMetricValue = this._unscaledLodMetricValue;
|
|
4644
4968
|
return;
|
|
4645
4969
|
}
|
|
@@ -4719,16 +5043,17 @@ var Tile3D = class {
|
|
|
4719
5043
|
}
|
|
4720
5044
|
}
|
|
4721
5045
|
_updateBoundingVolume(header) {
|
|
4722
|
-
this.
|
|
5046
|
+
this._boundingBox = void 0;
|
|
5047
|
+
this.boundingVolume = createBoundingVolume(header.boundingVolume, this.computedTransform, this.boundingVolume, this._initialTransform);
|
|
4723
5048
|
if (header.viewerRequestVolume) {
|
|
4724
|
-
this._viewerRequestVolume = createBoundingVolume(header.viewerRequestVolume, this.computedTransform, this._viewerRequestVolume);
|
|
5049
|
+
this._viewerRequestVolume = createBoundingVolume(header.viewerRequestVolume, this.computedTransform, this._viewerRequestVolume, this._initialTransform);
|
|
4725
5050
|
}
|
|
4726
5051
|
const content = header.content;
|
|
4727
5052
|
if (content) {
|
|
4728
5053
|
this._contentBoundingVolumeHeaders = Array.isArray(content) ? content : [content];
|
|
4729
5054
|
}
|
|
4730
5055
|
const contentHeaders = content ? Array.isArray(content) ? content : [content] : this._contentBoundingVolumeHeaders;
|
|
4731
|
-
this._contentBoundingVolumes = contentHeaders.length ? contentHeaders.map((headerEntry) => (headerEntry == null ? void 0 : headerEntry.boundingVolume) ? createBoundingVolume(headerEntry.boundingVolume, this.computedTransform) : this.boundingVolume) : [this.boundingVolume];
|
|
5056
|
+
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];
|
|
4732
5057
|
this._contentBoundingVolume = this._contentBoundingVolumes[0] || null;
|
|
4733
5058
|
}
|
|
4734
5059
|
/**
|
|
@@ -4748,8 +5073,8 @@ var Tile3D = class {
|
|
|
4748
5073
|
};
|
|
4749
5074
|
|
|
4750
5075
|
// dist/tileset-3d/format-3d-tiles/tiles-3d-source.js
|
|
4751
|
-
var
|
|
4752
|
-
var
|
|
5076
|
+
var import_geospatial10 = require("@math.gl/geospatial");
|
|
5077
|
+
var import_core12 = require("@math.gl/core");
|
|
4753
5078
|
|
|
4754
5079
|
// dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js
|
|
4755
5080
|
var Tileset3DTraverser = class extends TilesetTraverser {
|
|
@@ -4770,14 +5095,201 @@ var Tileset3DTraverser = class extends TilesetTraverser {
|
|
|
4770
5095
|
}
|
|
4771
5096
|
return true;
|
|
4772
5097
|
}
|
|
5098
|
+
/**
|
|
5099
|
+
* Runs normal replacement traversal or the dedicated skip-LOD traversal selected by options.
|
|
5100
|
+
*
|
|
5101
|
+
* @param root - Root of the runtime subtree to traverse.
|
|
5102
|
+
* @param frameState - Current culling and LOD state.
|
|
5103
|
+
*/
|
|
5104
|
+
executeTraversal(root, frameState) {
|
|
5105
|
+
if (!this.isSkipLevelOfDetailEnabled()) {
|
|
5106
|
+
super.executeTraversal(root, frameState);
|
|
5107
|
+
return;
|
|
5108
|
+
}
|
|
5109
|
+
this.executeSkipTraversal(root, frameState);
|
|
5110
|
+
}
|
|
5111
|
+
/**
|
|
5112
|
+
* Traverses visible replacement branches without requesting skipped intermediate content.
|
|
5113
|
+
*
|
|
5114
|
+
* Base-traversal tiles establish coarse coverage. Below that base, only final desired tiles and
|
|
5115
|
+
* tiles that cross the configured depth/SSE thresholds are requested. Already available
|
|
5116
|
+
* ancestors remain selectable while those requests stream in.
|
|
5117
|
+
*
|
|
5118
|
+
* @param root - Root of the runtime subtree to traverse.
|
|
5119
|
+
* @param frameState - Current culling and LOD state.
|
|
5120
|
+
*/
|
|
5121
|
+
executeSkipTraversal(root, frameState) {
|
|
5122
|
+
const stack = [root];
|
|
5123
|
+
root._selectionDepth = root.parent ? root.parent._selectionDepth : 1;
|
|
5124
|
+
while (stack.length > 0) {
|
|
5125
|
+
const tile = stack.pop();
|
|
5126
|
+
const parentRefines = !tile.parent || tile.parent._shouldRefine;
|
|
5127
|
+
const shouldRefine = this.canTraverse(tile, frameState) && this.updateAndPushSkipChildren(tile, frameState, stack) && parentRefines;
|
|
5128
|
+
const stoppedRefining = !shouldRefine && parentRefines;
|
|
5129
|
+
if (!tile.hasRenderContent) {
|
|
5130
|
+
this.emptyTiles[tile.id] = tile;
|
|
5131
|
+
this.loadTile(tile, frameState);
|
|
5132
|
+
if (stoppedRefining) {
|
|
5133
|
+
this.selectDesiredTile(tile, frameState);
|
|
5134
|
+
}
|
|
5135
|
+
} else if (tile.refine === TILE_REFINEMENT.ADD) {
|
|
5136
|
+
this.loadTile(tile, frameState);
|
|
5137
|
+
this.selectDesiredTile(tile, frameState);
|
|
5138
|
+
} else if (tile.refine === TILE_REFINEMENT.REPLACE) {
|
|
5139
|
+
if (this.isInBaseTraversal(tile, frameState)) {
|
|
5140
|
+
this.loadTile(tile, frameState);
|
|
5141
|
+
if (stoppedRefining) {
|
|
5142
|
+
this.selectDesiredTile(tile, frameState);
|
|
5143
|
+
}
|
|
5144
|
+
} else if (stoppedRefining) {
|
|
5145
|
+
this.loadTile(tile, frameState);
|
|
5146
|
+
this.selectDesiredTile(tile, frameState);
|
|
5147
|
+
} else if (this.hasReachedSkippingThreshold(tile, frameState)) {
|
|
5148
|
+
this.loadTile(tile, frameState);
|
|
5149
|
+
}
|
|
5150
|
+
}
|
|
5151
|
+
this.touchTile(tile, frameState);
|
|
5152
|
+
tile._shouldRefine = shouldRefine;
|
|
5153
|
+
}
|
|
5154
|
+
this.completeTraversal(frameState);
|
|
5155
|
+
}
|
|
5156
|
+
/**
|
|
5157
|
+
* Updates and pushes visible children for skip traversal without requiring sibling readiness.
|
|
5158
|
+
*
|
|
5159
|
+
* @param tile - Parent whose children are considered.
|
|
5160
|
+
* @param frameState - Current culling and LOD state.
|
|
5161
|
+
* @param stack - Depth-first traversal stack.
|
|
5162
|
+
* @returns `true` when at least one visible child continues refinement.
|
|
5163
|
+
*/
|
|
5164
|
+
updateAndPushSkipChildren(tile, frameState, stack) {
|
|
5165
|
+
this.updateChildTiles(tile, frameState);
|
|
5166
|
+
tile.children.sort(this.compareDistanceToCamera.bind(this));
|
|
5167
|
+
let hasVisibleChild = false;
|
|
5168
|
+
for (const child of tile.children) {
|
|
5169
|
+
child._selectionDepth = tile.hasRenderContent ? tile._selectionDepth + 1 : tile._selectionDepth;
|
|
5170
|
+
if (child.isVisibleAndInRequestVolume) {
|
|
5171
|
+
stack.push(child);
|
|
5172
|
+
hasVisibleChild = true;
|
|
5173
|
+
} else if (this.options.loadSiblings) {
|
|
5174
|
+
this.loadTile(child, frameState);
|
|
5175
|
+
this.touchTile(child, frameState);
|
|
5176
|
+
}
|
|
5177
|
+
}
|
|
5178
|
+
return hasVisibleChild;
|
|
5179
|
+
}
|
|
5180
|
+
/**
|
|
5181
|
+
* Determines whether a tile belongs to the coarse non-skipping portion of the traversal.
|
|
5182
|
+
*
|
|
5183
|
+
* @param tile - Tile considered for loading.
|
|
5184
|
+
* @param frameState - Current traversal frame.
|
|
5185
|
+
* @returns `true` when the tile should always be requested for fallback coverage.
|
|
5186
|
+
*/
|
|
5187
|
+
isInBaseTraversal(tile, frameState) {
|
|
5188
|
+
if (this.options.immediatelyLoadDesiredLevelOfDetail) {
|
|
5189
|
+
return false;
|
|
5190
|
+
}
|
|
5191
|
+
if (!this.findNearestRequestedOrLoadedAncestor(tile, frameState)) {
|
|
5192
|
+
return true;
|
|
5193
|
+
}
|
|
5194
|
+
const configuredBaseScreenSpaceError = Number.isFinite(this.options.baseScreenSpaceError) ? Math.max(this.options.baseScreenSpaceError, 0) : 1024;
|
|
5195
|
+
const baseScreenSpaceError = Math.max(configuredBaseScreenSpaceError, tile.tileset.memoryAdjustedScreenSpaceError);
|
|
5196
|
+
if (tile._screenSpaceError === 0 && tile.parent) {
|
|
5197
|
+
return tile.parent._screenSpaceError > baseScreenSpaceError;
|
|
5198
|
+
}
|
|
5199
|
+
return tile._screenSpaceError > baseScreenSpaceError;
|
|
5200
|
+
}
|
|
5201
|
+
/**
|
|
5202
|
+
* Determines whether a skipped branch has crossed its configured request threshold.
|
|
5203
|
+
*
|
|
5204
|
+
* @param tile - Tile considered for loading.
|
|
5205
|
+
* @param frameState - Current traversal frame.
|
|
5206
|
+
* @returns `true` when the tile must be requested instead of skipped.
|
|
5207
|
+
*/
|
|
5208
|
+
hasReachedSkippingThreshold(tile, frameState) {
|
|
5209
|
+
if (this.options.immediatelyLoadDesiredLevelOfDetail) {
|
|
5210
|
+
return false;
|
|
5211
|
+
}
|
|
5212
|
+
const progressiveResolutionLeaf = tile._priorityProgressiveResolution && tile._screenSpaceErrorProgressiveResolution <= tile.tileset.memoryAdjustedScreenSpaceError && Boolean(tile.parent && tile.parent._screenSpaceErrorProgressiveResolution > tile.tileset.memoryAdjustedScreenSpaceError);
|
|
5213
|
+
if (progressiveResolutionLeaf) {
|
|
5214
|
+
return true;
|
|
5215
|
+
}
|
|
5216
|
+
const ancestor = this.findNearestRequestedOrLoadedAncestor(tile, frameState);
|
|
5217
|
+
if (!ancestor) {
|
|
5218
|
+
return false;
|
|
5219
|
+
}
|
|
5220
|
+
const skipScreenSpaceErrorFactor = Number.isFinite(this.options.skipScreenSpaceErrorFactor) && this.options.skipScreenSpaceErrorFactor > 0 ? this.options.skipScreenSpaceErrorFactor : 16;
|
|
5221
|
+
const skipLevels = Number.isFinite(this.options.skipLevels) ? Math.max(Math.floor(this.options.skipLevels), 0) : 1;
|
|
5222
|
+
return tile._screenSpaceError < ancestor._screenSpaceError / skipScreenSpaceErrorFactor && tile.depth > ancestor.depth + skipLevels;
|
|
5223
|
+
}
|
|
5224
|
+
/**
|
|
5225
|
+
* Finds the nearest ancestor whose render content is loaded, loading, or requested this frame.
|
|
5226
|
+
*
|
|
5227
|
+
* @param tile - Descendant whose request threshold needs an anchor.
|
|
5228
|
+
* @param frameState - Current traversal frame.
|
|
5229
|
+
* @returns The nearest request anchor, or `null` when none exists.
|
|
5230
|
+
*/
|
|
5231
|
+
findNearestRequestedOrLoadedAncestor(tile, frameState) {
|
|
5232
|
+
let ancestor = tile.parent;
|
|
5233
|
+
while (ancestor) {
|
|
5234
|
+
const contentIsUsableAnchor = ancestor.hasRenderContent && !ancestor.contentFailed && (!ancestor.hasUnloadedContent || ancestor._requestedFrame === frameState.frameNumber);
|
|
5235
|
+
if (contentIsUsableAnchor) {
|
|
5236
|
+
return ancestor;
|
|
5237
|
+
}
|
|
5238
|
+
ancestor = ancestor.parent;
|
|
5239
|
+
}
|
|
5240
|
+
return null;
|
|
5241
|
+
}
|
|
5242
|
+
/**
|
|
5243
|
+
* Selects the desired tile, its nearest ready ancestor, or nearby ready descendants.
|
|
5244
|
+
*
|
|
5245
|
+
* @param tile - Tile that ended the desired refinement branch.
|
|
5246
|
+
* @param frameState - Current culling state.
|
|
5247
|
+
*/
|
|
5248
|
+
selectDesiredTile(tile, frameState) {
|
|
5249
|
+
let fallbackTile = tile;
|
|
5250
|
+
while (fallbackTile) {
|
|
5251
|
+
if (this.shouldSelectTile(fallbackTile, frameState)) {
|
|
5252
|
+
this.selectTile(fallbackTile, frameState);
|
|
5253
|
+
return;
|
|
5254
|
+
}
|
|
5255
|
+
fallbackTile = fallbackTile.parent;
|
|
5256
|
+
}
|
|
5257
|
+
this.selectLoadedDescendants(tile, frameState);
|
|
5258
|
+
}
|
|
5259
|
+
/**
|
|
5260
|
+
* Selects ready descendants near an unavailable desired tile to reduce temporary empty regions.
|
|
5261
|
+
*
|
|
5262
|
+
* @param root - Unavailable tile whose descendants are searched.
|
|
5263
|
+
* @param frameState - Current culling state.
|
|
5264
|
+
*/
|
|
5265
|
+
selectLoadedDescendants(root, frameState) {
|
|
5266
|
+
const stack = [{ tile: root, depth: 0 }];
|
|
5267
|
+
while (stack.length > 0) {
|
|
5268
|
+
const { tile, depth } = stack.pop();
|
|
5269
|
+
for (const child of tile.children) {
|
|
5270
|
+
this.updateTile(child, frameState);
|
|
5271
|
+
if (!child.isVisibleAndInRequestVolume) {
|
|
5272
|
+
continue;
|
|
5273
|
+
}
|
|
5274
|
+
if (child.contentAvailable) {
|
|
5275
|
+
this.selectTile(child, frameState);
|
|
5276
|
+
this.touchTile(child, frameState);
|
|
5277
|
+
} else if (depth < 1) {
|
|
5278
|
+
stack.push({ tile: child, depth: depth + 1 });
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
5281
|
+
}
|
|
5282
|
+
}
|
|
4773
5283
|
compareDistanceToCamera(a, b) {
|
|
4774
5284
|
return b._distanceToCamera === 0 && a._distanceToCamera === 0 ? b._centerZDepth - a._centerZDepth : b._distanceToCamera - a._distanceToCamera;
|
|
4775
5285
|
}
|
|
4776
5286
|
/**
|
|
4777
|
-
* Starts an implicit subtree request
|
|
5287
|
+
* Starts an implicit subtree request after culling and request-volume eligibility.
|
|
4778
5288
|
*
|
|
4779
|
-
* The
|
|
4780
|
-
*
|
|
5289
|
+
* The first subtree of an implicit hierarchy materializes independently of SSE because its
|
|
5290
|
+
* placeholder has no render content. Deeper subtree boundaries remain SSE-gated. The current
|
|
5291
|
+
* parent remains the traversal boundary while metadata is loading, which preserves REPLACE
|
|
5292
|
+
* coverage and ADD accumulation. Request scheduling reads the tile's existing
|
|
4781
5293
|
* progressive-resolution and foveated metrics, so subtree metadata follows the same priority
|
|
4782
5294
|
* policy as render content. A completion notification lets the owning tileset publish the newly
|
|
4783
5295
|
* materialized traversal result on the next update.
|
|
@@ -4786,7 +5298,9 @@ var Tileset3DTraverser = class extends TilesetTraverser {
|
|
|
4786
5298
|
* @param frameState - Current culling and LOD state.
|
|
4787
5299
|
*/
|
|
4788
5300
|
updateChildTiles(tile, frameState) {
|
|
4789
|
-
|
|
5301
|
+
var _a;
|
|
5302
|
+
const isImplicitHierarchyRoot = ((_a = tile.header.implicitSubtree) == null ? void 0 : _a.coordinates.level) === 0;
|
|
5303
|
+
if (tile.hasUnloadedChildren && tile.isVisibleAndInRequestVolume && (isImplicitHierarchyRoot || this.shouldRefine(tile, frameState))) {
|
|
4790
5304
|
const requestKey = `${frameState.viewport.id}:${tile.id}`;
|
|
4791
5305
|
if (!this.pendingImplicitSubtrees.has(requestKey)) {
|
|
4792
5306
|
this.pendingImplicitSubtrees.set(requestKey, frameState.frameNumber);
|
|
@@ -4977,7 +5491,7 @@ function getI3SSpatialReference(layer) {
|
|
|
4977
5491
|
const verticalUnitScale = getI3SVerticalUnitScale(verticalUnit, layer.ZFactor);
|
|
4978
5492
|
const heightReference = heightModel === "ellipsoidal" ? "ellipsoidal" : heightModel === "gravity_related_height" ? "orthometric" : "unknown";
|
|
4979
5493
|
const sourceIdentifier = getCrsIdentifier(spatialReference);
|
|
4980
|
-
const coordinateFrame = sourceIdentifier === void 0 ?
|
|
5494
|
+
const coordinateFrame = sourceIdentifier === void 0 ? sourceCrs ? getSpatialCoordinateFrame(sourceCrs) : "unknown" : getSpatialCoordinateFrame(`EPSG:${sourceIdentifier}`);
|
|
4981
5495
|
const units = getI3SCoordinateUnits(coordinateFrame, verticalUnit, layer.ZFactor);
|
|
4982
5496
|
const warnings = [];
|
|
4983
5497
|
const elevationMode = getI3SElevationMode((_e = layer.elevationInfo) == null ? void 0 : _e.mode);
|
|
@@ -5035,6 +5549,10 @@ function getI3SElevationMode(mode) {
|
|
|
5035
5549
|
}
|
|
5036
5550
|
function get3DTilesSpatialReference(tileset) {
|
|
5037
5551
|
var _a, _b;
|
|
5552
|
+
const draftSpatialReference = getDraft3DTilesSpatialReference(tileset);
|
|
5553
|
+
if (draftSpatialReference) {
|
|
5554
|
+
return draftSpatialReference;
|
|
5555
|
+
}
|
|
5038
5556
|
const geocentricCrs = getTilesetSemanticValue(tileset, "TILESET_CRS_GEOCENTRIC");
|
|
5039
5557
|
const coordinateEpoch = getTilesetSemanticValue(tileset, "TILESET_CRS_COORDINATE_EPOCH");
|
|
5040
5558
|
const warnings = [];
|
|
@@ -5072,6 +5590,87 @@ function get3DTilesSpatialReference(tileset) {
|
|
|
5072
5590
|
warnings
|
|
5073
5591
|
});
|
|
5074
5592
|
}
|
|
5593
|
+
function getDraft3DTilesSpatialReference(tileset) {
|
|
5594
|
+
var _a, _b, _c;
|
|
5595
|
+
const extension = (_a = tileset.extensions) == null ? void 0 : _a.EXT_geospatial_crs;
|
|
5596
|
+
if (!extension) {
|
|
5597
|
+
return void 0;
|
|
5598
|
+
}
|
|
5599
|
+
const warnings = [];
|
|
5600
|
+
let sourceCrs;
|
|
5601
|
+
let verticalCrs;
|
|
5602
|
+
let epoch;
|
|
5603
|
+
let representation;
|
|
5604
|
+
if (extension.format === "wkid") {
|
|
5605
|
+
const wkidExtension = (_b = extension.extensions) == null ? void 0 : _b.EXT_geospatial_crs_wkid;
|
|
5606
|
+
if (typeof (wkidExtension == null ? void 0 : wkidExtension.authority) === "string" && Number.isInteger(wkidExtension.wkid)) {
|
|
5607
|
+
sourceCrs = `${wkidExtension.authority}:${wkidExtension.wkid}`;
|
|
5608
|
+
representation = "identifier";
|
|
5609
|
+
if (Number.isInteger(wkidExtension.vcsWkid)) {
|
|
5610
|
+
verticalCrs = `${wkidExtension.authority}:${wkidExtension.vcsWkid}`;
|
|
5611
|
+
}
|
|
5612
|
+
epoch = parseCoordinateEpoch(wkidExtension.epoch);
|
|
5613
|
+
if (wkidExtension.epoch !== void 0 && epoch === void 0) {
|
|
5614
|
+
warnings.push("EXT_geospatial_crs_wkid epoch is not a finite decimal year");
|
|
5615
|
+
}
|
|
5616
|
+
} else {
|
|
5617
|
+
warnings.push("EXT_geospatial_crs_wkid requires string authority and integer wkid");
|
|
5618
|
+
}
|
|
5619
|
+
} else if (extension.format === "wkt2") {
|
|
5620
|
+
const wktExtension = (_c = extension.extensions) == null ? void 0 : _c.EXT_geospatial_crs_wkt2;
|
|
5621
|
+
if (typeof (wktExtension == null ? void 0 : wktExtension.wkt2) === "string" && wktExtension.wkt2.trim()) {
|
|
5622
|
+
sourceCrs = wktExtension.wkt2;
|
|
5623
|
+
representation = "wkt";
|
|
5624
|
+
} else {
|
|
5625
|
+
warnings.push("EXT_geospatial_crs_wkt2 requires a nonempty wkt2 string");
|
|
5626
|
+
}
|
|
5627
|
+
} else {
|
|
5628
|
+
warnings.push(`Unsupported EXT_geospatial_crs format ${String(extension.format)}`);
|
|
5629
|
+
}
|
|
5630
|
+
const coordinateFrame = representation === "wkt" ? getSpatialCoordinateFrame(sourceCrs) : getKnownCrsIdentifierCoordinateFrame(sourceCrs) || "unknown";
|
|
5631
|
+
const verticalSemantics = getDraftVerticalCrsSemantics(verticalCrs);
|
|
5632
|
+
if (verticalCrs && !verticalSemantics) {
|
|
5633
|
+
warnings.push(`Unsupported vertical CRS ${String(verticalCrs)}; vertical unit and height reference are unknown`);
|
|
5634
|
+
}
|
|
5635
|
+
const verticalUnit = verticalCrs ? verticalSemantics == null ? void 0 : verticalSemantics.unit : "meter";
|
|
5636
|
+
return createTilesetSpatialReference({
|
|
5637
|
+
sourceCrs,
|
|
5638
|
+
sourceCrsState: sourceCrs ? "explicit" : "unknown",
|
|
5639
|
+
sourceCrsRepresentation: representation,
|
|
5640
|
+
verticalCrs,
|
|
5641
|
+
coordinateEpoch: epoch,
|
|
5642
|
+
units: coordinateFrame === "geocentric" ? ["meter", "meter", "meter"] : coordinateFrame === "geographic" && verticalUnit ? ["degree", "degree", verticalUnit] : void 0,
|
|
5643
|
+
verticalUnitScale: verticalCrs ? (verticalSemantics == null ? void 0 : verticalSemantics.verticalUnitScale) ?? Number.NaN : 1,
|
|
5644
|
+
heightReference: verticalCrs ? (verticalSemantics == null ? void 0 : verticalSemantics.heightReference) ?? "unknown" : sourceCrs ? "ellipsoidal" : "unknown",
|
|
5645
|
+
coordinateFrame,
|
|
5646
|
+
axisOrder: sourceCrs ? "xyz" : "unknown",
|
|
5647
|
+
provenance: "metadata",
|
|
5648
|
+
warnings
|
|
5649
|
+
});
|
|
5650
|
+
}
|
|
5651
|
+
function getDraftVerticalCrsSemantics(verticalCrs) {
|
|
5652
|
+
if (typeof verticalCrs !== "string") {
|
|
5653
|
+
return void 0;
|
|
5654
|
+
}
|
|
5655
|
+
const epsgMatch = /^EPSG:(\d+)$/i.exec(verticalCrs);
|
|
5656
|
+
if (!epsgMatch) {
|
|
5657
|
+
return void 0;
|
|
5658
|
+
}
|
|
5659
|
+
switch (Number(epsgMatch[1])) {
|
|
5660
|
+
case 5702:
|
|
5661
|
+
// NGVD29 height (ftUS)
|
|
5662
|
+
case 6360:
|
|
5663
|
+
return {
|
|
5664
|
+
unit: "us-foot",
|
|
5665
|
+
verticalUnitScale: 1200 / 3937,
|
|
5666
|
+
heightReference: "orthometric"
|
|
5667
|
+
};
|
|
5668
|
+
case 5703:
|
|
5669
|
+
return { unit: "meter", verticalUnitScale: 1, heightReference: "orthometric" };
|
|
5670
|
+
default:
|
|
5671
|
+
return void 0;
|
|
5672
|
+
}
|
|
5673
|
+
}
|
|
5075
5674
|
function parseCoordinateEpoch(value) {
|
|
5076
5675
|
if (typeof value !== "string" && typeof value !== "number") {
|
|
5077
5676
|
return void 0;
|
|
@@ -5096,71 +5695,493 @@ function getI3SVerticalCrsDefinition(spatialReference) {
|
|
|
5096
5695
|
function getCrsIdentifier(spatialReference) {
|
|
5097
5696
|
return (spatialReference == null ? void 0 : spatialReference.latestWkid) ?? (spatialReference == null ? void 0 : spatialReference.wkid);
|
|
5098
5697
|
}
|
|
5099
|
-
function
|
|
5100
|
-
|
|
5101
|
-
|
|
5698
|
+
function getTilesetSemanticValue(tileset, semantic) {
|
|
5699
|
+
var _a, _b, _c, _d;
|
|
5700
|
+
const classIdentifier = (_a = tileset.metadata) == null ? void 0 : _a.class;
|
|
5701
|
+
if (!classIdentifier) {
|
|
5702
|
+
return void 0;
|
|
5102
5703
|
}
|
|
5103
|
-
|
|
5104
|
-
|
|
5704
|
+
const classDefinition = (_c = (_b = tileset.schema) == null ? void 0 : _b.classes) == null ? void 0 : _c[classIdentifier];
|
|
5705
|
+
const propertyDefinitions = classDefinition == null ? void 0 : classDefinition.properties;
|
|
5706
|
+
const propertyValues = (_d = tileset.metadata) == null ? void 0 : _d.properties;
|
|
5707
|
+
for (const [propertyIdentifier, propertyDefinition] of Object.entries(propertyDefinitions || {})) {
|
|
5708
|
+
if (propertyDefinition.semantic === semantic) {
|
|
5709
|
+
return propertyValues == null ? void 0 : propertyValues[propertyIdentifier];
|
|
5710
|
+
}
|
|
5105
5711
|
}
|
|
5106
|
-
return
|
|
5712
|
+
return void 0;
|
|
5107
5713
|
}
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5714
|
+
|
|
5715
|
+
// dist/spatial/spatial-coordinate-transformer.js
|
|
5716
|
+
var import_core10 = require("@math.gl/core");
|
|
5717
|
+
var import_geospatial7 = require("@math.gl/geospatial");
|
|
5718
|
+
var import_proj42 = require("@math.gl/proj4");
|
|
5719
|
+
|
|
5720
|
+
// dist/spatial/spatial-resource-registry.js
|
|
5721
|
+
var import_geoid = require("@math.gl/geoid");
|
|
5722
|
+
var import_proj4 = require("@math.gl/proj4");
|
|
5723
|
+
var geoidModels = /* @__PURE__ */ new Map();
|
|
5724
|
+
function registerSpatialCrs(name, definition) {
|
|
5725
|
+
validateResourceName(name, "CRS");
|
|
5726
|
+
import_proj4.Proj4Projection.defineProjectionAliases({ [name]: definition });
|
|
5727
|
+
}
|
|
5728
|
+
function registerSpatialDatumGrid(name, data) {
|
|
5729
|
+
validateResourceName(name, "datum grid");
|
|
5730
|
+
import_proj4.Proj4Projection.registerDatumGrid(name, data);
|
|
5731
|
+
}
|
|
5732
|
+
function registerGeoidModel(name, geoid) {
|
|
5733
|
+
validateResourceName(name, "geoid model");
|
|
5734
|
+
geoidModels.set(name, geoid);
|
|
5735
|
+
}
|
|
5736
|
+
function registerGeoidModelFromPgm(name, data, options = {}) {
|
|
5737
|
+
const geoid = (0, import_geoid.parsePGM)(data, options);
|
|
5738
|
+
registerGeoidModel(name, geoid);
|
|
5739
|
+
return geoid;
|
|
5740
|
+
}
|
|
5741
|
+
function getGeoidModel(name) {
|
|
5742
|
+
return geoidModels.get(name);
|
|
5743
|
+
}
|
|
5744
|
+
function validateResourceName(name, resourceType) {
|
|
5745
|
+
if (!name.trim()) {
|
|
5746
|
+
throw new Error(`${resourceType} name must not be empty`);
|
|
5120
5747
|
}
|
|
5121
|
-
|
|
5122
|
-
|
|
5748
|
+
}
|
|
5749
|
+
|
|
5750
|
+
// dist/spatial/spatial-coordinate-transformer.js
|
|
5751
|
+
var SpatialCoordinateTransformer = class {
|
|
5752
|
+
/** Normalized spatial metadata describing this transformation. */
|
|
5753
|
+
spatialReference;
|
|
5754
|
+
/** Projection from the source CRS directly to the requested horizontal target CRS. */
|
|
5755
|
+
horizontalProjection;
|
|
5756
|
+
/** Projection from the source CRS to geographic longitude, latitude, and ellipsoidal height. */
|
|
5757
|
+
geographicProjection;
|
|
5758
|
+
/** Projection from adjusted geographic coordinates to the requested output CRS. */
|
|
5759
|
+
heightOutputProjection;
|
|
5760
|
+
/** Whether source coordinates use the WGS84 geocentric frame handled by math.gl. */
|
|
5761
|
+
sourceIsGeocentric;
|
|
5762
|
+
/** Whether output coordinates use the WGS84 geocentric frame handled by math.gl. */
|
|
5763
|
+
outputIsGeocentric;
|
|
5764
|
+
/** Whether source coordinates already use conventional WGS84 longitude/latitude order. */
|
|
5765
|
+
sourceIsGeographic;
|
|
5766
|
+
/** Whether output coordinates use conventional WGS84 longitude/latitude order. */
|
|
5767
|
+
outputIsGeographic;
|
|
5768
|
+
/** Geoid model used to convert between ellipsoidal and orthometric heights. */
|
|
5769
|
+
geoid;
|
|
5770
|
+
/**
|
|
5771
|
+
* Creates a coordinate transformer.
|
|
5772
|
+
*
|
|
5773
|
+
* @param spatialReference - Format-discovered and option-normalized spatial metadata.
|
|
5774
|
+
* @param options - Application options containing an optional geoid model.
|
|
5775
|
+
*/
|
|
5776
|
+
constructor(spatialReference, options = {}) {
|
|
5777
|
+
this.spatialReference = spatialReference;
|
|
5778
|
+
validateTransformRequest(spatialReference);
|
|
5779
|
+
const outputCrs = spatialReference.targetCrs || spatialReference.sourceCrs;
|
|
5780
|
+
this.sourceIsGeocentric = isWgs84Geocentric(spatialReference.sourceCrs);
|
|
5781
|
+
this.outputIsGeocentric = isWgs84Geocentric(outputCrs);
|
|
5782
|
+
this.sourceIsGeographic = isWgs84Geographic(spatialReference.sourceCrs);
|
|
5783
|
+
this.outputIsGeographic = isWgs84Geographic(outputCrs);
|
|
5784
|
+
if (spatialReference.sourceCrs && spatialReference.targetCrs && !this.sourceIsGeocentric && !this.outputIsGeocentric) {
|
|
5785
|
+
this.horizontalProjection = new import_proj42.Proj4Projection({
|
|
5786
|
+
from: getHorizontalProj4Definition(spatialReference.sourceCrs),
|
|
5787
|
+
to: getHorizontalProj4Definition(spatialReference.targetCrs),
|
|
5788
|
+
enforceAxis: false
|
|
5789
|
+
});
|
|
5790
|
+
}
|
|
5791
|
+
if (requiresHeightTransformation(spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
|
|
5792
|
+
if (!this.sourceIsGeographic && !this.sourceIsGeocentric) {
|
|
5793
|
+
this.geographicProjection = new import_proj42.Proj4Projection({
|
|
5794
|
+
from: getHorizontalProj4Definition(spatialReference.sourceCrs),
|
|
5795
|
+
to: WGS84_GEOGRAPHIC_CRS,
|
|
5796
|
+
enforceAxis: false
|
|
5797
|
+
});
|
|
5798
|
+
}
|
|
5799
|
+
if (!this.outputIsGeographic && !this.outputIsGeocentric) {
|
|
5800
|
+
this.heightOutputProjection = new import_proj42.Proj4Projection({
|
|
5801
|
+
from: WGS84_GEOGRAPHIC_CRS,
|
|
5802
|
+
to: getHorizontalProj4Definition(outputCrs),
|
|
5803
|
+
enforceAxis: false
|
|
5804
|
+
});
|
|
5805
|
+
}
|
|
5806
|
+
}
|
|
5807
|
+
if (requiresHeightTransformation(spatialReference)) {
|
|
5808
|
+
this.geoid = resolveGeoid(options.geoidModel);
|
|
5809
|
+
if (!this.geoid) {
|
|
5810
|
+
const modelName = typeof options.geoidModel === "string" ? ` "${options.geoidModel}"` : "";
|
|
5811
|
+
throw new Error(`Height conversion requires a registered geoid model${modelName}; call registerGeoidModel() or pass a parsed Geoid instance`);
|
|
5812
|
+
}
|
|
5813
|
+
}
|
|
5123
5814
|
}
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5815
|
+
/**
|
|
5816
|
+
* Transforms one `[x, y, z?]` coordinate while retaining additional components.
|
|
5817
|
+
*
|
|
5818
|
+
* @param coordinate - Source coordinate in the format adapter's normalized `x/y/z` order.
|
|
5819
|
+
* @returns A new transformed coordinate array.
|
|
5820
|
+
*/
|
|
5821
|
+
transformPosition(coordinate) {
|
|
5822
|
+
if (coordinate.length < 2) {
|
|
5823
|
+
throw new Error("A spatial coordinate must contain at least x and y components");
|
|
5127
5824
|
}
|
|
5128
|
-
|
|
5129
|
-
|
|
5825
|
+
const result = [...coordinate];
|
|
5826
|
+
if (requiresHeightTransformation(this.spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
|
|
5827
|
+
if (result.length < 3 || !Number.isFinite(result[2])) {
|
|
5828
|
+
throw new Error("Three-dimensional CRS conversion requires a finite z coordinate");
|
|
5829
|
+
}
|
|
5830
|
+
const geographic = this.toGeographic(result);
|
|
5831
|
+
if (requiresHeightTransformation(this.spatialReference)) {
|
|
5832
|
+
const geoidUndulation = this.geoid.getHeight(geographic[1], geographic[0]);
|
|
5833
|
+
geographic[2] = transformHeight(geographic[2], geoidUndulation, this.spatialReference.heightReference, this.spatialReference.targetHeightReference);
|
|
5834
|
+
}
|
|
5835
|
+
const projected = this.fromGeographic(geographic);
|
|
5836
|
+
result.splice(0, projected.length, ...projected);
|
|
5837
|
+
return result;
|
|
5130
5838
|
}
|
|
5839
|
+
if (this.horizontalProjection) {
|
|
5840
|
+
const projected = this.horizontalProjection.project(result.slice(0, 3));
|
|
5841
|
+
result.splice(0, projected.length, ...projected);
|
|
5842
|
+
}
|
|
5843
|
+
return result;
|
|
5131
5844
|
}
|
|
5132
|
-
|
|
5845
|
+
/** Transform a packed sequence of xyz positions, preserving the input array type only when safe. */
|
|
5846
|
+
transformPositions(positions) {
|
|
5847
|
+
if (positions.length % 3 !== 0) {
|
|
5848
|
+
throw new Error("Packed spatial positions must contain a multiple of three components");
|
|
5849
|
+
}
|
|
5850
|
+
const transformedPositions = new Float64Array(positions.length);
|
|
5851
|
+
for (let index = 0; index < positions.length; index += 3) {
|
|
5852
|
+
const transformed = this.transformPosition([
|
|
5853
|
+
Number(positions[index]),
|
|
5854
|
+
Number(positions[index + 1]),
|
|
5855
|
+
Number(positions[index + 2])
|
|
5856
|
+
]);
|
|
5857
|
+
transformedPositions[index] = transformed[0];
|
|
5858
|
+
transformedPositions[index + 1] = transformed[1];
|
|
5859
|
+
transformedPositions[index + 2] = transformed[2];
|
|
5860
|
+
}
|
|
5861
|
+
return transformedPositions;
|
|
5862
|
+
}
|
|
5863
|
+
/** Transform packed xyz normals using a local finite-difference tangent approximation. */
|
|
5864
|
+
transformNormals(normals, positions) {
|
|
5865
|
+
if (normals.length !== positions.length || normals.length % 3 !== 0) {
|
|
5866
|
+
throw new Error("Spatial normals and positions must have matching xyz component counts");
|
|
5867
|
+
}
|
|
5868
|
+
const transformedNormals = new Float32Array(normals.length);
|
|
5869
|
+
const epsilon = 1e-5;
|
|
5870
|
+
for (let index = 0; index < normals.length; index += 3) {
|
|
5871
|
+
const position = [
|
|
5872
|
+
Number(positions[index]),
|
|
5873
|
+
Number(positions[index + 1]),
|
|
5874
|
+
Number(positions[index + 2])
|
|
5875
|
+
];
|
|
5876
|
+
const normal = [
|
|
5877
|
+
Number(normals[index]),
|
|
5878
|
+
Number(normals[index + 1]),
|
|
5879
|
+
Number(normals[index + 2])
|
|
5880
|
+
];
|
|
5881
|
+
const jacobian = getFiniteDifferenceJacobian(this, position, epsilon);
|
|
5882
|
+
const transformedNormal = inverseTransposeMultiply(jacobian, normal);
|
|
5883
|
+
const length = Math.hypot(...transformedNormal);
|
|
5884
|
+
if (length > 0 && Number.isFinite(length)) {
|
|
5885
|
+
transformedNormals[index] = transformedNormal[0] / length;
|
|
5886
|
+
transformedNormals[index + 1] = transformedNormal[1] / length;
|
|
5887
|
+
transformedNormals[index + 2] = transformedNormal[2] / length;
|
|
5888
|
+
} else {
|
|
5889
|
+
transformedNormals[index] = normal[0];
|
|
5890
|
+
transformedNormals[index + 1] = normal[1];
|
|
5891
|
+
transformedNormals[index + 2] = normal[2];
|
|
5892
|
+
}
|
|
5893
|
+
}
|
|
5894
|
+
return transformedNormals;
|
|
5895
|
+
}
|
|
5896
|
+
/** Convert one source coordinate to conventional WGS84 longitude, latitude, and height. */
|
|
5897
|
+
toGeographic(coordinate) {
|
|
5898
|
+
if (this.sourceIsGeocentric) {
|
|
5899
|
+
return Array.from(import_geospatial7.Ellipsoid.WGS84.cartesianToCartographic(new import_core10.Vector3(coordinate)));
|
|
5900
|
+
}
|
|
5901
|
+
if (this.sourceIsGeographic) {
|
|
5902
|
+
return coordinate.slice(0, 3);
|
|
5903
|
+
}
|
|
5904
|
+
return this.geographicProjection.project(coordinate.slice(0, 3));
|
|
5905
|
+
}
|
|
5906
|
+
/** Convert one conventional WGS84 geographic coordinate to the selected output CRS. */
|
|
5907
|
+
fromGeographic(coordinate) {
|
|
5908
|
+
if (this.outputIsGeocentric) {
|
|
5909
|
+
return Array.from(import_geospatial7.Ellipsoid.WGS84.cartographicToCartesian(new import_core10.Vector3(coordinate)));
|
|
5910
|
+
}
|
|
5911
|
+
if (this.outputIsGeographic) {
|
|
5912
|
+
return coordinate.slice(0, 3);
|
|
5913
|
+
}
|
|
5914
|
+
return this.heightOutputProjection.project(coordinate.slice(0, 3));
|
|
5915
|
+
}
|
|
5916
|
+
};
|
|
5917
|
+
function getFiniteDifferenceJacobian(transformer, position, epsilon) {
|
|
5918
|
+
const columns = [];
|
|
5919
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
5920
|
+
const plus = position.slice();
|
|
5921
|
+
const minus = position.slice();
|
|
5922
|
+
plus[axis] += epsilon;
|
|
5923
|
+
minus[axis] -= epsilon;
|
|
5924
|
+
const plusPosition = transformer.transformPosition(plus);
|
|
5925
|
+
const minusPosition = transformer.transformPosition(minus);
|
|
5926
|
+
columns.push([
|
|
5927
|
+
(plusPosition[0] - minusPosition[0]) / (2 * epsilon),
|
|
5928
|
+
(plusPosition[1] - minusPosition[1]) / (2 * epsilon),
|
|
5929
|
+
(plusPosition[2] - minusPosition[2]) / (2 * epsilon)
|
|
5930
|
+
]);
|
|
5931
|
+
}
|
|
5932
|
+
return columns;
|
|
5133
5933
|
}
|
|
5134
|
-
function
|
|
5135
|
-
|
|
5136
|
-
const
|
|
5137
|
-
if (!
|
|
5138
|
-
return
|
|
5934
|
+
function inverseTransposeMultiply(jacobianColumns, vector) {
|
|
5935
|
+
const [a, b, c] = jacobianColumns;
|
|
5936
|
+
const determinant = a[0] * (b[1] * c[2] - b[2] * c[1]) - b[0] * (a[1] * c[2] - a[2] * c[1]) + c[0] * (a[1] * b[2] - a[2] * b[1]);
|
|
5937
|
+
if (!Number.isFinite(determinant) || Math.abs(determinant) < 1e-15) {
|
|
5938
|
+
return vector;
|
|
5139
5939
|
}
|
|
5140
|
-
const
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5940
|
+
const inverseTranspose = [
|
|
5941
|
+
[b[1] * c[2] - b[2] * c[1], a[2] * c[1] - a[1] * c[2], a[1] * b[2] - a[2] * b[1]],
|
|
5942
|
+
[b[2] * c[0] - b[0] * c[2], a[0] * c[2] - a[2] * c[0], a[2] * b[0] - a[0] * b[2]],
|
|
5943
|
+
[b[0] * c[1] - b[1] * c[0], a[1] * c[0] - a[0] * c[1], a[0] * b[1] - a[1] * b[0]]
|
|
5944
|
+
];
|
|
5945
|
+
return inverseTranspose.map((row) => (row[0] * vector[0] + row[1] * vector[1] + row[2] * vector[2]) / determinant);
|
|
5946
|
+
}
|
|
5947
|
+
function getHorizontalProj4Definition(definition) {
|
|
5948
|
+
if (!definition) {
|
|
5949
|
+
throw new Error("Cannot construct a projection because the CRS is unknown");
|
|
5950
|
+
}
|
|
5951
|
+
return (0, import_proj42.toProj4CRSDefinition)(definition, { mode: "horizontal" });
|
|
5952
|
+
}
|
|
5953
|
+
function validateTransformRequest(spatialReference) {
|
|
5954
|
+
if (spatialReference.outputCoordinates === "local-enu") {
|
|
5955
|
+
throw new Error("local-enu output requires a dataset-derived local origin and must be created by a tileset source");
|
|
5956
|
+
}
|
|
5957
|
+
if (spatialReference.outputCoordinates === "target-crs" && !spatialReference.targetCrs) {
|
|
5958
|
+
throw new Error("target-crs output requires targetCrs");
|
|
5959
|
+
}
|
|
5960
|
+
if (!spatialReference.sourceCrs && spatialReference.status === "unresolved") {
|
|
5961
|
+
throw new Error("Cannot transform coordinates because the source CRS is unknown");
|
|
5962
|
+
}
|
|
5963
|
+
if (requiresHeightTransformation(spatialReference) && spatialReference.heightReference === "unknown") {
|
|
5964
|
+
throw new Error("Cannot convert heights because the source height reference is unknown");
|
|
5965
|
+
}
|
|
5966
|
+
if (spatialReference.coordinateFrame === "geocentric" && !isWgs84Geocentric(spatialReference.sourceCrs)) {
|
|
5967
|
+
throw new Error("Only EPSG:4978 geocentric coordinates are supported by the current spatial transformer");
|
|
5968
|
+
}
|
|
5969
|
+
if (spatialReference.status === "unresolved") {
|
|
5970
|
+
throw new Error("The requested spatial output cannot be resolved from the available metadata");
|
|
5971
|
+
}
|
|
5972
|
+
}
|
|
5973
|
+
function isWgs84Geocentric(definition) {
|
|
5974
|
+
return typeof definition === "string" && normalizeCrsIdentifier(definition) === WGS84_GEOCENTRIC_CRS;
|
|
5975
|
+
}
|
|
5976
|
+
function isWgs84Geographic(definition) {
|
|
5977
|
+
if (typeof definition !== "string") {
|
|
5978
|
+
return false;
|
|
5979
|
+
}
|
|
5980
|
+
const identifier = normalizeCrsIdentifier(definition);
|
|
5981
|
+
return identifier === WGS84_GEOGRAPHIC_CRS || identifier === "EPSG:4979" || identifier === "OGC:CRS84";
|
|
5982
|
+
}
|
|
5983
|
+
function requiresHeightTransformation(spatialReference) {
|
|
5984
|
+
const target = spatialReference.targetHeightReference;
|
|
5985
|
+
return target !== "native" && target !== spatialReference.heightReference;
|
|
5986
|
+
}
|
|
5987
|
+
function resolveGeoid(model) {
|
|
5988
|
+
return typeof model === "string" ? getGeoidModel(model) : model;
|
|
5989
|
+
}
|
|
5990
|
+
function transformHeight(height, geoidUndulation, source, target) {
|
|
5991
|
+
if (source === target || target === "native") {
|
|
5992
|
+
return height;
|
|
5993
|
+
}
|
|
5994
|
+
if (source === "orthometric" && target === "ellipsoidal") {
|
|
5995
|
+
return height + geoidUndulation;
|
|
5996
|
+
}
|
|
5997
|
+
if (source === "ellipsoidal" && target === "orthometric") {
|
|
5998
|
+
return height - geoidUndulation;
|
|
5999
|
+
}
|
|
6000
|
+
throw new Error(`Unsupported height conversion from ${source} to ${target}`);
|
|
6001
|
+
}
|
|
6002
|
+
|
|
6003
|
+
// dist/spatial/tiles-3d-spatial-transformer.js
|
|
6004
|
+
var import_core11 = require("@math.gl/core");
|
|
6005
|
+
var import_geospatial8 = require("@math.gl/geospatial");
|
|
6006
|
+
var Tiles3DSpatialTransformer = class {
|
|
6007
|
+
/** Normalized reference describing the completed operation. */
|
|
6008
|
+
spatialReference;
|
|
6009
|
+
coordinateTransformer;
|
|
6010
|
+
geographicCoordinateTransformer;
|
|
6011
|
+
/** Creates a 3D Tiles transformer for a requested target CRS. */
|
|
6012
|
+
constructor(spatialReference, options = {}) {
|
|
6013
|
+
this.coordinateTransformer = new SpatialCoordinateTransformer(spatialReference, options);
|
|
6014
|
+
const geographicSpatialReference = {
|
|
6015
|
+
...spatialReference,
|
|
6016
|
+
sourceCrs: "EPSG:4326",
|
|
6017
|
+
targetCrs: spatialReference.targetCrs || spatialReference.sourceCrs,
|
|
6018
|
+
coordinateFrame: "geographic",
|
|
6019
|
+
axisOrder: "xy"
|
|
6020
|
+
};
|
|
6021
|
+
this.geographicCoordinateTransformer = new SpatialCoordinateTransformer(geographicSpatialReference, options);
|
|
6022
|
+
this.spatialReference = spatialReference;
|
|
6023
|
+
}
|
|
6024
|
+
/** Transform packed POSITION values into the target CRS. */
|
|
6025
|
+
transformPositions(positions) {
|
|
6026
|
+
return this.coordinateTransformer.transformPositions(positions);
|
|
6027
|
+
}
|
|
6028
|
+
/** Transform packed NORMAL values using the corresponding source positions. */
|
|
6029
|
+
transformNormals(normals, positions) {
|
|
6030
|
+
return this.coordinateTransformer.transformNormals(normals, positions);
|
|
6031
|
+
}
|
|
6032
|
+
/** Rebuild a conservative target-frame volume from a source volume. */
|
|
6033
|
+
transformBoundingVolume(volume, sourceTransform) {
|
|
6034
|
+
const transform = sourceTransform ? new import_core11.Matrix4(Array.from(sourceTransform)) : void 0;
|
|
6035
|
+
const samples = volume.region ? getRegionSamples(volume.region) : getVolumeSamples(volume).map((sample) => transform ? Array.from(transform.transformAsPoint(sample)) : sample);
|
|
6036
|
+
if (!samples.length) {
|
|
6037
|
+
return volume;
|
|
6038
|
+
}
|
|
6039
|
+
const transformed = volume.region ? samples.map((sample) => this.transformRegionSample(sample)) : samples.map((sample) => this.coordinateTransformer.transformPosition(sample));
|
|
6040
|
+
return { box: createAxisAlignedBox(transformed) };
|
|
6041
|
+
}
|
|
6042
|
+
/** Transforms one WGS84 region sample into the selected output frame. */
|
|
6043
|
+
transformRegionSample(sample) {
|
|
6044
|
+
const [longitudeDegrees, latitudeDegrees, height] = sample;
|
|
6045
|
+
const targetCrs = this.spatialReference.targetCrs || this.spatialReference.sourceCrs;
|
|
6046
|
+
if (targetCrs && getSpatialCoordinateFrame(targetCrs) === "geocentric") {
|
|
6047
|
+
const cartesian = import_geospatial8.Ellipsoid.WGS84.cartographicToCartesian([
|
|
6048
|
+
longitudeDegrees,
|
|
6049
|
+
latitudeDegrees,
|
|
6050
|
+
height
|
|
6051
|
+
]);
|
|
6052
|
+
return Array.from(cartesian);
|
|
5146
6053
|
}
|
|
6054
|
+
return this.geographicCoordinateTransformer.transformPosition(sample);
|
|
5147
6055
|
}
|
|
5148
|
-
|
|
6056
|
+
};
|
|
6057
|
+
function getRegionSamples(region) {
|
|
6058
|
+
if (region.length < 6 || region.some((value) => !Number.isFinite(value))) {
|
|
6059
|
+
return [];
|
|
6060
|
+
}
|
|
6061
|
+
const [west, south, east, north, minimumHeight, maximumHeight] = region;
|
|
6062
|
+
const longitudeEnd = east < west ? east + Math.PI * 2 : east;
|
|
6063
|
+
const longitudes = getIntervalSamples(west, longitudeEnd);
|
|
6064
|
+
const latitudes = getIntervalSamples(south, north);
|
|
6065
|
+
const samples = [];
|
|
6066
|
+
for (const longitude of longitudes) {
|
|
6067
|
+
for (const latitude of latitudes) {
|
|
6068
|
+
for (const height of [minimumHeight, maximumHeight]) {
|
|
6069
|
+
samples.push([longitude * 180 / Math.PI, latitude * 180 / Math.PI, height]);
|
|
6070
|
+
}
|
|
6071
|
+
}
|
|
6072
|
+
}
|
|
6073
|
+
return samples;
|
|
6074
|
+
}
|
|
6075
|
+
function getIntervalSamples(start, end) {
|
|
6076
|
+
const samples = [start, (start + end) / 2, end];
|
|
6077
|
+
const angularStep = Math.PI / 2;
|
|
6078
|
+
const firstCriticalIndex = Math.ceil(start / angularStep);
|
|
6079
|
+
const lastCriticalIndex = Math.floor(end / angularStep);
|
|
6080
|
+
for (let criticalIndex = firstCriticalIndex; criticalIndex <= lastCriticalIndex; criticalIndex++) {
|
|
6081
|
+
samples.push(criticalIndex * angularStep);
|
|
6082
|
+
}
|
|
6083
|
+
return samples;
|
|
6084
|
+
}
|
|
6085
|
+
function getVolumeSamples(volume) {
|
|
6086
|
+
if (volume.box && volume.box.length >= 12) {
|
|
6087
|
+
const center = volume.box.slice(0, 3);
|
|
6088
|
+
const axes = [volume.box.slice(3, 6), volume.box.slice(6, 9), volume.box.slice(9, 12)];
|
|
6089
|
+
const samples = [];
|
|
6090
|
+
for (let firstIndex = 0; firstIndex <= 4; firstIndex++) {
|
|
6091
|
+
for (let secondIndex = 0; secondIndex <= 4; secondIndex++) {
|
|
6092
|
+
for (let thirdIndex = 0; thirdIndex <= 4; thirdIndex++) {
|
|
6093
|
+
const first = firstIndex / 2 - 1;
|
|
6094
|
+
const second = secondIndex / 2 - 1;
|
|
6095
|
+
const third = thirdIndex / 2 - 1;
|
|
6096
|
+
samples.push([
|
|
6097
|
+
center[0] + first * axes[0][0] + second * axes[1][0] + third * axes[2][0],
|
|
6098
|
+
center[1] + first * axes[0][1] + second * axes[1][1] + third * axes[2][1],
|
|
6099
|
+
center[2] + first * axes[0][2] + second * axes[1][2] + third * axes[2][2]
|
|
6100
|
+
]);
|
|
6101
|
+
}
|
|
6102
|
+
}
|
|
6103
|
+
}
|
|
6104
|
+
return samples;
|
|
6105
|
+
}
|
|
6106
|
+
if (volume.sphere && volume.sphere.length >= 4) {
|
|
6107
|
+
const [x, y, z, radius] = volume.sphere;
|
|
6108
|
+
const samples = [
|
|
6109
|
+
[x - radius, y, z],
|
|
6110
|
+
[x + radius, y, z],
|
|
6111
|
+
[x, y - radius, z],
|
|
6112
|
+
[x, y + radius, z],
|
|
6113
|
+
[x, y, z - radius],
|
|
6114
|
+
[x, y, z + radius]
|
|
6115
|
+
];
|
|
6116
|
+
for (let longitudeIndex = 0; longitudeIndex < 16; longitudeIndex++) {
|
|
6117
|
+
const longitude = longitudeIndex * Math.PI * 2 / 16;
|
|
6118
|
+
samples.push([x + radius * Math.cos(longitude), y + radius * Math.sin(longitude), z]);
|
|
6119
|
+
}
|
|
6120
|
+
return samples;
|
|
6121
|
+
}
|
|
6122
|
+
return [];
|
|
6123
|
+
}
|
|
6124
|
+
function createAxisAlignedBox(samples) {
|
|
6125
|
+
const minimum = [Infinity, Infinity, Infinity];
|
|
6126
|
+
const maximum = [-Infinity, -Infinity, -Infinity];
|
|
6127
|
+
for (const sample of samples) {
|
|
6128
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
6129
|
+
minimum[axis] = Math.min(minimum[axis], sample[axis]);
|
|
6130
|
+
maximum[axis] = Math.max(maximum[axis], sample[axis]);
|
|
6131
|
+
}
|
|
6132
|
+
}
|
|
6133
|
+
const padding = [
|
|
6134
|
+
Math.max((maximum[0] - minimum[0]) * 0.01, 1e-9),
|
|
6135
|
+
Math.max((maximum[1] - minimum[1]) * 0.01, 1e-9),
|
|
6136
|
+
Math.max((maximum[2] - minimum[2]) * 0.01, 1e-9)
|
|
6137
|
+
];
|
|
6138
|
+
const center = [
|
|
6139
|
+
(minimum[0] + maximum[0]) / 2,
|
|
6140
|
+
(minimum[1] + maximum[1]) / 2,
|
|
6141
|
+
(minimum[2] + maximum[2]) / 2
|
|
6142
|
+
];
|
|
6143
|
+
return [
|
|
6144
|
+
...center,
|
|
6145
|
+
(maximum[0] - minimum[0]) / 2 + padding[0],
|
|
6146
|
+
0,
|
|
6147
|
+
0,
|
|
6148
|
+
0,
|
|
6149
|
+
(maximum[1] - minimum[1]) / 2 + padding[1],
|
|
6150
|
+
0,
|
|
6151
|
+
0,
|
|
6152
|
+
0,
|
|
6153
|
+
(maximum[2] - minimum[2]) / 2 + padding[2]
|
|
6154
|
+
];
|
|
6155
|
+
}
|
|
6156
|
+
|
|
6157
|
+
// dist/tileset-3d/format-3d-tiles/implicit-tiling.js
|
|
6158
|
+
var import_s22 = require("@math.gl/dggs/s2");
|
|
6159
|
+
|
|
6160
|
+
// dist/tileset-3d/helpers/s2-bounding-volume.js
|
|
6161
|
+
var import_s2 = require("@math.gl/dggs/s2");
|
|
6162
|
+
var import_geospatial9 = require("@math.gl/geospatial");
|
|
6163
|
+
function convertS2BoundingVolumeToOBB(s2VolumeInfo) {
|
|
6164
|
+
const [[west, south], [east, north]] = (0, import_s2.getS2Bounds)(s2VolumeInfo.token);
|
|
6165
|
+
const orientedBoundingBox = (0, import_geospatial9.makeOBBFromRegion)([west, south, east, north, s2VolumeInfo.minimumHeight, s2VolumeInfo.maximumHeight], import_geospatial9.Ellipsoid.WGS84, { units: "degrees" });
|
|
6166
|
+
return [...orientedBoundingBox.center, ...orientedBoundingBox.halfAxes];
|
|
5149
6167
|
}
|
|
5150
6168
|
|
|
5151
6169
|
// dist/tileset-3d/format-3d-tiles/implicit-tiling.js
|
|
5152
6170
|
var QUADTREE_CHILD_COUNT = 4;
|
|
5153
6171
|
var OCTREE_CHILD_COUNT = 8;
|
|
6172
|
+
var AVAILABILITY_RANK_CACHE = /* @__PURE__ */ new WeakMap();
|
|
5154
6173
|
function createImplicitSubtreeReference(descriptor, coordinates) {
|
|
5155
6174
|
return {
|
|
5156
6175
|
coordinates,
|
|
5157
6176
|
subtreeUrl: replaceImplicitUrlTemplate(descriptor.subtreesUrlTemplate, coordinates),
|
|
5158
|
-
descriptor
|
|
6177
|
+
descriptor,
|
|
6178
|
+
resource: findImplicitPackageResource(descriptor.resourceFiles, replaceImplicitUrlTemplate(descriptor.subtreesUrlTemplate, coordinates))
|
|
5159
6179
|
};
|
|
5160
6180
|
}
|
|
5161
6181
|
function materializeImplicitSubtree(subtree, reference) {
|
|
5162
6182
|
const { descriptor } = reference;
|
|
5163
6183
|
validateImplicitDescriptor(descriptor);
|
|
6184
|
+
validateImplicitSubtree(subtree, descriptor);
|
|
5164
6185
|
const counters = { tileCount: 0, childSubtreeCount: 0 };
|
|
5165
6186
|
const root = materializeAvailableTile(subtree, reference, { localLevel: 0, mortonIndex: 0 }, reference.coordinates, counters);
|
|
5166
6187
|
if (!root) {
|
|
@@ -5168,14 +6189,79 @@ function materializeImplicitSubtree(subtree, reference) {
|
|
|
5168
6189
|
}
|
|
5169
6190
|
return { root, ...counters };
|
|
5170
6191
|
}
|
|
5171
|
-
function
|
|
6192
|
+
function validateImplicitSubtree(subtree, descriptor) {
|
|
6193
|
+
const childCount = getImplicitChildCount(descriptor.subdivisionScheme);
|
|
6194
|
+
const tileElementCount = (childCount ** descriptor.subtreeLevels - 1) / (childCount - 1);
|
|
6195
|
+
const childSubtreeElementCount = childCount ** descriptor.subtreeLevels;
|
|
6196
|
+
validateAvailabilityLength(subtree.tileAvailability, tileElementCount, "tile");
|
|
6197
|
+
const contentAvailabilityStreams = Array.isArray(subtree.contentAvailability) ? subtree.contentAvailability : subtree.contentAvailability ? [subtree.contentAvailability] : [];
|
|
6198
|
+
for (const contentAvailability of contentAvailabilityStreams) {
|
|
6199
|
+
validateAvailabilityLength(contentAvailability, tileElementCount, "content");
|
|
6200
|
+
}
|
|
6201
|
+
validateAvailabilityLength(subtree.childSubtreeAvailability, childSubtreeElementCount, "child subtree");
|
|
6202
|
+
const availableTileCount = countAvailableElements(subtree.tileAvailability, tileElementCount);
|
|
6203
|
+
const availableContentCount = contentAvailabilityStreams[0] ? countAvailableElements(contentAvailabilityStreams[0], tileElementCount) : 0;
|
|
6204
|
+
validateAttributeLengths(subtree.tileAttributes, availableTileCount, "tile");
|
|
6205
|
+
validateAttributeLengths(subtree.contentAttributes, availableContentCount, "content");
|
|
6206
|
+
if (subtree.tilePropertyRows && subtree.tilePropertyRows.length !== availableTileCount) {
|
|
6207
|
+
throw new Error("3DTILES_subtree: tile property-table count does not match availability");
|
|
6208
|
+
}
|
|
6209
|
+
if (subtree.contentPropertyRows && subtree.contentPropertyRows.length !== availableContentCount) {
|
|
6210
|
+
throw new Error("3DTILES_subtree: content property-table count does not match availability");
|
|
6211
|
+
}
|
|
6212
|
+
}
|
|
6213
|
+
function validateAvailabilityLength(availability, elementCount, label) {
|
|
6214
|
+
if (availability.constant === 0 || availability.constant === 1) {
|
|
6215
|
+
return;
|
|
6216
|
+
}
|
|
6217
|
+
if (!availability.explicitBitstream || availability.explicitBitstream.byteLength * 8 < elementCount) {
|
|
6218
|
+
throw new Error(`3DTILES_subtree: ${label} availability bitstream is too short`);
|
|
6219
|
+
}
|
|
6220
|
+
}
|
|
6221
|
+
function countAvailableElements(availability, elementCount) {
|
|
6222
|
+
if (availability.constant === 1) {
|
|
6223
|
+
return elementCount;
|
|
6224
|
+
}
|
|
6225
|
+
if (availability.constant === 0) {
|
|
6226
|
+
return 0;
|
|
6227
|
+
}
|
|
6228
|
+
let availableCount = 0;
|
|
6229
|
+
for (let index = 0; index < elementCount; index++) {
|
|
6230
|
+
if (getAvailabilityValue(availability, index)) {
|
|
6231
|
+
availableCount++;
|
|
6232
|
+
}
|
|
6233
|
+
}
|
|
6234
|
+
return availableCount;
|
|
6235
|
+
}
|
|
6236
|
+
function validateAttributeLengths(attributes, availableCount, label) {
|
|
6237
|
+
const componentCounts = {
|
|
6238
|
+
TILE_BOUNDING_BOX: 16,
|
|
6239
|
+
TILE_BOUNDING_SPHERE: 4,
|
|
6240
|
+
TILE_GEOMETRIC_ERROR: 1,
|
|
6241
|
+
TILE_REFINE: 1,
|
|
6242
|
+
TILE_TRANSFORM: 16,
|
|
6243
|
+
CONTENT_BOUNDING_BOX: 16,
|
|
6244
|
+
CONTENT_BOUNDING_SPHERE: 4
|
|
6245
|
+
};
|
|
6246
|
+
for (const [semantic, values] of Object.entries(attributes || {})) {
|
|
6247
|
+
const componentCount = componentCounts[semantic];
|
|
6248
|
+
if (componentCount && values.length !== availableCount * componentCount) {
|
|
6249
|
+
throw new Error(`3DTILES_subtree: ${label} attribute ${semantic} count does not match availability`);
|
|
6250
|
+
}
|
|
6251
|
+
}
|
|
6252
|
+
}
|
|
6253
|
+
function replaceImplicitUrlTemplate(templateUrl, coordinates, properties = {}) {
|
|
5172
6254
|
const values = {
|
|
5173
6255
|
level: coordinates.level,
|
|
5174
6256
|
x: coordinates.x,
|
|
5175
6257
|
y: coordinates.y,
|
|
5176
|
-
z: coordinates.z
|
|
6258
|
+
z: coordinates.z,
|
|
6259
|
+
...properties
|
|
5177
6260
|
};
|
|
5178
|
-
return templateUrl.replace(/{(
|
|
6261
|
+
return templateUrl.replace(/{([^{}]+)}/g, (match, propertyName) => {
|
|
6262
|
+
const value = Object.hasOwn(values, propertyName) ? values[propertyName] : values[propertyName.toLowerCase()];
|
|
6263
|
+
return value === void 0 ? match : String(value);
|
|
6264
|
+
});
|
|
5179
6265
|
}
|
|
5180
6266
|
function materializeAvailableTile(subtree, reference, localCoordinates, globalCoordinates, counters) {
|
|
5181
6267
|
const { descriptor } = reference;
|
|
@@ -5210,10 +6296,12 @@ function materializeAvailableTile(subtree, reference, localCoordinates, globalCo
|
|
|
5210
6296
|
}
|
|
5211
6297
|
}
|
|
5212
6298
|
}
|
|
5213
|
-
return formatImplicitTileHeader(subtree, descriptor, reference, globalCoordinates, contentAvailability, children);
|
|
6299
|
+
return formatImplicitTileHeader(subtree, descriptor, reference, globalCoordinates, availabilityIndex, contentAvailability, children);
|
|
5214
6300
|
}
|
|
5215
6301
|
function createLazyImplicitTileHeader(subtree, descriptor, coordinates) {
|
|
5216
|
-
const
|
|
6302
|
+
const resourceFiles = mergeImplicitPackageFiles(descriptor.resourceFiles, subtree.resourceFiles);
|
|
6303
|
+
const childDescriptor = resourceFiles ? { ...descriptor, resourceFiles } : descriptor;
|
|
6304
|
+
const reference = createImplicitSubtreeReference(childDescriptor, coordinates);
|
|
5217
6305
|
return {
|
|
5218
6306
|
id: getImplicitTileId(reference, coordinates),
|
|
5219
6307
|
children: [],
|
|
@@ -5224,55 +6312,187 @@ function createLazyImplicitTileHeader(subtree, descriptor, coordinates) {
|
|
|
5224
6312
|
lodMetricValue: descriptor.rootLodMetricValue / 2 ** coordinates.level,
|
|
5225
6313
|
refine: descriptor.refine,
|
|
5226
6314
|
type: TILE_TYPE.EMPTY,
|
|
5227
|
-
implicitMetadata: getImplicitSubtreeMetadata(subtree)
|
|
6315
|
+
implicitMetadata: getImplicitSubtreeMetadata(subtree),
|
|
6316
|
+
_scaleGeometricError: descriptor.scaleGeometricError !== false
|
|
6317
|
+
};
|
|
6318
|
+
}
|
|
6319
|
+
function getSubtreeAttributeOverrides(attributes, rowIndex, scope) {
|
|
6320
|
+
var _a, _b;
|
|
6321
|
+
if (!attributes || rowIndex < 0) {
|
|
6322
|
+
return {};
|
|
6323
|
+
}
|
|
6324
|
+
const box = getAttributeComponents(attributes[scope === "tile" ? "TILE_BOUNDING_BOX" : "CONTENT_BOUNDING_BOX"], rowIndex, 16);
|
|
6325
|
+
const sphere = getAttributeComponents(attributes[scope === "tile" ? "TILE_BOUNDING_SPHERE" : "CONTENT_BOUNDING_SPHERE"], rowIndex, 4);
|
|
6326
|
+
const boundingVolume = box ? {
|
|
6327
|
+
box: [
|
|
6328
|
+
box[12],
|
|
6329
|
+
box[13],
|
|
6330
|
+
box[14],
|
|
6331
|
+
box[0] / 2,
|
|
6332
|
+
box[1] / 2,
|
|
6333
|
+
box[2] / 2,
|
|
6334
|
+
box[4] / 2,
|
|
6335
|
+
box[5] / 2,
|
|
6336
|
+
box[6] / 2,
|
|
6337
|
+
box[8] / 2,
|
|
6338
|
+
box[9] / 2,
|
|
6339
|
+
box[10] / 2
|
|
6340
|
+
]
|
|
6341
|
+
} : sphere ? { sphere } : void 0;
|
|
6342
|
+
if (scope === "content") {
|
|
6343
|
+
return { boundingVolume };
|
|
6344
|
+
}
|
|
6345
|
+
const geometricError = (_a = getAttributeComponents(attributes.TILE_GEOMETRIC_ERROR, rowIndex, 1)) == null ? void 0 : _a[0];
|
|
6346
|
+
if (geometricError !== void 0 && (!Number.isFinite(geometricError) || geometricError < 0)) {
|
|
6347
|
+
throw new Error("3DTILES_subtree: TILE_GEOMETRIC_ERROR must be nonnegative");
|
|
6348
|
+
}
|
|
6349
|
+
const refineValue = (_b = getAttributeComponents(attributes.TILE_REFINE, rowIndex, 1)) == null ? void 0 : _b[0];
|
|
6350
|
+
if (refineValue !== void 0 && refineValue !== 0 && refineValue !== 1) {
|
|
6351
|
+
throw new Error("3DTILES_subtree: TILE_REFINE must be 0 or 1");
|
|
6352
|
+
}
|
|
6353
|
+
return {
|
|
6354
|
+
boundingVolume,
|
|
6355
|
+
geometricError,
|
|
6356
|
+
refine: refineValue === void 0 ? void 0 : refineValue === 0 ? TILE_REFINEMENT.ADD : TILE_REFINEMENT.REPLACE,
|
|
6357
|
+
transform: getAttributeComponents(attributes.TILE_TRANSFORM, rowIndex, 16)
|
|
5228
6358
|
};
|
|
5229
6359
|
}
|
|
5230
|
-
function
|
|
6360
|
+
function getAttributeComponents(values, rowIndex, componentCount) {
|
|
6361
|
+
if (!values) {
|
|
6362
|
+
return void 0;
|
|
6363
|
+
}
|
|
6364
|
+
const offset = rowIndex * componentCount;
|
|
6365
|
+
if (offset + componentCount > values.length) {
|
|
6366
|
+
throw new Error("3DTILES_subtree: attribute accessor is shorter than availability");
|
|
6367
|
+
}
|
|
6368
|
+
return Array.from({ length: componentCount }, (_unused, componentIndex) => Number(values[offset + componentIndex]));
|
|
6369
|
+
}
|
|
6370
|
+
function getAvailabilityRank(availability, index) {
|
|
6371
|
+
var _a;
|
|
6372
|
+
if (availability.constant === 1) {
|
|
6373
|
+
return index;
|
|
6374
|
+
}
|
|
6375
|
+
if (availability.constant === 0) {
|
|
6376
|
+
return 0;
|
|
6377
|
+
}
|
|
6378
|
+
let ranks = AVAILABILITY_RANK_CACHE.get(availability);
|
|
6379
|
+
if (!ranks) {
|
|
6380
|
+
const bitCount = (((_a = availability.explicitBitstream) == null ? void 0 : _a.byteLength) || 0) * 8;
|
|
6381
|
+
ranks = new Uint32Array(bitCount + 1);
|
|
6382
|
+
for (let candidateIndex = 0; candidateIndex < bitCount; candidateIndex++) {
|
|
6383
|
+
ranks[candidateIndex + 1] = ranks[candidateIndex] + Number(getAvailabilityValue(availability, candidateIndex));
|
|
6384
|
+
}
|
|
6385
|
+
AVAILABILITY_RANK_CACHE.set(availability, ranks);
|
|
6386
|
+
}
|
|
6387
|
+
return ranks[index];
|
|
6388
|
+
}
|
|
6389
|
+
function findImplicitPackageResource(files, resourceUrl) {
|
|
5231
6390
|
var _a;
|
|
5232
|
-
|
|
6391
|
+
if (!(files == null ? void 0 : files.length)) {
|
|
6392
|
+
return void 0;
|
|
6393
|
+
}
|
|
6394
|
+
const urlWithoutQuery = resourceUrl.split("?")[0];
|
|
6395
|
+
const packageRelativePath = (_a = /^gltf-package:\/\/[^/]+\/(.*)$/.exec(urlWithoutQuery)) == null ? void 0 : _a[1];
|
|
6396
|
+
const exactFileIndex = files.findIndex((file) => {
|
|
6397
|
+
const reference = file.originalUri || file.name;
|
|
6398
|
+
return file.uri === urlWithoutQuery || Boolean(reference && (urlWithoutQuery === reference || packageRelativePath === reference));
|
|
6399
|
+
});
|
|
6400
|
+
if (exactFileIndex >= 0) {
|
|
6401
|
+
return { fileIndex: exactFileIndex, files };
|
|
6402
|
+
}
|
|
6403
|
+
const fileIndex = files.findIndex((file) => {
|
|
6404
|
+
const reference = file.originalUri || file.name;
|
|
6405
|
+
return Boolean(reference && (urlWithoutQuery.endsWith(`/${reference}`) || urlWithoutQuery.endsWith(`:${reference}`)));
|
|
6406
|
+
});
|
|
6407
|
+
return fileIndex < 0 ? void 0 : { fileIndex, files };
|
|
6408
|
+
}
|
|
6409
|
+
function mergeImplicitPackageFiles(parentFiles, childFiles) {
|
|
6410
|
+
if (!(childFiles == null ? void 0 : childFiles.length)) {
|
|
6411
|
+
return parentFiles;
|
|
6412
|
+
}
|
|
6413
|
+
if (!(parentFiles == null ? void 0 : parentFiles.length)) {
|
|
6414
|
+
return childFiles;
|
|
6415
|
+
}
|
|
6416
|
+
const childReferences = new Set(childFiles.flatMap((file) => [file.uri, file.originalUri, file.name].filter(Boolean)));
|
|
6417
|
+
return [
|
|
6418
|
+
...childFiles,
|
|
6419
|
+
...parentFiles.filter((file) => ![file.uri, file.originalUri, file.name].some((reference) => reference && childReferences.has(reference)))
|
|
6420
|
+
];
|
|
6421
|
+
}
|
|
6422
|
+
function formatImplicitTileHeader(subtree, descriptor, reference, coordinates, availabilityIndex, contentAvailability, children) {
|
|
6423
|
+
var _a, _b, _c, _d, _e;
|
|
6424
|
+
const tilePropertyIndex = getAvailabilityRank(subtree.tileAvailability, availabilityIndex);
|
|
6425
|
+
const tileProperties = (_a = subtree.tilePropertyRows) == null ? void 0 : _a[tilePropertyIndex];
|
|
6426
|
+
const primaryContentAvailability = Array.isArray(subtree.contentAvailability) ? subtree.contentAvailability[0] : subtree.contentAvailability;
|
|
6427
|
+
const contentPropertyIndex = primaryContentAvailability && getAvailabilityValue(primaryContentAvailability, availabilityIndex) ? getAvailabilityRank(primaryContentAvailability, availabilityIndex) : -1;
|
|
6428
|
+
const contentProperties = (_b = subtree.contentPropertyRows) == null ? void 0 : _b[contentPropertyIndex];
|
|
6429
|
+
const tileTemplateProperties = ((_c = subtree.tileTemplatePropertyRows) == null ? void 0 : _c[tilePropertyIndex]) || tileProperties;
|
|
6430
|
+
const contentTemplateProperties = ((_d = subtree.contentTemplatePropertyRows) == null ? void 0 : _d[contentPropertyIndex]) || contentProperties;
|
|
6431
|
+
const templateProperties = { ...tileTemplateProperties, ...contentTemplateProperties };
|
|
6432
|
+
const tileAttributes = getSubtreeAttributeOverrides(subtree.tileAttributes, tilePropertyIndex, "tile");
|
|
6433
|
+
const contentAttributes = getSubtreeAttributeOverrides(subtree.contentAttributes, contentPropertyIndex, "content");
|
|
6434
|
+
const contentUrlTemplates = ((_e = descriptor.contentUrlTemplates) == null ? void 0 : _e.length) ? descriptor.contentUrlTemplates : [descriptor.contentUrlTemplate];
|
|
5233
6435
|
const contentEntries = contentUrlTemplates.map((templateUrl, contentIndex) => {
|
|
5234
6436
|
if (!contentAvailability[contentIndex] || !templateUrl) {
|
|
5235
6437
|
return null;
|
|
5236
6438
|
}
|
|
6439
|
+
const contentUrl2 = replaceImplicitUrlTemplate(templateUrl, coordinates, templateProperties);
|
|
6440
|
+
if (/{[^{}]+}/.test(contentUrl2)) {
|
|
6441
|
+
throw new Error(`Implicit content URI has unresolved template values: ${contentUrl2}`);
|
|
6442
|
+
}
|
|
5237
6443
|
return {
|
|
5238
6444
|
contentIndex,
|
|
5239
|
-
contentUrl:
|
|
6445
|
+
contentUrl: contentUrl2
|
|
5240
6446
|
};
|
|
5241
6447
|
}).filter((entry) => Boolean(entry));
|
|
5242
6448
|
const availableContentUrls = contentEntries.map((entry) => entry.contentUrl);
|
|
6449
|
+
const resourceFiles = mergeImplicitPackageFiles(descriptor.resourceFiles, subtree.resourceFiles);
|
|
5243
6450
|
const content = contentEntries.map(({ contentIndex, contentUrl: contentUrl2 }) => {
|
|
5244
6451
|
var _a2;
|
|
6452
|
+
const packageResource = findImplicitPackageResource(resourceFiles, contentUrl2);
|
|
5245
6453
|
return {
|
|
5246
6454
|
...((_a2 = descriptor.contentHeaders) == null ? void 0 : _a2[contentIndex]) || (contentIndex === 0 ? descriptor.contentHeader : {}) || {},
|
|
5247
|
-
|
|
6455
|
+
...contentAttributes,
|
|
6456
|
+
uri: contentUrl2,
|
|
6457
|
+
...contentProperties ? { metadata: { properties: contentProperties } } : {},
|
|
6458
|
+
...packageResource ? { _resource: packageResource } : {}
|
|
5248
6459
|
};
|
|
5249
6460
|
});
|
|
5250
6461
|
const contentUrl = availableContentUrls[0];
|
|
5251
|
-
const
|
|
6462
|
+
const computedLodMetricValue = descriptor.rootLodMetricValue / 2 ** coordinates.level;
|
|
6463
|
+
const lodMetricValue = tileAttributes.geometricError ?? computedLodMetricValue;
|
|
6464
|
+
const computedBoundingVolume = calculateImplicitBoundingVolume(descriptor.rootBoundingVolume, coordinates, descriptor.subdivisionScheme);
|
|
5252
6465
|
return {
|
|
5253
6466
|
id: getImplicitTileId(reference, coordinates),
|
|
5254
6467
|
children,
|
|
5255
6468
|
contentUrl,
|
|
5256
6469
|
content: content.length > 1 ? content : content[0],
|
|
6470
|
+
contents: descriptor.useCanonicalContents && content.length ? content : void 0,
|
|
5257
6471
|
contentUrls: availableContentUrls,
|
|
5258
|
-
refine: descriptor.refine,
|
|
6472
|
+
refine: tileAttributes.refine || descriptor.refine,
|
|
5259
6473
|
type: getImplicitTileType(contentUrl),
|
|
5260
6474
|
lodMetricType: descriptor.lodMetricType,
|
|
5261
6475
|
lodMetricValue,
|
|
5262
6476
|
geometricError: lodMetricValue,
|
|
5263
|
-
boundingVolume:
|
|
5264
|
-
|
|
6477
|
+
boundingVolume: tileAttributes.boundingVolume || computedBoundingVolume,
|
|
6478
|
+
transform: tileAttributes.transform,
|
|
6479
|
+
transformMatrix: tileAttributes.transform,
|
|
6480
|
+
metadata: tileProperties ? { properties: tileProperties } : void 0,
|
|
6481
|
+
implicitMetadata: getImplicitSubtreeMetadata(subtree, tileProperties, contentProperties),
|
|
6482
|
+
_scaleGeometricError: descriptor.scaleGeometricError !== false
|
|
5265
6483
|
};
|
|
5266
6484
|
}
|
|
5267
|
-
function getImplicitSubtreeMetadata(subtree) {
|
|
5268
|
-
if (!subtree.propertyTables && subtree.tileMetadata === void 0 && !subtree.contentMetadata && subtree.subtreeMetadata === void 0) {
|
|
6485
|
+
function getImplicitSubtreeMetadata(subtree, tileProperties, contentProperties) {
|
|
6486
|
+
if (!subtree.propertyTables && subtree.tileMetadata === void 0 && !subtree.contentMetadata && subtree.subtreeMetadata === void 0 && !tileProperties && !contentProperties) {
|
|
5269
6487
|
return void 0;
|
|
5270
6488
|
}
|
|
5271
6489
|
return {
|
|
5272
6490
|
propertyTables: subtree.propertyTables,
|
|
5273
6491
|
tileMetadata: subtree.tileMetadata,
|
|
5274
6492
|
contentMetadata: subtree.contentMetadata,
|
|
5275
|
-
subtreeMetadata: subtree.subtreeMetadata
|
|
6493
|
+
subtreeMetadata: subtree.subtreeMetadata,
|
|
6494
|
+
tileProperties,
|
|
6495
|
+
contentProperties
|
|
5276
6496
|
};
|
|
5277
6497
|
}
|
|
5278
6498
|
function getImplicitTileId(reference, coordinates) {
|
|
@@ -5309,12 +6529,15 @@ function getImplicitChildCount(subdivisionScheme) {
|
|
|
5309
6529
|
return subdivisionScheme === "OCTREE" ? OCTREE_CHILD_COUNT : QUADTREE_CHILD_COUNT;
|
|
5310
6530
|
}
|
|
5311
6531
|
function calculateImplicitBoundingVolume(rootBoundingVolume, coordinates, subdivisionScheme) {
|
|
6532
|
+
var _a;
|
|
5312
6533
|
if (rootBoundingVolume.region) {
|
|
5313
6534
|
const [west, south, east, north, minimumHeight, maximumHeight] = rootBoundingVolume.region;
|
|
5314
6535
|
const divisionCount = 2 ** coordinates.level;
|
|
5315
|
-
const
|
|
6536
|
+
const longitudeSpan = east >= west ? east - west : east + 2 * Math.PI - west;
|
|
6537
|
+
const longitudeSize = longitudeSpan / divisionCount;
|
|
5316
6538
|
const latitudeSize = (north - south) / divisionCount;
|
|
5317
|
-
const childWest = west + longitudeSize * coordinates.x;
|
|
6539
|
+
const childWest = normalizeRegionLongitude(west + longitudeSize * coordinates.x);
|
|
6540
|
+
const childEast = normalizeRegionLongitude(west + longitudeSize * (coordinates.x + 1));
|
|
5318
6541
|
const childSouth = south + latitudeSize * coordinates.y;
|
|
5319
6542
|
let childMinimumHeight = minimumHeight;
|
|
5320
6543
|
let childMaximumHeight = maximumHeight;
|
|
@@ -5327,7 +6550,7 @@ function calculateImplicitBoundingVolume(rootBoundingVolume, coordinates, subdiv
|
|
|
5327
6550
|
region: [
|
|
5328
6551
|
childWest,
|
|
5329
6552
|
childSouth,
|
|
5330
|
-
|
|
6553
|
+
childEast,
|
|
5331
6554
|
childSouth + latitudeSize,
|
|
5332
6555
|
childMinimumHeight,
|
|
5333
6556
|
childMaximumHeight
|
|
@@ -5336,7 +6559,13 @@ function calculateImplicitBoundingVolume(rootBoundingVolume, coordinates, subdiv
|
|
|
5336
6559
|
}
|
|
5337
6560
|
if (rootBoundingVolume.box) {
|
|
5338
6561
|
if (rootBoundingVolume.s2VolumeInfo) {
|
|
5339
|
-
return
|
|
6562
|
+
return calculateS2ImplicitBoundingVolume(rootBoundingVolume, coordinates, subdivisionScheme);
|
|
6563
|
+
}
|
|
6564
|
+
if ((_a = rootBoundingVolume.extensions) == null ? void 0 : _a["3DTILES_shape_cylinder_region"]) {
|
|
6565
|
+
return {
|
|
6566
|
+
...rootBoundingVolume,
|
|
6567
|
+
box: [...rootBoundingVolume.box]
|
|
6568
|
+
};
|
|
5340
6569
|
}
|
|
5341
6570
|
const box = rootBoundingVolume.box;
|
|
5342
6571
|
const divisionCount = 2 ** coordinates.level;
|
|
@@ -5366,6 +6595,41 @@ function calculateImplicitBoundingVolume(rootBoundingVolume, coordinates, subdiv
|
|
|
5366
6595
|
}
|
|
5367
6596
|
throw new Error(`Unsupported implicit 3D Tiles bounding volume: ${JSON.stringify(rootBoundingVolume)}`);
|
|
5368
6597
|
}
|
|
6598
|
+
function calculateS2ImplicitBoundingVolume(rootBoundingVolume, coordinates, subdivisionScheme) {
|
|
6599
|
+
const rootS2VolumeInfo = rootBoundingVolume.s2VolumeInfo;
|
|
6600
|
+
const rootIndex = (0, import_s22.getS2IndexFromToken)(rootS2VolumeInfo.token);
|
|
6601
|
+
const descendantIndex = (0, import_s22.getS2DescendantIndex)(rootIndex, coordinates.level, coordinates.x, coordinates.y);
|
|
6602
|
+
const divisionCount = 2 ** coordinates.level;
|
|
6603
|
+
const heightSize = (rootS2VolumeInfo.maximumHeight - rootS2VolumeInfo.minimumHeight) / divisionCount;
|
|
6604
|
+
const childS2VolumeInfo = {
|
|
6605
|
+
token: (0, import_s22.getS2TokenFromIndex)(descendantIndex),
|
|
6606
|
+
minimumHeight: rootS2VolumeInfo.minimumHeight + (subdivisionScheme === "OCTREE" ? heightSize * coordinates.z : 0),
|
|
6607
|
+
maximumHeight: rootS2VolumeInfo.minimumHeight + (subdivisionScheme === "OCTREE" ? heightSize * (coordinates.z + 1) : heightSize * divisionCount)
|
|
6608
|
+
};
|
|
6609
|
+
const extensions = rootBoundingVolume.extensions ? { ...rootBoundingVolume.extensions } : void 0;
|
|
6610
|
+
if (extensions == null ? void 0 : extensions["3DTILES_bounding_volume_S2"]) {
|
|
6611
|
+
extensions["3DTILES_bounding_volume_S2"] = childS2VolumeInfo;
|
|
6612
|
+
}
|
|
6613
|
+
if (extensions == null ? void 0 : extensions["3DTILES_shape_s2"]) {
|
|
6614
|
+
extensions["3DTILES_shape_s2"] = childS2VolumeInfo;
|
|
6615
|
+
}
|
|
6616
|
+
return {
|
|
6617
|
+
...rootBoundingVolume,
|
|
6618
|
+
...extensions ? { extensions } : {},
|
|
6619
|
+
s2VolumeInfo: childS2VolumeInfo,
|
|
6620
|
+
box: convertS2BoundingVolumeToOBB(childS2VolumeInfo)
|
|
6621
|
+
};
|
|
6622
|
+
}
|
|
6623
|
+
function normalizeRegionLongitude(longitude) {
|
|
6624
|
+
let normalizedLongitude = longitude;
|
|
6625
|
+
while (normalizedLongitude > Math.PI) {
|
|
6626
|
+
normalizedLongitude -= 2 * Math.PI;
|
|
6627
|
+
}
|
|
6628
|
+
while (normalizedLongitude < -Math.PI) {
|
|
6629
|
+
normalizedLongitude += 2 * Math.PI;
|
|
6630
|
+
}
|
|
6631
|
+
return normalizedLongitude;
|
|
6632
|
+
}
|
|
5369
6633
|
function getImplicitTileType(contentUrl) {
|
|
5370
6634
|
var _a;
|
|
5371
6635
|
if (!contentUrl) {
|
|
@@ -5434,6 +6698,12 @@ var Tiles3DSource = class {
|
|
|
5434
6698
|
queryParams = {};
|
|
5435
6699
|
/** Final request URLs cached by unmodified tile content URL. */
|
|
5436
6700
|
tileUrlCache = /* @__PURE__ */ new Map();
|
|
6701
|
+
/** Original content descriptors retained across {@link Tile3D.unloadContent} calls. */
|
|
6702
|
+
tileContentHeaders = /* @__PURE__ */ new WeakMap();
|
|
6703
|
+
/** Source-local namespaces assigned to distinct embedded glTF package file collections. */
|
|
6704
|
+
packageNamespaces = /* @__PURE__ */ new WeakMap();
|
|
6705
|
+
/** Next source-local package namespace. */
|
|
6706
|
+
nextPackageNamespace = 0;
|
|
5437
6707
|
/** Parsed subtree requests keyed by final source URL for deduplication and LRU reuse. */
|
|
5438
6708
|
implicitSubtreeCache;
|
|
5439
6709
|
/** Mutable counters exposed as a defensive snapshot through {@link getImplicitTilingStats}. */
|
|
@@ -5448,6 +6718,10 @@ var Tiles3DSource = class {
|
|
|
5448
6718
|
extensionsUsed = [];
|
|
5449
6719
|
resolver;
|
|
5450
6720
|
rootTileset;
|
|
6721
|
+
/** CRS transformer shared by this source's headers and decoded glTF content. */
|
|
6722
|
+
spatialTransformer;
|
|
6723
|
+
/** Root header after composing source-frame transforms and rebuilding target bounds. */
|
|
6724
|
+
preparedRootHeader;
|
|
5451
6725
|
/**
|
|
5452
6726
|
* Creates a 3D Tiles source.
|
|
5453
6727
|
* @param input Root metadata request, or preloaded root metadata for tests and internal callers.
|
|
@@ -5505,8 +6779,8 @@ var Tiles3DSource = class {
|
|
|
5505
6779
|
if (!this.asset) {
|
|
5506
6780
|
throw new Error("Tileset must have an asset property.");
|
|
5507
6781
|
}
|
|
5508
|
-
if (this.asset.version !== "0.0" && this.asset.version !== "1.0" && this.asset.version !== "1.1") {
|
|
5509
|
-
throw new Error("The tileset must be 3D Tiles version
|
|
6782
|
+
if (this.rootTileset.formatVersion !== "2.0-draft" && this.asset.version !== "0.0" && this.asset.version !== "1.0" && this.asset.version !== "1.1") {
|
|
6783
|
+
throw new Error("The tileset must be 3D Tiles version 0.0, 1.0, 1.1, or 2.0-draft.");
|
|
5510
6784
|
}
|
|
5511
6785
|
if ("tilesetVersion" in this.asset) {
|
|
5512
6786
|
this.setQueryParameter("v", this.asset.tilesetVersion);
|
|
@@ -5542,12 +6816,26 @@ var Tiles3DSource = class {
|
|
|
5542
6816
|
async getRootTileset() {
|
|
5543
6817
|
return this.getMetadata().tileset;
|
|
5544
6818
|
}
|
|
6819
|
+
/** Prepare nonlinear CRS state before runtime headers are materialized. */
|
|
6820
|
+
async prepareTileset(tileset) {
|
|
6821
|
+
const spatialReference = tileset.spatialReference;
|
|
6822
|
+
if (spatialReference.status === "unresolved") {
|
|
6823
|
+
throw new Error(spatialReference.warnings[0] || "3D Tiles spatial operations cannot be resolved from the supplied metadata and options");
|
|
6824
|
+
}
|
|
6825
|
+
if (spatialReference.status !== "transformable" && spatialReference.status !== "transformed") {
|
|
6826
|
+
return;
|
|
6827
|
+
}
|
|
6828
|
+
this.spatialTransformer ||= new Tiles3DSpatialTransformer(spatialReference, tileset.options.spatial);
|
|
6829
|
+
tileset.spatialReference = markTilesetSpatialReferenceTransformed(spatialReference);
|
|
6830
|
+
this.preparedRootHeader = this.transformTileHeader(this.getMetadata().tileset.root, new import_core12.Matrix4());
|
|
6831
|
+
}
|
|
5545
6832
|
/**
|
|
5546
6833
|
* Builds explicit runtime headers while leaving implicit subtree references lazy.
|
|
5547
6834
|
*/
|
|
5548
6835
|
initializeTileHeaders(tileset, tilesetJson, parentTile) {
|
|
5549
6836
|
var _a;
|
|
5550
|
-
const
|
|
6837
|
+
const rootHeader = parentTile ? tilesetJson.root : this.preparedRootHeader || tilesetJson.root;
|
|
6838
|
+
const rootTile = new Tile3D(tileset, rootHeader, parentTile || void 0);
|
|
5551
6839
|
if (parentTile) {
|
|
5552
6840
|
parentTile.children.push(rootTile);
|
|
5553
6841
|
rootTile.depth = parentTile.depth + 1;
|
|
@@ -5583,7 +6871,13 @@ var Tiles3DSource = class {
|
|
|
5583
6871
|
* Loads binary content or nested tileset JSON for a runtime tile.
|
|
5584
6872
|
*/
|
|
5585
6873
|
async loadTileContent(tile) {
|
|
6874
|
+
var _a, _b, _c, _d, _e, _f;
|
|
5586
6875
|
const contentUrls = (tile.contentUrls || [tile.contentUrl]).filter(Boolean);
|
|
6876
|
+
const cachedContentHeaders = this.tileContentHeaders.get(tile);
|
|
6877
|
+
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] : []);
|
|
6878
|
+
if (!cachedContentHeaders) {
|
|
6879
|
+
this.tileContentHeaders.set(tile, contentHeaders);
|
|
6880
|
+
}
|
|
5587
6881
|
const tilesetLoaderOptions = this.loadOptions[this.loader.id] || {};
|
|
5588
6882
|
const options = {
|
|
5589
6883
|
...this.loadOptions,
|
|
@@ -5592,10 +6886,28 @@ var Tiles3DSource = class {
|
|
|
5592
6886
|
// Content bytes, rather than URL suffixes, distinguish external tilesets from renderable
|
|
5593
6887
|
// payloads. This is required for signed and extensionless resources.
|
|
5594
6888
|
isTileset: "auto",
|
|
5595
|
-
assetGltfUpAxis: this.asset && this.asset.gltfUpAxis || "Y"
|
|
6889
|
+
assetGltfUpAxis: this.asset && this.asset.gltfUpAxis || "Y",
|
|
6890
|
+
_tilesetOptions: {
|
|
6891
|
+
spatialReference: ((_c = tile.header) == null ? void 0 : _c._spatialReference) || ((_d = tile.tileset) == null ? void 0 : _d.spatialReference),
|
|
6892
|
+
spatialOptions: (_e = tile.tileset) == null ? void 0 : _e.options.spatial,
|
|
6893
|
+
spatialTransform: (_f = tile.header) == null ? void 0 : _f._spatialTransform
|
|
6894
|
+
}
|
|
5596
6895
|
}
|
|
5597
6896
|
};
|
|
5598
|
-
const contents = await Promise.all(contentUrls.map((contentUrl) =>
|
|
6897
|
+
const contents = await Promise.all(contentUrls.map((contentUrl, contentIndex) => {
|
|
6898
|
+
var _a2;
|
|
6899
|
+
const contentHeader = contentHeaders[contentIndex] || {};
|
|
6900
|
+
const vectorExtension = (_a2 = contentHeader.extensions) == null ? void 0 : _a2["3DTILES_content_gltf_vector"];
|
|
6901
|
+
const vectorContent = contentHeader._vectorContent || ((vectorExtension == null ? void 0 : vectorExtension.vector) === true ? { clip: vectorExtension.clip === true } : void 0);
|
|
6902
|
+
const contentOptions = vectorContent ? {
|
|
6903
|
+
...options,
|
|
6904
|
+
[this.loader.id]: {
|
|
6905
|
+
...options[this.loader.id],
|
|
6906
|
+
vectorContent
|
|
6907
|
+
}
|
|
6908
|
+
} : options;
|
|
6909
|
+
return this.loadContentResource(this.getTileUrl(contentUrl), contentHeader._resource, contentOptions);
|
|
6910
|
+
}));
|
|
5599
6911
|
tile.contents = contents;
|
|
5600
6912
|
tile.content = contents[0] || null;
|
|
5601
6913
|
const nestedTilesets = contents.filter((content) => (content == null ? void 0 : content.shape) === "tileset3d");
|
|
@@ -5606,6 +6918,34 @@ var Tiles3DSource = class {
|
|
|
5606
6918
|
nestedTilesets
|
|
5607
6919
|
};
|
|
5608
6920
|
}
|
|
6921
|
+
/** Transform a tile header and its eagerly declared descendants. */
|
|
6922
|
+
transformTileHeader(header, parentTransform = new import_core12.Matrix4()) {
|
|
6923
|
+
if (!this.spatialTransformer) {
|
|
6924
|
+
return header;
|
|
6925
|
+
}
|
|
6926
|
+
return this.transformTileHeaderWithTransformer(header, this.spatialTransformer, parentTransform);
|
|
6927
|
+
}
|
|
6928
|
+
/** Rebuilds one header subtree using an explicitly selected CRS transformer. */
|
|
6929
|
+
transformTileHeaderWithTransformer(header, transformer, parentTransform, spatialReference) {
|
|
6930
|
+
const localTransform = header.transform ? new import_core12.Matrix4(header.transform) : new import_core12.Matrix4();
|
|
6931
|
+
const composedTransform = new import_core12.Matrix4(parentTransform).multiplyRight(localTransform);
|
|
6932
|
+
const content = Array.isArray(header.content) ? header.content.map((entry) => this.transformContentHeader(entry, composedTransform, transformer)) : header.content ? this.transformContentHeader(header.content, composedTransform, transformer) : header.content;
|
|
6933
|
+
return {
|
|
6934
|
+
...header,
|
|
6935
|
+
transform: void 0,
|
|
6936
|
+
boundingVolume: header.boundingVolume ? transformer.transformBoundingVolume(header.boundingVolume, composedTransform) : header.boundingVolume,
|
|
6937
|
+
_spatialReference: spatialReference,
|
|
6938
|
+
_spatialTransform: composedTransform.toArray(),
|
|
6939
|
+
content,
|
|
6940
|
+
children: Array.isArray(header.children) ? header.children.map((child) => this.transformTileHeaderWithTransformer(child, transformer, composedTransform, spatialReference)) : header.children
|
|
6941
|
+
};
|
|
6942
|
+
}
|
|
6943
|
+
transformContentHeader(content, composedTransform, transformer) {
|
|
6944
|
+
return {
|
|
6945
|
+
...content,
|
|
6946
|
+
boundingVolume: content.boundingVolume ? transformer.transformBoundingVolume(content.boundingVolume, composedTransform) : content.boundingVolume
|
|
6947
|
+
};
|
|
6948
|
+
}
|
|
5609
6949
|
/**
|
|
5610
6950
|
* Loads, materializes, and installs exactly one implicit subtree.
|
|
5611
6951
|
*
|
|
@@ -5624,7 +6964,7 @@ var Tiles3DSource = class {
|
|
|
5624
6964
|
return { loaded: false, tileCount: 0, childSubtreeCount: 0 };
|
|
5625
6965
|
}
|
|
5626
6966
|
const subtreeUrl = this.getTileUrl(reference.subtreeUrl);
|
|
5627
|
-
const subtree = await this.loadImplicitSubtreeResource(subtreeUrl);
|
|
6967
|
+
const subtree = await this.loadImplicitSubtreeResource(subtreeUrl, reference.resource);
|
|
5628
6968
|
if (this.destroyed || tile.isDestroyed()) {
|
|
5629
6969
|
return { loaded: false, tileCount: 0, childSubtreeCount: 0 };
|
|
5630
6970
|
}
|
|
@@ -5632,8 +6972,11 @@ var Tiles3DSource = class {
|
|
|
5632
6972
|
...reference,
|
|
5633
6973
|
subtreeUrl
|
|
5634
6974
|
});
|
|
5635
|
-
tile.
|
|
5636
|
-
const
|
|
6975
|
+
const nestedSpatialReference = tile.header._spatialReference;
|
|
6976
|
+
const subtreeTransformer = nestedSpatialReference ? new Tiles3DSpatialTransformer(nestedSpatialReference, tile.tileset.options.spatial) : this.spatialTransformer;
|
|
6977
|
+
const materializedRoot = subtreeTransformer ? this.transformTileHeaderWithTransformer(materializedSubtree.root, subtreeTransformer, new import_core12.Matrix4(), nestedSpatialReference) : materializedSubtree.root;
|
|
6978
|
+
tile.applyImplicitSubtreeHeader(materializedRoot);
|
|
6979
|
+
const materializedTileCount = this.initializeMaterializedChildren(tile.tileset, tile, materializedRoot.children);
|
|
5637
6980
|
this.implicitTilingStats.loadedSubtrees++;
|
|
5638
6981
|
this.implicitTilingStats.materializedTiles += materializedTileCount;
|
|
5639
6982
|
return {
|
|
@@ -5720,10 +7063,10 @@ var Tiles3DSource = class {
|
|
|
5720
7063
|
const { center } = rootTile.boundingVolume;
|
|
5721
7064
|
let cartographicCenter;
|
|
5722
7065
|
if (center && (center[0] !== 0 || center[1] !== 0 || center[2] !== 0)) {
|
|
5723
|
-
cartographicCenter = new
|
|
5724
|
-
|
|
7066
|
+
cartographicCenter = new import_core12.Vector3();
|
|
7067
|
+
import_geospatial10.Ellipsoid.WGS84.cartesianToCartographic(center, cartographicCenter);
|
|
5725
7068
|
} else {
|
|
5726
|
-
cartographicCenter = new
|
|
7069
|
+
cartographicCenter = new import_core12.Vector3(0, 0, -import_geospatial10.Ellipsoid.WGS84.radii[0]);
|
|
5727
7070
|
}
|
|
5728
7071
|
return {
|
|
5729
7072
|
asset: this.asset,
|
|
@@ -5762,9 +7105,59 @@ var Tiles3DSource = class {
|
|
|
5762
7105
|
}
|
|
5763
7106
|
const nestedTilesets = loadResult.nestedTilesets || (loadResult.nestedTileset ? [loadResult.nestedTileset] : []);
|
|
5764
7107
|
for (const nestedTileset of nestedTilesets) {
|
|
5765
|
-
tileset._initializeTileHeaders(nestedTileset, tile);
|
|
7108
|
+
tileset._initializeTileHeaders(this.prepareNestedTileset(tileset, nestedTileset), tile);
|
|
5766
7109
|
}
|
|
5767
7110
|
}
|
|
7111
|
+
/**
|
|
7112
|
+
* Resolves a nested tileset's CRS independently and adapts it to the owning tileset output frame.
|
|
7113
|
+
*
|
|
7114
|
+
* Nested resources may use a different source CRS from their parent. Their headers and glTF
|
|
7115
|
+
* payloads must therefore use a transformer built from the nested descriptor, while the parent
|
|
7116
|
+
* runtime continues to expose one requested output frame to traversal and rendering.
|
|
7117
|
+
*/
|
|
7118
|
+
prepareNestedTileset(tileset, nestedTileset) {
|
|
7119
|
+
const nestedSpatialReference = nestedTileset.spatialMetadata;
|
|
7120
|
+
const parentSpatialReference = tileset.spatialReference;
|
|
7121
|
+
if ((nestedSpatialReference == null ? void 0 : nestedSpatialReference.status) === "unresolved" || (nestedSpatialReference == null ? void 0 : nestedSpatialReference.crs.state) === "unknown") {
|
|
7122
|
+
throw new Error(nestedSpatialReference.warnings[0] || "Nested 3D Tiles CRS is explicitly unresolved and cannot be placed in the parent frame");
|
|
7123
|
+
}
|
|
7124
|
+
if (!nestedSpatialReference || !nestedSpatialReference.sourceCrs) {
|
|
7125
|
+
if (this.spatialTransformer && (parentSpatialReference.status === "transformable" || parentSpatialReference.status === "transformed")) {
|
|
7126
|
+
return {
|
|
7127
|
+
...nestedTileset,
|
|
7128
|
+
spatialMetadata: parentSpatialReference,
|
|
7129
|
+
root: this.transformTileHeaderWithTransformer(nestedTileset.root, this.spatialTransformer, new import_core12.Matrix4(), parentSpatialReference)
|
|
7130
|
+
};
|
|
7131
|
+
}
|
|
7132
|
+
return addNestedSpatialReference(nestedTileset, parentSpatialReference);
|
|
7133
|
+
}
|
|
7134
|
+
const parentCoordinateEpoch = parentSpatialReference.coordinateEpoch;
|
|
7135
|
+
const nestedCoordinateEpoch = nestedSpatialReference.coordinateEpoch;
|
|
7136
|
+
if (parentCoordinateEpoch !== void 0 && nestedCoordinateEpoch !== void 0 && parentCoordinateEpoch !== nestedCoordinateEpoch) {
|
|
7137
|
+
throw new Error(`Nested 3D Tiles coordinate epoch ${nestedCoordinateEpoch} differs from parent epoch ${parentCoordinateEpoch}; epoch-aware transformation is unavailable`);
|
|
7138
|
+
}
|
|
7139
|
+
const outputCrs = parentSpatialReference.targetCrs || parentSpatialReference.sourceCrs;
|
|
7140
|
+
if (!outputCrs) {
|
|
7141
|
+
return addNestedSpatialReference(nestedTileset, nestedSpatialReference);
|
|
7142
|
+
}
|
|
7143
|
+
const nestedOutputReference = applyTilesetSpatialOptions(nestedSpatialReference, {
|
|
7144
|
+
...tileset.options.spatial,
|
|
7145
|
+
outputCoordinates: "target-crs",
|
|
7146
|
+
targetCrs: outputCrs
|
|
7147
|
+
});
|
|
7148
|
+
if (nestedOutputReference.status === "unresolved") {
|
|
7149
|
+
throw new Error(nestedOutputReference.warnings[0] || "Nested 3D Tiles CRS cannot be resolved in the parent output frame");
|
|
7150
|
+
}
|
|
7151
|
+
if (nestedOutputReference.status === "native") {
|
|
7152
|
+
return addNestedSpatialReference(nestedTileset, nestedOutputReference);
|
|
7153
|
+
}
|
|
7154
|
+
const nestedTransformer = new Tiles3DSpatialTransformer(nestedOutputReference, tileset.options.spatial);
|
|
7155
|
+
return {
|
|
7156
|
+
...nestedTileset,
|
|
7157
|
+
spatialMetadata: nestedOutputReference,
|
|
7158
|
+
root: this.transformTileHeaderWithTransformer(nestedTileset.root, nestedTransformer, new import_core12.Matrix4(), nestedOutputReference)
|
|
7159
|
+
};
|
|
7160
|
+
}
|
|
5768
7161
|
/**
|
|
5769
7162
|
* Loads data through injected core APIs so this module stays independent from `@loaders.gl/core`.
|
|
5770
7163
|
*/
|
|
@@ -5792,13 +7185,84 @@ var Tiles3DSource = class {
|
|
|
5792
7185
|
}
|
|
5793
7186
|
return await this.loadWithCoreApi(url, options, loader);
|
|
5794
7187
|
}
|
|
7188
|
+
/** Loads a URL content reference or parses a buffer-view file retained from a glTF package. */
|
|
7189
|
+
async loadContentResource(url, packageResource, options) {
|
|
7190
|
+
if (!packageResource) {
|
|
7191
|
+
return await this.loadResourceData(url, options);
|
|
7192
|
+
}
|
|
7193
|
+
const file = packageResource.files[packageResource.fileIndex];
|
|
7194
|
+
if (!file) {
|
|
7195
|
+
throw new Error(`3D Tiles package references missing file ${packageResource.fileIndex}`);
|
|
7196
|
+
}
|
|
7197
|
+
if (file.uri) {
|
|
7198
|
+
return await this.loadResourceData(this.getTileUrl(file.uri), options);
|
|
7199
|
+
}
|
|
7200
|
+
if (!this.coreApi) {
|
|
7201
|
+
throw new Error("Tiles3DSource requires an injected coreApi to parse embedded package data");
|
|
7202
|
+
}
|
|
7203
|
+
const data = await this.getPackageFileData(file);
|
|
7204
|
+
const packageNamespace = this.getPackageNamespace(packageResource.files);
|
|
7205
|
+
const packageRootUrl = `gltf-package://${packageNamespace}/${packageResource.fileIndex}`;
|
|
7206
|
+
const fileName = file.name || "content";
|
|
7207
|
+
const directorySeparatorIndex = fileName.lastIndexOf("/");
|
|
7208
|
+
const packageBaseUrl = directorySeparatorIndex >= 0 ? `${packageRootUrl}/${fileName.slice(0, directorySeparatorIndex)}` : packageRootUrl;
|
|
7209
|
+
return await this.coreApi.parse(data, this.loader, options, {
|
|
7210
|
+
url: `${packageRootUrl}/${fileName}`,
|
|
7211
|
+
filename: fileName,
|
|
7212
|
+
baseUrl: packageBaseUrl,
|
|
7213
|
+
loaders: [this.loader],
|
|
7214
|
+
coreApi: this.coreApi,
|
|
7215
|
+
_parse: this.coreApi.parse,
|
|
7216
|
+
_tiles3dPackageFiles: packageResource.files,
|
|
7217
|
+
fetch: async (resource, init) => {
|
|
7218
|
+
const reference = resource.startsWith(`${packageRootUrl}/`) ? resource.slice(packageRootUrl.length + 1) : resource;
|
|
7219
|
+
const referencedFile = packageResource.files.find((packageFile) => packageFile.name === reference || packageFile.originalUri === reference);
|
|
7220
|
+
if (!referencedFile) {
|
|
7221
|
+
throw new Error(`3D Tiles glTF package does not contain file ${reference}`);
|
|
7222
|
+
}
|
|
7223
|
+
if (referencedFile.uri) {
|
|
7224
|
+
return await this.coreApi.fetchFile(this.getTileUrl(referencedFile.uri), init);
|
|
7225
|
+
}
|
|
7226
|
+
const referencedData = await this.getPackageFileData(referencedFile);
|
|
7227
|
+
return new Response(referencedData, {
|
|
7228
|
+
headers: { "content-type": referencedFile.mimeType }
|
|
7229
|
+
});
|
|
7230
|
+
}
|
|
7231
|
+
});
|
|
7232
|
+
}
|
|
7233
|
+
/** Returns a stable source-local namespace for one embedded glTF package file collection. */
|
|
7234
|
+
getPackageNamespace(files) {
|
|
7235
|
+
const existingNamespace = this.packageNamespaces.get(files);
|
|
7236
|
+
if (existingNamespace !== void 0) {
|
|
7237
|
+
return existingNamespace;
|
|
7238
|
+
}
|
|
7239
|
+
const packageNamespace = this.nextPackageNamespace++;
|
|
7240
|
+
this.packageNamespaces.set(files, packageNamespace);
|
|
7241
|
+
return packageNamespace;
|
|
7242
|
+
}
|
|
7243
|
+
/** Resolves a retained package-file byte range without eagerly copying other package files. */
|
|
7244
|
+
async getPackageFileData(file) {
|
|
7245
|
+
if (file.data) {
|
|
7246
|
+
return sliceArrayBuffer(file.data, file.byteOffset, file.byteLength);
|
|
7247
|
+
}
|
|
7248
|
+
if (file.bufferUri && this.coreApi) {
|
|
7249
|
+
const response = await this.coreApi.fetchFile(this.getTileUrl(file.bufferUri));
|
|
7250
|
+
if (!response.ok) {
|
|
7251
|
+
throw new Error(`Failed to fetch 3D Tiles package buffer: HTTP ${response.status}`);
|
|
7252
|
+
}
|
|
7253
|
+
const buffer = await response.arrayBuffer();
|
|
7254
|
+
return sliceArrayBuffer(buffer, file.byteOffset, file.byteLength);
|
|
7255
|
+
}
|
|
7256
|
+
throw new Error("3D Tiles package file has no available byte source");
|
|
7257
|
+
}
|
|
5795
7258
|
/**
|
|
5796
7259
|
* Returns a parsed subtree from the LRU cache or starts one source-managed request.
|
|
5797
7260
|
*
|
|
5798
7261
|
* @param subtreeUrl - Final subtree URL after query inheritance.
|
|
7262
|
+
* @param packageResource - Optional glTF package file satisfying the subtree reference.
|
|
5799
7263
|
* @returns Parsed subtree availability data.
|
|
5800
7264
|
*/
|
|
5801
|
-
async loadImplicitSubtreeResource(subtreeUrl) {
|
|
7265
|
+
async loadImplicitSubtreeResource(subtreeUrl, packageResource) {
|
|
5802
7266
|
const cachedSubtree = this.implicitSubtreeCache.get(subtreeUrl);
|
|
5803
7267
|
if (cachedSubtree) {
|
|
5804
7268
|
this.implicitTilingStats.cacheHits++;
|
|
@@ -5807,14 +7271,15 @@ var Tiles3DSource = class {
|
|
|
5807
7271
|
this.implicitTilingStats.requestedSubtrees++;
|
|
5808
7272
|
const loaderOptions = this.loadOptions[this.loader.id] || {};
|
|
5809
7273
|
return await this.implicitSubtreeCache.getOrLoad(subtreeUrl, async () => {
|
|
5810
|
-
|
|
7274
|
+
const options = {
|
|
5811
7275
|
...this.loadOptions,
|
|
5812
7276
|
[this.loader.id]: {
|
|
5813
7277
|
...loaderOptions,
|
|
5814
7278
|
isTileset: false,
|
|
5815
7279
|
isSubtree: true
|
|
5816
7280
|
}
|
|
5817
|
-
}
|
|
7281
|
+
};
|
|
7282
|
+
return await (packageResource ? this.loadContentResource(subtreeUrl, packageResource, options) : this.loadResourceData(subtreeUrl, options));
|
|
5818
7283
|
});
|
|
5819
7284
|
}
|
|
5820
7285
|
/**
|
|
@@ -5865,10 +7330,22 @@ function normalizeTiles3DRequest(input) {
|
|
|
5865
7330
|
coreApi: input.coreApi
|
|
5866
7331
|
};
|
|
5867
7332
|
}
|
|
7333
|
+
function addNestedSpatialReference(nestedTileset, spatialReference) {
|
|
7334
|
+
const addToHeader = (header) => ({
|
|
7335
|
+
...header,
|
|
7336
|
+
_spatialReference: spatialReference,
|
|
7337
|
+
children: Array.isArray(header.children) ? header.children.map(addToHeader) : header.children
|
|
7338
|
+
});
|
|
7339
|
+
return {
|
|
7340
|
+
...nestedTileset,
|
|
7341
|
+
spatialMetadata: spatialReference,
|
|
7342
|
+
root: addToHeader(nestedTileset.root)
|
|
7343
|
+
};
|
|
7344
|
+
}
|
|
5868
7345
|
|
|
5869
7346
|
// dist/tileset-3d/format-i3s/i3s-source.js
|
|
5870
|
-
var
|
|
5871
|
-
var
|
|
7347
|
+
var import_geospatial12 = require("@math.gl/geospatial");
|
|
7348
|
+
var import_core14 = require("@math.gl/core");
|
|
5872
7349
|
|
|
5873
7350
|
// dist/tileset-3d/format-i3s/i3s-pending-tiles-register.js
|
|
5874
7351
|
var I3SPendingTilesRegister = class {
|
|
@@ -6049,224 +7526,8 @@ var I3STilesetTraverser = class extends TilesetTraverser {
|
|
|
6049
7526
|
};
|
|
6050
7527
|
|
|
6051
7528
|
// dist/spatial/i3s-spatial-transformer.js
|
|
6052
|
-
var
|
|
6053
|
-
var
|
|
6054
|
-
|
|
6055
|
-
// dist/spatial/spatial-coordinate-transformer.js
|
|
6056
|
-
var import_core11 = require("@math.gl/core");
|
|
6057
|
-
var import_geospatial8 = require("@math.gl/geospatial");
|
|
6058
|
-
var import_proj42 = require("@math.gl/proj4");
|
|
6059
|
-
|
|
6060
|
-
// dist/spatial/spatial-resource-registry.js
|
|
6061
|
-
var import_geoid = require("@math.gl/geoid");
|
|
6062
|
-
var import_proj4 = require("@math.gl/proj4");
|
|
6063
|
-
var geoidModels = /* @__PURE__ */ new Map();
|
|
6064
|
-
function registerSpatialCrs(name, definition) {
|
|
6065
|
-
validateResourceName(name, "CRS");
|
|
6066
|
-
import_proj4.Proj4Projection.defineProjectionAliases({ [name]: definition });
|
|
6067
|
-
}
|
|
6068
|
-
function registerSpatialDatumGrid(name, data) {
|
|
6069
|
-
validateResourceName(name, "datum grid");
|
|
6070
|
-
import_proj4.Proj4Projection.registerDatumGrid(name, data);
|
|
6071
|
-
}
|
|
6072
|
-
function registerGeoidModel(name, geoid) {
|
|
6073
|
-
validateResourceName(name, "geoid model");
|
|
6074
|
-
geoidModels.set(name, geoid);
|
|
6075
|
-
}
|
|
6076
|
-
function registerGeoidModelFromPgm(name, data, options = {}) {
|
|
6077
|
-
const geoid = (0, import_geoid.parsePGM)(data, options);
|
|
6078
|
-
registerGeoidModel(name, geoid);
|
|
6079
|
-
return geoid;
|
|
6080
|
-
}
|
|
6081
|
-
function getGeoidModel(name) {
|
|
6082
|
-
return geoidModels.get(name);
|
|
6083
|
-
}
|
|
6084
|
-
function validateResourceName(name, resourceType) {
|
|
6085
|
-
if (!name.trim()) {
|
|
6086
|
-
throw new Error(`${resourceType} name must not be empty`);
|
|
6087
|
-
}
|
|
6088
|
-
}
|
|
6089
|
-
|
|
6090
|
-
// dist/spatial/spatial-coordinate-transformer.js
|
|
6091
|
-
var GEOGRAPHIC_CRS2 = "EPSG:4326";
|
|
6092
|
-
var GEOCENTRIC_CRS2 = "EPSG:4978";
|
|
6093
|
-
var SpatialCoordinateTransformer = class {
|
|
6094
|
-
/** Normalized spatial metadata describing this transformation. */
|
|
6095
|
-
spatialReference;
|
|
6096
|
-
/** Projection from the source CRS directly to the requested horizontal target CRS. */
|
|
6097
|
-
horizontalProjection;
|
|
6098
|
-
/** Projection from the source CRS to geographic longitude, latitude, and ellipsoidal height. */
|
|
6099
|
-
geographicProjection;
|
|
6100
|
-
/** Projection from adjusted geographic coordinates to the requested output CRS. */
|
|
6101
|
-
heightOutputProjection;
|
|
6102
|
-
/** Whether source coordinates use the WGS84 geocentric frame handled by math.gl. */
|
|
6103
|
-
sourceIsGeocentric;
|
|
6104
|
-
/** Whether output coordinates use the WGS84 geocentric frame handled by math.gl. */
|
|
6105
|
-
outputIsGeocentric;
|
|
6106
|
-
/** Whether source coordinates already use conventional WGS84 longitude/latitude order. */
|
|
6107
|
-
sourceIsGeographic;
|
|
6108
|
-
/** Whether output coordinates use conventional WGS84 longitude/latitude order. */
|
|
6109
|
-
outputIsGeographic;
|
|
6110
|
-
/** Geoid model used to convert between ellipsoidal and orthometric heights. */
|
|
6111
|
-
geoid;
|
|
6112
|
-
/**
|
|
6113
|
-
* Creates a coordinate transformer.
|
|
6114
|
-
*
|
|
6115
|
-
* @param spatialReference - Format-discovered and option-normalized spatial metadata.
|
|
6116
|
-
* @param options - Application options containing an optional geoid model.
|
|
6117
|
-
*/
|
|
6118
|
-
constructor(spatialReference, options = {}) {
|
|
6119
|
-
this.spatialReference = spatialReference;
|
|
6120
|
-
validateTransformRequest(spatialReference);
|
|
6121
|
-
const outputCrs = spatialReference.targetCrs || spatialReference.sourceCrs;
|
|
6122
|
-
this.sourceIsGeocentric = isWgs84Geocentric(spatialReference.sourceCrs);
|
|
6123
|
-
this.outputIsGeocentric = isWgs84Geocentric(outputCrs);
|
|
6124
|
-
this.sourceIsGeographic = isWgs84Geographic(spatialReference.sourceCrs);
|
|
6125
|
-
this.outputIsGeographic = isWgs84Geographic(outputCrs);
|
|
6126
|
-
if (spatialReference.sourceCrs && spatialReference.targetCrs && !this.sourceIsGeocentric && !this.outputIsGeocentric) {
|
|
6127
|
-
this.horizontalProjection = new import_proj42.Proj4Projection({
|
|
6128
|
-
from: getHorizontalProj4Definition(spatialReference.sourceCrs),
|
|
6129
|
-
to: getHorizontalProj4Definition(spatialReference.targetCrs),
|
|
6130
|
-
enforceAxis: false
|
|
6131
|
-
});
|
|
6132
|
-
}
|
|
6133
|
-
if (requiresHeightTransformation(spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
|
|
6134
|
-
if (!this.sourceIsGeographic && !this.sourceIsGeocentric) {
|
|
6135
|
-
this.geographicProjection = new import_proj42.Proj4Projection({
|
|
6136
|
-
from: getHorizontalProj4Definition(spatialReference.sourceCrs),
|
|
6137
|
-
to: GEOGRAPHIC_CRS2,
|
|
6138
|
-
enforceAxis: false
|
|
6139
|
-
});
|
|
6140
|
-
}
|
|
6141
|
-
if (!this.outputIsGeographic && !this.outputIsGeocentric) {
|
|
6142
|
-
this.heightOutputProjection = new import_proj42.Proj4Projection({
|
|
6143
|
-
from: GEOGRAPHIC_CRS2,
|
|
6144
|
-
to: getHorizontalProj4Definition(outputCrs),
|
|
6145
|
-
enforceAxis: false
|
|
6146
|
-
});
|
|
6147
|
-
}
|
|
6148
|
-
}
|
|
6149
|
-
if (requiresHeightTransformation(spatialReference)) {
|
|
6150
|
-
this.geoid = resolveGeoid(options.geoidModel);
|
|
6151
|
-
if (!this.geoid) {
|
|
6152
|
-
const modelName = typeof options.geoidModel === "string" ? ` "${options.geoidModel}"` : "";
|
|
6153
|
-
throw new Error(`Height conversion requires a registered geoid model${modelName}; call registerGeoidModel() or pass a parsed Geoid instance`);
|
|
6154
|
-
}
|
|
6155
|
-
}
|
|
6156
|
-
}
|
|
6157
|
-
/**
|
|
6158
|
-
* Transforms one `[x, y, z?]` coordinate while retaining additional components.
|
|
6159
|
-
*
|
|
6160
|
-
* @param coordinate - Source coordinate in the format adapter's normalized `x/y/z` order.
|
|
6161
|
-
* @returns A new transformed coordinate array.
|
|
6162
|
-
*/
|
|
6163
|
-
transformPosition(coordinate) {
|
|
6164
|
-
if (coordinate.length < 2) {
|
|
6165
|
-
throw new Error("A spatial coordinate must contain at least x and y components");
|
|
6166
|
-
}
|
|
6167
|
-
const result = [...coordinate];
|
|
6168
|
-
if (requiresHeightTransformation(this.spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
|
|
6169
|
-
if (result.length < 3 || !Number.isFinite(result[2])) {
|
|
6170
|
-
throw new Error("Three-dimensional CRS conversion requires a finite z coordinate");
|
|
6171
|
-
}
|
|
6172
|
-
const geographic = this.toGeographic(result);
|
|
6173
|
-
if (requiresHeightTransformation(this.spatialReference)) {
|
|
6174
|
-
const geoidUndulation = this.geoid.getHeight(geographic[1], geographic[0]);
|
|
6175
|
-
geographic[2] = transformHeight(geographic[2], geoidUndulation, this.spatialReference.heightReference, this.spatialReference.targetHeightReference);
|
|
6176
|
-
}
|
|
6177
|
-
const projected = this.fromGeographic(geographic);
|
|
6178
|
-
result.splice(0, projected.length, ...projected);
|
|
6179
|
-
return result;
|
|
6180
|
-
}
|
|
6181
|
-
if (this.horizontalProjection) {
|
|
6182
|
-
const projected = this.horizontalProjection.project(result.slice(0, 3));
|
|
6183
|
-
result.splice(0, projected.length, ...projected);
|
|
6184
|
-
}
|
|
6185
|
-
return result;
|
|
6186
|
-
}
|
|
6187
|
-
/** Convert one source coordinate to conventional WGS84 longitude, latitude, and height. */
|
|
6188
|
-
toGeographic(coordinate) {
|
|
6189
|
-
if (this.sourceIsGeocentric) {
|
|
6190
|
-
return Array.from(import_geospatial8.Ellipsoid.WGS84.cartesianToCartographic(new import_core11.Vector3(coordinate)));
|
|
6191
|
-
}
|
|
6192
|
-
if (this.sourceIsGeographic) {
|
|
6193
|
-
return coordinate.slice(0, 3);
|
|
6194
|
-
}
|
|
6195
|
-
return this.geographicProjection.project(coordinate.slice(0, 3));
|
|
6196
|
-
}
|
|
6197
|
-
/** Convert one conventional WGS84 geographic coordinate to the selected output CRS. */
|
|
6198
|
-
fromGeographic(coordinate) {
|
|
6199
|
-
if (this.outputIsGeocentric) {
|
|
6200
|
-
return Array.from(import_geospatial8.Ellipsoid.WGS84.cartographicToCartesian(new import_core11.Vector3(coordinate)));
|
|
6201
|
-
}
|
|
6202
|
-
if (this.outputIsGeographic) {
|
|
6203
|
-
return coordinate.slice(0, 3);
|
|
6204
|
-
}
|
|
6205
|
-
return this.heightOutputProjection.project(coordinate.slice(0, 3));
|
|
6206
|
-
}
|
|
6207
|
-
};
|
|
6208
|
-
function getHorizontalProj4Definition(definition) {
|
|
6209
|
-
if (!definition) {
|
|
6210
|
-
throw new Error("Cannot construct a projection because the CRS is unknown");
|
|
6211
|
-
}
|
|
6212
|
-
return (0, import_proj42.toProj4CRSDefinition)(definition, { mode: "horizontal" });
|
|
6213
|
-
}
|
|
6214
|
-
function validateTransformRequest(spatialReference) {
|
|
6215
|
-
if (spatialReference.outputCoordinates === "local-enu") {
|
|
6216
|
-
throw new Error("local-enu output requires a dataset-derived local origin and must be created by a tileset source");
|
|
6217
|
-
}
|
|
6218
|
-
if (spatialReference.outputCoordinates === "target-crs" && !spatialReference.targetCrs) {
|
|
6219
|
-
throw new Error("target-crs output requires targetCrs");
|
|
6220
|
-
}
|
|
6221
|
-
if (!spatialReference.sourceCrs && spatialReference.status === "unresolved") {
|
|
6222
|
-
throw new Error("Cannot transform coordinates because the source CRS is unknown");
|
|
6223
|
-
}
|
|
6224
|
-
if (requiresHeightTransformation(spatialReference) && spatialReference.heightReference === "unknown") {
|
|
6225
|
-
throw new Error("Cannot convert heights because the source height reference is unknown");
|
|
6226
|
-
}
|
|
6227
|
-
if (spatialReference.coordinateFrame === "geocentric" && !isWgs84Geocentric(spatialReference.sourceCrs)) {
|
|
6228
|
-
throw new Error("Only EPSG:4978 geocentric coordinates are supported by the current spatial transformer");
|
|
6229
|
-
}
|
|
6230
|
-
if (spatialReference.status === "unresolved") {
|
|
6231
|
-
throw new Error("The requested spatial output cannot be resolved from the available metadata");
|
|
6232
|
-
}
|
|
6233
|
-
}
|
|
6234
|
-
function isWgs84Geocentric(definition) {
|
|
6235
|
-
return typeof definition === "string" && normalizeCrsIdentifier2(definition) === GEOCENTRIC_CRS2;
|
|
6236
|
-
}
|
|
6237
|
-
function isWgs84Geographic(definition) {
|
|
6238
|
-
if (typeof definition !== "string") {
|
|
6239
|
-
return false;
|
|
6240
|
-
}
|
|
6241
|
-
const identifier = normalizeCrsIdentifier2(definition);
|
|
6242
|
-
return identifier === GEOGRAPHIC_CRS2 || identifier === "EPSG:4979" || identifier === "OGC:CRS84";
|
|
6243
|
-
}
|
|
6244
|
-
function normalizeCrsIdentifier2(identifier) {
|
|
6245
|
-
const normalizedIdentifier = identifier.trim().toUpperCase();
|
|
6246
|
-
const ogcMatch = normalizedIdentifier.match(/(?:\/DEF\/CRS\/|URN:OGC:DEF:CRS:)([A-Z0-9_-]+)(?:\/|::)(?:[^/:]*[/:])?([A-Z0-9_.-]+)$/);
|
|
6247
|
-
return ogcMatch ? `${ogcMatch[1]}:${ogcMatch[2]}` : normalizedIdentifier;
|
|
6248
|
-
}
|
|
6249
|
-
function requiresHeightTransformation(spatialReference) {
|
|
6250
|
-
const target = spatialReference.targetHeightReference;
|
|
6251
|
-
return target !== "native" && target !== spatialReference.heightReference;
|
|
6252
|
-
}
|
|
6253
|
-
function resolveGeoid(model) {
|
|
6254
|
-
return typeof model === "string" ? getGeoidModel(model) : model;
|
|
6255
|
-
}
|
|
6256
|
-
function transformHeight(height, geoidUndulation, source, target) {
|
|
6257
|
-
if (source === target || target === "native") {
|
|
6258
|
-
return height;
|
|
6259
|
-
}
|
|
6260
|
-
if (source === "orthometric" && target === "ellipsoidal") {
|
|
6261
|
-
return height + geoidUndulation;
|
|
6262
|
-
}
|
|
6263
|
-
if (source === "ellipsoidal" && target === "orthometric") {
|
|
6264
|
-
return height - geoidUndulation;
|
|
6265
|
-
}
|
|
6266
|
-
throw new Error(`Unsupported height conversion from ${source} to ${target}`);
|
|
6267
|
-
}
|
|
6268
|
-
|
|
6269
|
-
// dist/spatial/i3s-spatial-transformer.js
|
|
7529
|
+
var import_core13 = require("@math.gl/core");
|
|
7530
|
+
var import_geospatial11 = require("@math.gl/geospatial");
|
|
6270
7531
|
var I3SSpatialTransformer = class {
|
|
6271
7532
|
/** Descriptor attached to output after all adapter-owned spatial values have been transformed. */
|
|
6272
7533
|
spatialReference;
|
|
@@ -6461,7 +7722,7 @@ var I3SSpatialTransformer = class {
|
|
|
6461
7722
|
positions[index + 2] = transformed[2] - origin[2];
|
|
6462
7723
|
}
|
|
6463
7724
|
const isGeographic = this.targetCoordinateFrame === "geographic";
|
|
6464
|
-
const modelMatrix = isGeographic ? new
|
|
7725
|
+
const modelMatrix = isGeographic ? new import_core13.Matrix4() : new import_core13.Matrix4().translate(origin);
|
|
6465
7726
|
return {
|
|
6466
7727
|
positions,
|
|
6467
7728
|
sourcePositions: absoluteSourcePositions,
|
|
@@ -6489,7 +7750,7 @@ var I3SSpatialTransformer = class {
|
|
|
6489
7750
|
sourcePositions[index + 1],
|
|
6490
7751
|
sourcePositions[index + 2]
|
|
6491
7752
|
]);
|
|
6492
|
-
const inputNormal = new
|
|
7753
|
+
const inputNormal = new import_core13.Vector3([
|
|
6493
7754
|
normals[index],
|
|
6494
7755
|
normals[index + 1],
|
|
6495
7756
|
normals[index + 2]
|
|
@@ -6527,12 +7788,12 @@ var I3SSpatialTransformer = class {
|
|
|
6527
7788
|
}
|
|
6528
7789
|
/** Rebuild an I3S bound as a WGS84 ECEF box for generic `Tileset3D` traversal. */
|
|
6529
7790
|
transformBoundingVolumeToGeocentric(bounds) {
|
|
6530
|
-
const cartesianSamples = this.getGeographicBoundSamples(bounds).map((position) => Array.from(
|
|
7791
|
+
const cartesianSamples = this.getGeographicBoundSamples(bounds).map((position) => Array.from(import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position))));
|
|
6531
7792
|
return { box: getAxisAlignedBox(cartesianSamples) };
|
|
6532
7793
|
}
|
|
6533
7794
|
/** Rebuild an I3S bound as WGS84 ECEF after asynchronous elevation placement. */
|
|
6534
7795
|
async transformBoundingVolumeToGeocentricAsync(bounds) {
|
|
6535
|
-
const cartesianSamples = (await this.getGeographicBoundSamplesAsync(bounds)).map((position) => Array.from(
|
|
7796
|
+
const cartesianSamples = (await this.getGeographicBoundSamplesAsync(bounds)).map((position) => Array.from(import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position))));
|
|
6536
7797
|
return { box: getAxisAlignedBox(cartesianSamples) };
|
|
6537
7798
|
}
|
|
6538
7799
|
/** Return a WGS84 geographic MBS used by the I3S screen-threshold calculation. */
|
|
@@ -6559,7 +7820,7 @@ var I3SSpatialTransformer = class {
|
|
|
6559
7820
|
*/
|
|
6560
7821
|
async transformBoundsAsync(bounds) {
|
|
6561
7822
|
const geographicSamples = await this.getGeographicBoundSamplesAsync(bounds);
|
|
6562
|
-
const cartesianSamples = geographicSamples.map((position) => Array.from(
|
|
7823
|
+
const cartesianSamples = geographicSamples.map((position) => Array.from(import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position))));
|
|
6563
7824
|
const targetSamples = geographicSamples.map((position) => this.geographicToTargetTransformer.transformPosition(position));
|
|
6564
7825
|
return {
|
|
6565
7826
|
boundingVolume: { box: getAxisAlignedBox(cartesianSamples) },
|
|
@@ -6682,21 +7943,21 @@ var I3SSpatialTransformer = class {
|
|
|
6682
7943
|
if (this.targetCoordinateFrame === "geographic") {
|
|
6683
7944
|
return ecefVectorToLocalEnu(ecefNormal, geographic).normalize();
|
|
6684
7945
|
}
|
|
6685
|
-
const cartesian =
|
|
7946
|
+
const cartesian = import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(geographic));
|
|
6686
7947
|
const jacobianColumns = [];
|
|
6687
7948
|
for (const direction of getPositiveAxisDirections()) {
|
|
6688
|
-
const positiveGeographic =
|
|
6689
|
-
const negativeGeographic =
|
|
7949
|
+
const positiveGeographic = import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(new import_core13.Vector3(cartesian).add(direction));
|
|
7950
|
+
const negativeGeographic = import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(new import_core13.Vector3(cartesian).subtract(direction));
|
|
6690
7951
|
const positiveTarget = this.geographicToTargetTransformer.transformPosition(positiveGeographic);
|
|
6691
7952
|
const negativeTarget = this.geographicToTargetTransformer.transformPosition(negativeGeographic);
|
|
6692
7953
|
jacobianColumns.push((positiveTarget[0] - negativeTarget[0]) / 2, (positiveTarget[1] - negativeTarget[1]) / 2, (positiveTarget[2] - negativeTarget[2]) / 2);
|
|
6693
7954
|
}
|
|
6694
|
-
const normalMatrix = new
|
|
7955
|
+
const normalMatrix = new import_core13.Matrix3(jacobianColumns);
|
|
6695
7956
|
if (Math.abs(normalMatrix.determinant()) < 1e-12) {
|
|
6696
7957
|
throw new Error("Cannot transform an I3S normal through a singular local projection");
|
|
6697
7958
|
}
|
|
6698
7959
|
normalMatrix.invert().transpose();
|
|
6699
|
-
return new
|
|
7960
|
+
return new import_core13.Vector3(ecefNormal).transformByMatrix3(normalMatrix).normalize();
|
|
6700
7961
|
}
|
|
6701
7962
|
};
|
|
6702
7963
|
function getElevationProvider(mode, options) {
|
|
@@ -6728,17 +7989,17 @@ function getGeographicBoundingSphere(geographicSamples) {
|
|
|
6728
7989
|
if (!geographicSamples.length) {
|
|
6729
7990
|
throw new Error("I3S spatial transformation requires at least one bound sample");
|
|
6730
7991
|
}
|
|
6731
|
-
const cartesianSamples = geographicSamples.map((position) =>
|
|
6732
|
-
const cartesianCenter = new
|
|
7992
|
+
const cartesianSamples = geographicSamples.map((position) => import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(position)));
|
|
7993
|
+
const cartesianCenter = new import_core13.Vector3();
|
|
6733
7994
|
for (const sample of cartesianSamples) {
|
|
6734
7995
|
cartesianCenter.add(sample);
|
|
6735
7996
|
}
|
|
6736
7997
|
cartesianCenter.scale(1 / cartesianSamples.length);
|
|
6737
7998
|
let radius = 0;
|
|
6738
7999
|
for (const sample of cartesianSamples) {
|
|
6739
|
-
radius = Math.max(radius, new
|
|
8000
|
+
radius = Math.max(radius, new import_core13.Vector3(sample).subtract(cartesianCenter).magnitude());
|
|
6740
8001
|
}
|
|
6741
|
-
const geographicCenter =
|
|
8002
|
+
const geographicCenter = import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(cartesianCenter);
|
|
6742
8003
|
return [geographicCenter[0], geographicCenter[1], geographicCenter[2], radius];
|
|
6743
8004
|
}
|
|
6744
8005
|
function getSourceBoundSamples(bounds, sourceFrame, sourceToGeographicTransformer, sourceVerticalUnitScale) {
|
|
@@ -6747,28 +8008,28 @@ function getSourceBoundSamples(bounds, sourceFrame, sourceToGeographicTransforme
|
|
|
6747
8008
|
const center2 = Array.from(obb.center).slice(0, 3);
|
|
6748
8009
|
center2[2] *= sourceVerticalUnitScale;
|
|
6749
8010
|
const halfSize = Array.from(obb.halfSize).slice(0, 3);
|
|
6750
|
-
const quaternion = new
|
|
8011
|
+
const quaternion = new import_core13.Quaternion().fromArray(Array.from(obb.quaternion));
|
|
6751
8012
|
const axes = [
|
|
6752
|
-
new
|
|
6753
|
-
new
|
|
6754
|
-
new
|
|
8013
|
+
new import_core13.Vector3([halfSize[0], 0, 0]).transformByQuaternion(quaternion),
|
|
8014
|
+
new import_core13.Vector3([0, halfSize[1], 0]).transformByQuaternion(quaternion),
|
|
8015
|
+
new import_core13.Vector3([0, 0, halfSize[2]]).transformByQuaternion(quaternion)
|
|
6755
8016
|
];
|
|
6756
8017
|
if (sourceFrame === "geographic") {
|
|
6757
8018
|
const geographicCenter = sourceToGeographicTransformer.transformPosition(center2);
|
|
6758
|
-
const cartesianCenter =
|
|
8019
|
+
const cartesianCenter = import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(geographicCenter));
|
|
6759
8020
|
const cartesianAxes = bounds.normalReferenceFrame === "vertex-reference-frame" ? axes.map((axis) => localEnuVectorToEcef(axis, geographicCenter)) : axes;
|
|
6760
8021
|
return getBoxSigns().map((signs) => {
|
|
6761
|
-
const corner = new
|
|
8022
|
+
const corner = new import_core13.Vector3(cartesianCenter);
|
|
6762
8023
|
for (let axisIndex = 0; axisIndex < 3; axisIndex++) {
|
|
6763
|
-
corner.add(new
|
|
8024
|
+
corner.add(new import_core13.Vector3(cartesianAxes[axisIndex]).scale(signs[axisIndex]));
|
|
6764
8025
|
}
|
|
6765
|
-
return Array.from(
|
|
8026
|
+
return Array.from(import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(corner));
|
|
6766
8027
|
});
|
|
6767
8028
|
}
|
|
6768
8029
|
return getBoxSigns().map((signs) => {
|
|
6769
|
-
const corner = new
|
|
8030
|
+
const corner = new import_core13.Vector3(center2);
|
|
6770
8031
|
for (let axisIndex = 0; axisIndex < 3; axisIndex++) {
|
|
6771
|
-
corner.add(new
|
|
8032
|
+
corner.add(new import_core13.Vector3(axes[axisIndex]).scale(signs[axisIndex]));
|
|
6772
8033
|
}
|
|
6773
8034
|
return Array.from(corner);
|
|
6774
8035
|
});
|
|
@@ -6782,10 +8043,10 @@ function getSourceBoundSamples(bounds, sourceFrame, sourceToGeographicTransforme
|
|
|
6782
8043
|
const radius = mbs[3];
|
|
6783
8044
|
if (sourceFrame === "geographic") {
|
|
6784
8045
|
const geographicCenter = sourceToGeographicTransformer.transformPosition(center);
|
|
6785
|
-
const cartesianCenter =
|
|
6786
|
-
return getAxisDirections().map((direction) => Array.from(
|
|
8046
|
+
const cartesianCenter = import_geospatial11.Ellipsoid.WGS84.cartographicToCartesian(new import_core13.Vector3(geographicCenter));
|
|
8047
|
+
return getAxisDirections().map((direction) => Array.from(import_geospatial11.Ellipsoid.WGS84.cartesianToCartographic(new import_core13.Vector3(cartesianCenter).add(new import_core13.Vector3(direction).scale(radius)))));
|
|
6787
8048
|
}
|
|
6788
|
-
return getAxisDirections().map((direction) => Array.from(new
|
|
8049
|
+
return getAxisDirections().map((direction) => Array.from(new import_core13.Vector3(center).add(new import_core13.Vector3(direction).scale(radius))));
|
|
6789
8050
|
}
|
|
6790
8051
|
function getBoxSigns() {
|
|
6791
8052
|
return [-1, 1].flatMap((x) => [-1, 1].flatMap((y) => [-1, 1].map((z) => [x, y, z])));
|
|
@@ -6801,18 +8062,18 @@ function getAxisDirections() {
|
|
|
6801
8062
|
];
|
|
6802
8063
|
}
|
|
6803
8064
|
function getPositiveAxisDirections() {
|
|
6804
|
-
return [new
|
|
8065
|
+
return [new import_core13.Vector3([1, 0, 0]), new import_core13.Vector3([0, 1, 0]), new import_core13.Vector3([0, 0, 1])];
|
|
6805
8066
|
}
|
|
6806
8067
|
function localEnuVectorToEcef(vector, geographic) {
|
|
6807
8068
|
const longitude = geographic[0] * Math.PI / 180;
|
|
6808
8069
|
const latitude = geographic[1] * Math.PI / 180;
|
|
6809
|
-
const east = new
|
|
6810
|
-
const north = new
|
|
8070
|
+
const east = new import_core13.Vector3([-Math.sin(longitude), Math.cos(longitude), 0]);
|
|
8071
|
+
const north = new import_core13.Vector3([
|
|
6811
8072
|
-Math.sin(latitude) * Math.cos(longitude),
|
|
6812
8073
|
-Math.sin(latitude) * Math.sin(longitude),
|
|
6813
8074
|
Math.cos(latitude)
|
|
6814
8075
|
]);
|
|
6815
|
-
const up = new
|
|
8076
|
+
const up = new import_core13.Vector3([
|
|
6816
8077
|
Math.cos(latitude) * Math.cos(longitude),
|
|
6817
8078
|
Math.cos(latitude) * Math.sin(longitude),
|
|
6818
8079
|
Math.sin(latitude)
|
|
@@ -6822,18 +8083,18 @@ function localEnuVectorToEcef(vector, geographic) {
|
|
|
6822
8083
|
function ecefVectorToLocalEnu(vector, geographic) {
|
|
6823
8084
|
const longitude = geographic[0] * Math.PI / 180;
|
|
6824
8085
|
const latitude = geographic[1] * Math.PI / 180;
|
|
6825
|
-
const east = new
|
|
6826
|
-
const north = new
|
|
8086
|
+
const east = new import_core13.Vector3([-Math.sin(longitude), Math.cos(longitude), 0]);
|
|
8087
|
+
const north = new import_core13.Vector3([
|
|
6827
8088
|
-Math.sin(latitude) * Math.cos(longitude),
|
|
6828
8089
|
-Math.sin(latitude) * Math.sin(longitude),
|
|
6829
8090
|
Math.cos(latitude)
|
|
6830
8091
|
]);
|
|
6831
|
-
const up = new
|
|
8092
|
+
const up = new import_core13.Vector3([
|
|
6832
8093
|
Math.cos(latitude) * Math.cos(longitude),
|
|
6833
8094
|
Math.cos(latitude) * Math.sin(longitude),
|
|
6834
8095
|
Math.sin(latitude)
|
|
6835
8096
|
]);
|
|
6836
|
-
return new
|
|
8097
|
+
return new import_core13.Vector3([east.dot(vector), north.dot(vector), up.dot(vector)]);
|
|
6837
8098
|
}
|
|
6838
8099
|
function getAxisAlignedBox(positions) {
|
|
6839
8100
|
const minimum = [Infinity, Infinity, Infinity];
|
|
@@ -6888,8 +8149,10 @@ var EMPTY_CONTENT_FORMATS2 = {
|
|
|
6888
8149
|
var I3SSource = class {
|
|
6889
8150
|
/** I3S format discriminator. */
|
|
6890
8151
|
type = TILESET_TYPE.I3S;
|
|
6891
|
-
/**
|
|
8152
|
+
/** Primary I3S loader used for root and child metadata requests. */
|
|
6892
8153
|
loader;
|
|
8154
|
+
/** Worker-capable loader used for binary tile content when supplied by the format loader. */
|
|
8155
|
+
contentLoader;
|
|
6893
8156
|
/** Root I3S layer URL. */
|
|
6894
8157
|
url;
|
|
6895
8158
|
/** Base path used for relative tile resource resolution. */
|
|
@@ -6924,6 +8187,7 @@ var I3SSource = class {
|
|
|
6924
8187
|
this.rootTileset = isTilesetRequest2(input) ? null : input;
|
|
6925
8188
|
this.tileset = this.rootTileset;
|
|
6926
8189
|
this.loader = request.loader;
|
|
8190
|
+
this.contentLoader = getI3SContentLoader(request.loader);
|
|
6927
8191
|
this.url = request.url;
|
|
6928
8192
|
this.basePath = request.basePath || path_exports.dirname(request.url);
|
|
6929
8193
|
this.resolver = request.resolver;
|
|
@@ -7040,7 +8304,7 @@ var I3SSource = class {
|
|
|
7040
8304
|
isTileHeader: false
|
|
7041
8305
|
}
|
|
7042
8306
|
};
|
|
7043
|
-
tile.content = await this.loadResourceData(contentUrl, options);
|
|
8307
|
+
tile.content = await this.loadResourceData(contentUrl, options, this.contentLoader);
|
|
7044
8308
|
return { loaded: true };
|
|
7045
8309
|
}
|
|
7046
8310
|
/**
|
|
@@ -7095,8 +8359,8 @@ var I3SSource = class {
|
|
|
7095
8359
|
getViewState(rootTile) {
|
|
7096
8360
|
var _a;
|
|
7097
8361
|
if (this.spatialTransformer && rootTile) {
|
|
7098
|
-
const center = new
|
|
7099
|
-
const cartographicCenter = new
|
|
8362
|
+
const center = new import_core14.Vector3(rootTile.boundingVolume.center);
|
|
8363
|
+
const cartographicCenter = new import_core14.Vector3(rootTile.header.i3sLodMbs.slice(0, 3));
|
|
7100
8364
|
if (this.spatialTransformer.targetCoordinateFrame === "geographic") {
|
|
7101
8365
|
return {
|
|
7102
8366
|
boundingVolume: rootTile.boundingVolume,
|
|
@@ -7116,9 +8380,9 @@ var I3SSource = class {
|
|
|
7116
8380
|
const fullExtent = metadata.tileset.fullExtent;
|
|
7117
8381
|
if (fullExtent) {
|
|
7118
8382
|
const { xmin, xmax, ymin, ymax, zmin, zmax } = fullExtent;
|
|
7119
|
-
const cartographicCenter = new
|
|
7120
|
-
const cartesianCenter = new
|
|
7121
|
-
|
|
8383
|
+
const cartographicCenter = new import_core14.Vector3(xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2, zmin + (zmax - zmin) / 2);
|
|
8384
|
+
const cartesianCenter = new import_core14.Vector3();
|
|
8385
|
+
import_geospatial12.Ellipsoid.WGS84.cartographicToCartesian(cartographicCenter, cartesianCenter);
|
|
7122
8386
|
return {
|
|
7123
8387
|
cartographicCenter,
|
|
7124
8388
|
cartesianCenter,
|
|
@@ -7128,9 +8392,9 @@ var I3SSource = class {
|
|
|
7128
8392
|
const extent = (_a = metadata.tileset.store) == null ? void 0 : _a.extent;
|
|
7129
8393
|
if (extent) {
|
|
7130
8394
|
const [xmin, ymin, xmax, ymax] = extent;
|
|
7131
|
-
const cartographicCenter = new
|
|
7132
|
-
const cartesianCenter = new
|
|
7133
|
-
|
|
8395
|
+
const cartographicCenter = new import_core14.Vector3(xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2, 0);
|
|
8396
|
+
const cartesianCenter = new import_core14.Vector3();
|
|
8397
|
+
import_geospatial12.Ellipsoid.WGS84.cartographicToCartesian(cartographicCenter, cartesianCenter);
|
|
7134
8398
|
return {
|
|
7135
8399
|
cartographicCenter,
|
|
7136
8400
|
cartesianCenter,
|
|
@@ -7139,7 +8403,7 @@ var I3SSource = class {
|
|
|
7139
8403
|
}
|
|
7140
8404
|
console.warn("Extent is not defined in the tileset header");
|
|
7141
8405
|
return {
|
|
7142
|
-
cartographicCenter: new
|
|
8406
|
+
cartographicCenter: new import_core14.Vector3(),
|
|
7143
8407
|
zoom: 1
|
|
7144
8408
|
};
|
|
7145
8409
|
}
|
|
@@ -7171,11 +8435,11 @@ var I3SSource = class {
|
|
|
7171
8435
|
/**
|
|
7172
8436
|
* Loads data through injected core APIs so this module stays independent from `@loaders.gl/core`.
|
|
7173
8437
|
*/
|
|
7174
|
-
async loadWithCoreApi(url, options) {
|
|
8438
|
+
async loadWithCoreApi(url, options, loader = this.loader) {
|
|
7175
8439
|
if (!this.coreApi) {
|
|
7176
8440
|
throw new Error("I3SSource requires an injected coreApi to load tileset data");
|
|
7177
8441
|
}
|
|
7178
|
-
return await this.coreApi.load(url,
|
|
8442
|
+
return await this.coreApi.load(url, loader, options);
|
|
7179
8443
|
}
|
|
7180
8444
|
/**
|
|
7181
8445
|
* Loads data through an injected resolver when present, otherwise through the injected core API.
|
|
@@ -7202,11 +8466,11 @@ var I3SSource = class {
|
|
|
7202
8466
|
/**
|
|
7203
8467
|
* Loads tile metadata or content through an injected resolver when present, otherwise through the injected core API.
|
|
7204
8468
|
*/
|
|
7205
|
-
async loadResourceData(url, options) {
|
|
8469
|
+
async loadResourceData(url, options, loader = this.loader) {
|
|
7206
8470
|
if (this.resolver) {
|
|
7207
|
-
return await this.resolver.loadResource(url,
|
|
8471
|
+
return await this.resolver.loadResource(url, loader, options);
|
|
7208
8472
|
}
|
|
7209
|
-
return await this.loadWithCoreApi(url, options);
|
|
8473
|
+
return await this.loadWithCoreApi(url, options, loader);
|
|
7210
8474
|
}
|
|
7211
8475
|
/** Transform one I3S header bound after target options and elevation providers are available. */
|
|
7212
8476
|
async transformTileHeader(header) {
|
|
@@ -7230,6 +8494,9 @@ var I3SSource = class {
|
|
|
7230
8494
|
};
|
|
7231
8495
|
}
|
|
7232
8496
|
};
|
|
8497
|
+
function getI3SContentLoader(loader) {
|
|
8498
|
+
return loader.contentLoader || loader;
|
|
8499
|
+
}
|
|
7233
8500
|
function isTilesetRequest2(input) {
|
|
7234
8501
|
return Boolean(input && typeof input === "object" && "url" in input && "loader" in input && !("type" in input));
|
|
7235
8502
|
}
|
|
@@ -8456,7 +9723,7 @@ function isAbortError3(error) {
|
|
|
8456
9723
|
}
|
|
8457
9724
|
|
|
8458
9725
|
// dist/point-cloud/point-cloud-tileset.js
|
|
8459
|
-
var
|
|
9726
|
+
var import_core15 = require("@math.gl/core");
|
|
8460
9727
|
var import_culling6 = require("@math.gl/culling");
|
|
8461
9728
|
|
|
8462
9729
|
// dist/point-cloud/point-cloud-tile.js
|
|
@@ -8620,7 +9887,7 @@ var PointCloudTileset = class {
|
|
|
8620
9887
|
const viewState = await ((_b = (_a = this.dataSource).getViewState) == null ? void 0 : _b.call(_a));
|
|
8621
9888
|
this.boundingVolume = (viewState == null ? void 0 : viewState.boundingVolume) || this.root.boundingVolume;
|
|
8622
9889
|
const center = (viewState == null ? void 0 : viewState.cartographicCenter) || this.root.boundingVolume.center;
|
|
8623
|
-
this.cartographicCenter = new
|
|
9890
|
+
this.cartographicCenter = new import_core15.Vector3(center);
|
|
8624
9891
|
this.zoom = (viewState == null ? void 0 : viewState.zoom) || this.estimateZoom(this.boundingVolume);
|
|
8625
9892
|
}
|
|
8626
9893
|
/**
|