@honua/app-platform 0.1.12 → 0.1.13
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/columnar/apache-arrow.d.ts +17 -0
- package/columnar/apache-arrow.d.ts.map +1 -0
- package/columnar/apache-arrow.js +1036 -0
- package/columnar/batch-cache-conformance.d.ts +66 -0
- package/columnar/batch-cache-conformance.d.ts.map +1 -0
- package/columnar/batch-cache-conformance.js +317 -0
- package/columnar/batch-cache-indexeddb.d.ts +31 -0
- package/columnar/batch-cache-indexeddb.d.ts.map +1 -0
- package/columnar/batch-cache-indexeddb.js +148 -0
- package/columnar/batch-cache.d.ts +298 -0
- package/columnar/batch-cache.d.ts.map +1 -0
- package/columnar/batch-cache.js +757 -0
- package/columnar/geoarrow-aggregate.d.ts +178 -0
- package/columnar/geoarrow-aggregate.d.ts.map +1 -0
- package/columnar/geoarrow-aggregate.js +976 -0
- package/columnar/geoarrow-patch.d.ts +382 -0
- package/columnar/geoarrow-patch.d.ts.map +1 -0
- package/columnar/geoarrow-patch.js +1656 -0
- package/columnar/geoarrow-reproject.d.ts +22 -0
- package/columnar/geoarrow-reproject.d.ts.map +1 -0
- package/columnar/geoarrow-reproject.js +119 -0
- package/columnar/geoarrow-serialization.d.ts +68 -0
- package/columnar/geoarrow-serialization.d.ts.map +1 -0
- package/columnar/geoarrow-serialization.js +331 -0
- package/columnar/geoarrow-types.d.ts +271 -0
- package/columnar/geoarrow-types.d.ts.map +1 -0
- package/columnar/geoarrow-types.js +15 -0
- package/columnar/geoarrow.d.ts +52 -0
- package/columnar/geoarrow.d.ts.map +1 -0
- package/columnar/geoarrow.js +1469 -0
- package/columnar/index.d.ts +43 -0
- package/columnar/index.d.ts.map +1 -0
- package/columnar/index.js +29 -0
- package/columnar/operators.d.ts +70 -0
- package/columnar/operators.d.ts.map +1 -0
- package/columnar/operators.js +307 -0
- package/columnar/result.d.ts +369 -0
- package/columnar/result.d.ts.map +1 -0
- package/columnar/result.js +815 -0
- package/columnar/telemetry.d.ts +152 -0
- package/columnar/telemetry.d.ts.map +1 -0
- package/columnar/telemetry.js +265 -0
- package/columnar/transfer.d.ts +28 -0
- package/columnar/transfer.d.ts.map +1 -0
- package/columnar/transfer.js +669 -0
- package/columnar/types.d.ts +175 -0
- package/columnar/types.d.ts.map +1 -0
- package/columnar/types.js +22 -0
- package/columnar/worker.d.ts +157 -0
- package/columnar/worker.d.ts.map +1 -0
- package/columnar/worker.js +1059 -0
- package/contract/pmtiles.d.ts +6 -5
- package/contract/pmtiles.d.ts.map +1 -1
- package/contract/pmtiles.js +30 -5
- package/controls/catalog.d.ts.map +1 -1
- package/controls/catalog.js +110 -0
- package/controls/index.d.ts +1 -1
- package/controls/index.js +1 -1
- package/controls/types.d.ts +1 -1
- package/controls/types.js +1 -1
- package/core/client.d.ts.map +1 -1
- package/core/client.js +87 -19
- package/core/deprecation-notice.d.ts +28 -0
- package/core/deprecation-notice.d.ts.map +1 -0
- package/core/deprecation-notice.js +22 -0
- package/core/esri-geojson.d.ts.map +1 -1
- package/core/esri-geojson.js +10 -6
- package/core/optional-grpc-peer.d.ts +15 -0
- package/core/optional-grpc-peer.d.ts.map +1 -0
- package/core/optional-grpc-peer.js +60 -0
- package/esri-compat/basemap-gallery.d.ts +2 -0
- package/esri-compat/basemap-gallery.d.ts.map +1 -1
- package/esri-compat/basemap-gallery.js +12 -0
- package/esri-compat/basemap.d.ts +4 -0
- package/esri-compat/basemap.d.ts.map +1 -1
- package/esri-compat/basemap.js +70 -0
- package/esri-compat/bookmarks.d.ts +2 -0
- package/esri-compat/bookmarks.d.ts.map +1 -1
- package/esri-compat/bookmarks.js +12 -0
- package/esri-compat/controls.d.ts +18 -0
- package/esri-compat/controls.d.ts.map +1 -1
- package/esri-compat/controls.js +120 -57
- package/esri-compat/directions.d.ts +4 -0
- package/esri-compat/directions.d.ts.map +1 -1
- package/esri-compat/directions.js +30 -20
- package/esri-compat/editor.d.ts +4 -0
- package/esri-compat/editor.d.ts.map +1 -1
- package/esri-compat/editor.js +16 -0
- package/esri-compat/esri-config.d.ts +2 -1
- package/esri-compat/esri-config.d.ts.map +1 -1
- package/esri-compat/feature-effect.d.ts +23 -0
- package/esri-compat/feature-effect.d.ts.map +1 -0
- package/esri-compat/feature-effect.js +12 -0
- package/esri-compat/feature-form.d.ts +6 -0
- package/esri-compat/feature-form.d.ts.map +1 -1
- package/esri-compat/feature-form.js +63 -0
- package/esri-compat/feature-layer.d.ts +21 -2
- package/esri-compat/feature-layer.d.ts.map +1 -1
- package/esri-compat/feature-layer.js +172 -1
- package/esri-compat/feature-table.d.ts +5 -0
- package/esri-compat/feature-table.d.ts.map +1 -1
- package/esri-compat/feature-table.js +23 -0
- package/esri-compat/identity-manager.d.ts +1 -1
- package/esri-compat/identity-manager.js +1 -1
- package/esri-compat/legend.d.ts +2 -0
- package/esri-compat/legend.d.ts.map +1 -1
- package/esri-compat/legend.js +98 -0
- package/esri-compat/locator.d.ts +1 -1
- package/esri-compat/locator.js +1 -1
- package/esri-compat/map-view-mount.d.ts +1 -0
- package/esri-compat/map-view-mount.d.ts.map +1 -1
- package/esri-compat/map-view-mount.js +46 -25
- package/esri-compat/map-view.d.ts +13 -0
- package/esri-compat/map-view.d.ts.map +1 -1
- package/esri-compat/map-view.js +94 -8
- package/esri-compat/map.d.ts +5 -1
- package/esri-compat/map.d.ts.map +1 -1
- package/esri-compat/map.js +10 -0
- package/esri-compat/measurement.d.ts +2 -0
- package/esri-compat/measurement.d.ts.map +1 -1
- package/esri-compat/measurement.js +14 -0
- package/esri-compat/point.d.ts +7 -0
- package/esri-compat/point.d.ts.map +1 -1
- package/esri-compat/point.js +33 -3
- package/esri-compat/popup.d.ts +2 -0
- package/esri-compat/popup.d.ts.map +1 -1
- package/esri-compat/popup.js +12 -0
- package/esri-compat/portal.d.ts +1 -1
- package/esri-compat/portal.js +1 -1
- package/esri-compat/print.d.ts +3 -0
- package/esri-compat/print.d.ts.map +1 -1
- package/esri-compat/print.js +15 -0
- package/esri-compat/search.d.ts +4 -0
- package/esri-compat/search.d.ts.map +1 -1
- package/esri-compat/search.js +25 -28
- package/esri-compat/sketch.d.ts +2 -0
- package/esri-compat/sketch.d.ts.map +1 -1
- package/esri-compat/sketch.js +12 -0
- package/esri-compat/widget-host.d.ts +46 -17
- package/esri-compat/widget-host.d.ts.map +1 -1
- package/esri-compat/widget-host.js +84 -20
- package/esri-compat/widget-shell-hosts.d.ts +61 -0
- package/esri-compat/widget-shell-hosts.d.ts.map +1 -0
- package/esri-compat/widget-shell-hosts.js +76 -0
- package/kernel/renderer.d.ts +82 -0
- package/kernel/renderer.js +1 -0
- package/offline/conflict-resolution.d.ts +183 -0
- package/offline/conflict-resolution.d.ts.map +1 -0
- package/offline/conflict-resolution.js +286 -0
- package/offline/credential-screen.d.ts +34 -0
- package/offline/credential-screen.d.ts.map +1 -0
- package/offline/credential-screen.js +78 -0
- package/offline/digest.d.ts +15 -0
- package/offline/digest.d.ts.map +1 -0
- package/offline/digest.js +58 -0
- package/offline/edit-queue.d.ts +403 -0
- package/offline/edit-queue.d.ts.map +1 -0
- package/offline/edit-queue.js +1807 -0
- package/offline/edit-replay.d.ts +116 -0
- package/offline/edit-replay.d.ts.map +1 -0
- package/offline/edit-replay.js +392 -0
- package/offline/fetch-handler.d.ts +12 -0
- package/offline/fetch-handler.d.ts.map +1 -0
- package/offline/fetch-handler.js +65 -0
- package/offline/index.d.ts +52 -0
- package/offline/index.d.ts.map +1 -0
- package/offline/index.js +34 -0
- package/offline/indexeddb.d.ts +135 -0
- package/offline/indexeddb.d.ts.map +1 -0
- package/offline/indexeddb.js +888 -0
- package/offline/memory-store.d.ts +17 -0
- package/offline/memory-store.d.ts.map +1 -0
- package/offline/memory-store.js +183 -0
- package/offline/quota.d.ts +161 -0
- package/offline/quota.d.ts.map +1 -0
- package/offline/quota.js +370 -0
- package/offline/read-gate.d.ts +175 -0
- package/offline/read-gate.d.ts.map +1 -0
- package/offline/read-gate.js +252 -0
- package/offline/read-resource.d.ts +99 -0
- package/offline/read-resource.d.ts.map +1 -0
- package/offline/read-resource.js +156 -0
- package/offline/read.d.ts +50 -0
- package/offline/read.d.ts.map +1 -0
- package/offline/read.js +65 -0
- package/offline/region.d.ts +29 -0
- package/offline/region.d.ts.map +1 -0
- package/offline/region.js +1007 -0
- package/offline/replay-conflict.d.ts +183 -0
- package/offline/replay-conflict.d.ts.map +1 -0
- package/offline/replay-conflict.js +482 -0
- package/offline/selection.d.ts +140 -0
- package/offline/selection.d.ts.map +1 -0
- package/offline/selection.js +391 -0
- package/offline/snapshot.d.ts +132 -0
- package/offline/snapshot.d.ts.map +1 -0
- package/offline/snapshot.js +312 -0
- package/offline/status.d.ts +136 -0
- package/offline/status.d.ts.map +1 -0
- package/offline/status.js +479 -0
- package/offline/store-conformance.d.ts +48 -0
- package/offline/store-conformance.d.ts.map +1 -0
- package/offline/store-conformance.js +233 -0
- package/offline/tile-protocol.d.ts +81 -0
- package/offline/tile-protocol.d.ts.map +1 -0
- package/offline/tile-protocol.js +119 -0
- package/offline/types.d.ts +349 -0
- package/offline/types.d.ts.map +1 -0
- package/offline/types.js +75 -0
- package/package.json +14 -2
- package/scene-workspace/index.d.ts +2 -2
- package/scene-workspace/index.d.ts.map +1 -1
- package/scene-workspace/index.js +1 -1
- package/scene-workspace/scene-discovery.d.ts +111 -91
- package/scene-workspace/scene-discovery.d.ts.map +1 -1
- package/scene-workspace/scene-discovery.js +340 -92
- package/scene-workspace/scene-view.d.ts +6 -6
- package/scene-workspace/scene-view.d.ts.map +1 -1
- package/scene-workspace/scene-view.js +32 -6
- package/web-components/elements.d.ts +34 -0
- package/web-components/elements.d.ts.map +1 -1
- package/web-components/elements.js +82 -8
- package/web-components/index.d.ts +2 -0
- package/web-components/index.d.ts.map +1 -1
- package/web-components/index.js +3 -1
- package/web-components/map-chrome.d.ts +103 -0
- package/web-components/map-chrome.d.ts.map +1 -0
- package/web-components/map-chrome.js +325 -0
- package/web-components/widget-shell.d.ts +68 -0
- package/web-components/widget-shell.d.ts.map +1 -0
- package/web-components/widget-shell.js +224 -0
- package/widget-capabilities.d.ts +67 -0
- package/widget-capabilities.js +152 -0
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HTTP scene discovery for the 3D scene workspace.
|
|
3
3
|
*
|
|
4
|
-
* Honua publishes
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* {
|
|
10
|
-
*
|
|
4
|
+
* Honua Server publishes three public JSON contracts, and this module
|
|
5
|
+
* normalizes those rather than the proto `sceneId` / `title` / `extent` shape:
|
|
6
|
+
*
|
|
7
|
+
* - `GET /api/scenes` — list items use `id`, `name`, `tilesetUrl`, `bounds`, `auth`
|
|
8
|
+
* - `GET /api/scenes/{sceneId}` — metadata uses `id`, `name`, `tileset`, `center`, `bounds`, `auth`
|
|
9
|
+
* - `GET /api/scenes/{sceneId}/resolve` — resolution uses `sceneId`, `endpoints`, `auth`
|
|
10
|
+
*
|
|
11
|
+
* `bounds` is `{west,south,east,north}` and is remapped onto {@link SceneExtent3D}.
|
|
12
|
+
* `center` is `{latitude,longitude,height}` and becomes the initial camera.
|
|
13
|
+
* A nested metadata `tileset` object supplies the tileset URL. The flat proto
|
|
14
|
+
* names (`sceneId`, `scene_id`, `title`, `tileset_url`, `extent`) are still
|
|
15
|
+
* accepted so older payloads do not throw; callers that need the server
|
|
16
|
+
* contract should pass the three routes above.
|
|
17
|
+
*
|
|
18
|
+
* The runtime tileset URL comes from {@link resolveScene}. Nothing in this
|
|
19
|
+
* module synthesizes `/scenes/{id}/tileset.json`. An empty id fails closed
|
|
20
|
+
* before a request is sent, and a tileset URL whose path contains `/scenes//`
|
|
21
|
+
* is rejected so a missing id cannot be requested.
|
|
22
|
+
*
|
|
23
|
+
* Auth requirements are retained on the normalized scene. This module does not
|
|
24
|
+
* refresh protected-asset credentials; that is a separate ticket.
|
|
11
25
|
*
|
|
12
26
|
* Discovery calls go through a caller-supplied {@link SceneDiscoveryRequestExecutor}
|
|
13
27
|
* — typically `(...args) => client.pipelineRequestJson(...args)` against a
|
|
14
28
|
* `HonuaClient` — so they reuse the SDK's shared auth / retry / timeout /
|
|
15
|
-
* interceptor pipeline rather than issuing ad-hoc `fetch` calls.
|
|
16
|
-
* transport as a function keeps this module free of a hard `core/client` import
|
|
17
|
-
* (and equally usable from a Node backend, a worker, or a unit test with a mock).
|
|
18
|
-
*
|
|
19
|
-
* The mapping helpers ({@link sceneToRuntimePrimitives},
|
|
20
|
-
* {@link sceneCameraPrimitive}, {@link sceneViewpointBookmarks}) are pure (no
|
|
21
|
-
* Cesium, no transport) and unit-testable on their own.
|
|
29
|
+
* interceptor pipeline rather than issuing ad-hoc `fetch` calls.
|
|
22
30
|
*
|
|
23
31
|
* @experimental Held back from the beta `@honua/app-platform/scene-workspace`
|
|
24
32
|
* tier: Honua Server scene discovery is server-attached, so it sits outside
|
|
@@ -27,107 +35,347 @@
|
|
|
27
35
|
* are beta.
|
|
28
36
|
* @module
|
|
29
37
|
*/
|
|
30
|
-
import { trimTrailingSlashes } from "../core/path-utils.js";
|
|
31
38
|
const SCENES_BASE_PATH = "/api/scenes";
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
const EMPTY_TILESET_PATH = "/scenes//";
|
|
40
|
+
function asRecord(raw, message) {
|
|
41
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
42
|
+
throw new Error(message);
|
|
43
|
+
}
|
|
44
|
+
return raw;
|
|
45
|
+
}
|
|
46
|
+
function readText(value) {
|
|
47
|
+
return typeof value === "string" && value !== "" ? value : undefined;
|
|
48
|
+
}
|
|
49
|
+
function readId(value) {
|
|
50
|
+
if (typeof value !== "string")
|
|
34
51
|
return undefined;
|
|
52
|
+
const trimmed = value.trim();
|
|
53
|
+
return trimmed === "" ? undefined : trimmed;
|
|
54
|
+
}
|
|
55
|
+
function requireSceneId(record, message) {
|
|
56
|
+
// `id` is the list/metadata contract. `sceneId` / `scene_id` remain only so
|
|
57
|
+
// proto-shaped payloads still normalize; an empty value is never substituted.
|
|
58
|
+
const sceneId = readId(record.id) ?? readId(record.sceneId) ?? readId(record.scene_id);
|
|
59
|
+
if (!sceneId)
|
|
60
|
+
throw new Error(message);
|
|
61
|
+
return sceneId;
|
|
62
|
+
}
|
|
63
|
+
function readFinite(value) {
|
|
64
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
65
|
+
}
|
|
66
|
+
/** Reject a blank URL and the empty-id `/scenes//` path. */
|
|
67
|
+
function isUsableSceneResourceUrl(url) {
|
|
68
|
+
if (!url)
|
|
69
|
+
return false;
|
|
70
|
+
const trimmed = url.trim();
|
|
71
|
+
return trimmed !== "" && !trimmed.includes(EMPTY_TILESET_PATH);
|
|
72
|
+
}
|
|
73
|
+
function readStringList(value) {
|
|
74
|
+
if (!Array.isArray(value))
|
|
75
|
+
return undefined;
|
|
76
|
+
return value.filter((item) => typeof item === "string");
|
|
77
|
+
}
|
|
78
|
+
function readAuth(value) {
|
|
79
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
80
|
+
return undefined;
|
|
81
|
+
const record = value;
|
|
82
|
+
const schemes = readStringList(record.schemes) ?? [];
|
|
83
|
+
const policy = readText(record.policy);
|
|
35
84
|
return {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
...(raw.heading !== undefined ? { heading: raw.heading } : {}),
|
|
40
|
-
...(raw.pitch !== undefined ? { pitch: raw.pitch } : {}),
|
|
41
|
-
...(raw.roll !== undefined ? { roll: raw.roll } : {}),
|
|
85
|
+
requiresAuthentication: record.requiresAuthentication === true,
|
|
86
|
+
schemes,
|
|
87
|
+
...(policy !== undefined ? { policy } : {}),
|
|
42
88
|
};
|
|
43
89
|
}
|
|
44
|
-
function
|
|
45
|
-
if (!
|
|
90
|
+
function readEndpoint(value) {
|
|
91
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
92
|
+
return undefined;
|
|
93
|
+
const record = value;
|
|
94
|
+
const url = readText(record.url) ?? readText(record.href);
|
|
95
|
+
const kind = readText(record.kind) ?? readText(record.type) ?? readText(record.format);
|
|
96
|
+
if (!isUsableSceneResourceUrl(url) || !kind)
|
|
46
97
|
return undefined;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
98
|
+
const mediaType = readText(record.mediaType);
|
|
99
|
+
const format = readText(record.format);
|
|
100
|
+
return {
|
|
101
|
+
kind,
|
|
102
|
+
url: url.trim(),
|
|
103
|
+
...(mediaType !== undefined ? { mediaType } : {}),
|
|
104
|
+
...(format !== undefined ? { format } : {}),
|
|
105
|
+
requiresAuthentication: record.requiresAuthentication === true,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function readEndpoints(value) {
|
|
109
|
+
if (!Array.isArray(value))
|
|
110
|
+
return [];
|
|
111
|
+
return value.flatMap((item) => {
|
|
112
|
+
const endpoint = readEndpoint(item);
|
|
113
|
+
return endpoint ? [endpoint] : [];
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function readLinks(value) {
|
|
117
|
+
if (!Array.isArray(value))
|
|
52
118
|
return undefined;
|
|
119
|
+
const links = [];
|
|
120
|
+
for (const item of value) {
|
|
121
|
+
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
122
|
+
continue;
|
|
123
|
+
const record = item;
|
|
124
|
+
const rel = readText(record.rel);
|
|
125
|
+
const href = readText(record.href);
|
|
126
|
+
if (!rel || !href)
|
|
127
|
+
continue;
|
|
128
|
+
const type = readText(record.type);
|
|
129
|
+
const title = readText(record.title);
|
|
130
|
+
links.push({
|
|
131
|
+
rel,
|
|
132
|
+
href,
|
|
133
|
+
...(type !== undefined ? { type } : {}),
|
|
134
|
+
...(title !== undefined ? { title } : {}),
|
|
135
|
+
});
|
|
53
136
|
}
|
|
54
|
-
|
|
55
|
-
|
|
137
|
+
return links;
|
|
138
|
+
}
|
|
139
|
+
function readTilesetUrl(record) {
|
|
140
|
+
const flat = readText(record.tilesetUrl) ?? readText(record.tileset_url);
|
|
141
|
+
if (isUsableSceneResourceUrl(flat))
|
|
142
|
+
return flat.trim();
|
|
143
|
+
const tileset = record.tileset;
|
|
144
|
+
if (!tileset || typeof tileset !== "object" || Array.isArray(tileset))
|
|
145
|
+
return undefined;
|
|
146
|
+
const nested = tileset;
|
|
147
|
+
const url = readText(nested.url) ?? readText(nested.href);
|
|
148
|
+
return isUsableSceneResourceUrl(url) ? url.trim() : undefined;
|
|
149
|
+
}
|
|
150
|
+
function normalizeCamera(raw) {
|
|
151
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
152
|
+
return undefined;
|
|
153
|
+
const camera = raw;
|
|
154
|
+
const longitude = readFinite(camera.longitude);
|
|
155
|
+
const latitude = readFinite(camera.latitude);
|
|
156
|
+
if (longitude === undefined || latitude === undefined)
|
|
157
|
+
return undefined;
|
|
158
|
+
const height = readFinite(camera.height) ?? 0;
|
|
159
|
+
const heading = readFinite(camera.heading);
|
|
160
|
+
const pitch = readFinite(camera.pitch);
|
|
161
|
+
const roll = readFinite(camera.roll);
|
|
162
|
+
return {
|
|
163
|
+
longitude,
|
|
164
|
+
latitude,
|
|
165
|
+
height,
|
|
166
|
+
...(heading !== undefined ? { heading } : {}),
|
|
167
|
+
...(pitch !== undefined ? { pitch } : {}),
|
|
168
|
+
...(roll !== undefined ? { roll } : {}),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/** Server `bounds` (`west`/`south`/`east`/`north`) onto the SDK extent axes. */
|
|
172
|
+
function readBounds(raw) {
|
|
173
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
174
|
+
return undefined;
|
|
175
|
+
const bounds = raw;
|
|
176
|
+
const xmin = readFinite(bounds.west);
|
|
177
|
+
const ymin = readFinite(bounds.south);
|
|
178
|
+
const xmax = readFinite(bounds.east);
|
|
179
|
+
const ymax = readFinite(bounds.north);
|
|
180
|
+
if (xmin === undefined || ymin === undefined || xmax === undefined || ymax === undefined)
|
|
181
|
+
return undefined;
|
|
182
|
+
return { xmin, ymin, xmax, ymax };
|
|
183
|
+
}
|
|
184
|
+
/** Proto `extent` tolerance: a flat or nested `{xmin,ymin,xmax,ymax}` envelope. */
|
|
185
|
+
function readProtoExtent(raw) {
|
|
186
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
187
|
+
return undefined;
|
|
188
|
+
const record = raw;
|
|
189
|
+
const nested = record.extent;
|
|
190
|
+
const envelope = nested && typeof nested === "object" && !Array.isArray(nested) ? nested : record;
|
|
191
|
+
const xmin = readFinite(envelope.xmin);
|
|
192
|
+
const ymin = readFinite(envelope.ymin);
|
|
193
|
+
const xmax = readFinite(envelope.xmax);
|
|
194
|
+
const ymax = readFinite(envelope.ymax);
|
|
195
|
+
if (xmin === undefined || ymin === undefined || xmax === undefined || ymax === undefined)
|
|
196
|
+
return undefined;
|
|
197
|
+
const minHeight = readFinite(record.minHeight) ?? readFinite(record.min_height);
|
|
198
|
+
const maxHeight = readFinite(record.maxHeight) ?? readFinite(record.max_height);
|
|
199
|
+
const spatialReference = readFinite(envelope.spatialReference);
|
|
56
200
|
return {
|
|
57
|
-
xmin
|
|
58
|
-
ymin
|
|
59
|
-
xmax
|
|
60
|
-
ymax
|
|
201
|
+
xmin,
|
|
202
|
+
ymin,
|
|
203
|
+
xmax,
|
|
204
|
+
ymax,
|
|
61
205
|
...(minHeight !== undefined ? { minHeight } : {}),
|
|
62
206
|
...(maxHeight !== undefined ? { maxHeight } : {}),
|
|
63
|
-
...(
|
|
207
|
+
...(spatialReference !== undefined ? { spatialReference } : {}),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function readExtent(record) {
|
|
211
|
+
return readBounds(record.bounds) ?? readProtoExtent(record.extent);
|
|
212
|
+
}
|
|
213
|
+
function readInitialCamera(record) {
|
|
214
|
+
const explicit = normalizeCamera(record.initialCamera) ?? normalizeCamera(record.initial_camera);
|
|
215
|
+
if (explicit)
|
|
216
|
+
return explicit;
|
|
217
|
+
return normalizeCamera(record.center);
|
|
218
|
+
}
|
|
219
|
+
function readViewpoints(value) {
|
|
220
|
+
if (!Array.isArray(value))
|
|
221
|
+
return [];
|
|
222
|
+
const viewpoints = [];
|
|
223
|
+
for (const item of value) {
|
|
224
|
+
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
225
|
+
continue;
|
|
226
|
+
const record = item;
|
|
227
|
+
const id = readId(record.id);
|
|
228
|
+
const camera = normalizeCamera(record.camera);
|
|
229
|
+
if (!id || !camera)
|
|
230
|
+
continue;
|
|
231
|
+
const title = readText(record.title) ?? id;
|
|
232
|
+
viewpoints.push({ id, title, camera });
|
|
233
|
+
}
|
|
234
|
+
return viewpoints;
|
|
235
|
+
}
|
|
236
|
+
function readStyleExpression(record) {
|
|
237
|
+
const direct = readText(record.styleExpression);
|
|
238
|
+
if (direct)
|
|
239
|
+
return direct;
|
|
240
|
+
const style = record.style;
|
|
241
|
+
if (!style || typeof style !== "object" || Array.isArray(style))
|
|
242
|
+
return undefined;
|
|
243
|
+
return readText(style.expression);
|
|
244
|
+
}
|
|
245
|
+
function readScene(record, missingIdMessage) {
|
|
246
|
+
const sceneId = requireSceneId(record, missingIdMessage);
|
|
247
|
+
const name = readText(record.name);
|
|
248
|
+
const title = name ?? readText(record.title);
|
|
249
|
+
const description = readText(record.description);
|
|
250
|
+
const tilesetUrl = readTilesetUrl(record);
|
|
251
|
+
const terrainUrl = readText(record.terrainUrl) ?? readText(record.terrain_url);
|
|
252
|
+
const extent = readExtent(record);
|
|
253
|
+
const initialCamera = readInitialCamera(record);
|
|
254
|
+
const styleExpression = readStyleExpression(record);
|
|
255
|
+
const edition = readText(record.edition);
|
|
256
|
+
const auth = readAuth(record.auth);
|
|
257
|
+
const attribution = readStringList(record.attribution);
|
|
258
|
+
const updatedAt = readText(record.updatedAt);
|
|
259
|
+
const links = readLinks(record.links);
|
|
260
|
+
const usableTerrain = isUsableSceneResourceUrl(terrainUrl) ? terrainUrl.trim() : undefined;
|
|
261
|
+
return {
|
|
262
|
+
sceneId,
|
|
263
|
+
...(name !== undefined ? { name } : {}),
|
|
264
|
+
...(title !== undefined ? { title } : {}),
|
|
265
|
+
...(description !== undefined ? { description } : {}),
|
|
266
|
+
...(tilesetUrl !== undefined ? { tilesetUrl } : {}),
|
|
267
|
+
...(usableTerrain !== undefined ? { terrainUrl: usableTerrain } : {}),
|
|
268
|
+
...(extent ? { extent } : {}),
|
|
269
|
+
...(initialCamera ? { initialCamera } : {}),
|
|
270
|
+
viewpoints: readViewpoints(record.viewpoints),
|
|
271
|
+
...(styleExpression !== undefined ? { styleExpression } : {}),
|
|
272
|
+
...(edition !== undefined ? { edition } : {}),
|
|
273
|
+
capabilities: readStringList(record.capabilities) ?? [],
|
|
274
|
+
...(auth ? { auth } : {}),
|
|
275
|
+
...(attribution ? { attribution } : {}),
|
|
276
|
+
...(updatedAt !== undefined ? { updatedAt } : {}),
|
|
277
|
+
...(links ? { links } : {}),
|
|
64
278
|
};
|
|
65
279
|
}
|
|
280
|
+
function unwrapSceneEnvelope(raw) {
|
|
281
|
+
const record = asRecord(raw, "Scene response must be a JSON object.");
|
|
282
|
+
const nested = record.scene;
|
|
283
|
+
const hasOwnId = readId(record.id) ?? readId(record.sceneId) ?? readId(record.scene_id);
|
|
284
|
+
if (!hasOwnId && nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
285
|
+
return nested;
|
|
286
|
+
}
|
|
287
|
+
return record;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Normalize one list item from `GET /api/scenes`.
|
|
291
|
+
* Reads `id`, `name`, `tilesetUrl`, `bounds`, and `auth`.
|
|
292
|
+
*/
|
|
293
|
+
export function normalizeSceneSummary(raw) {
|
|
294
|
+
return readScene(asRecord(raw, "Scene list item must be a JSON object."), "Scene list item is missing an id.");
|
|
295
|
+
}
|
|
66
296
|
/**
|
|
67
|
-
* Normalize
|
|
68
|
-
*
|
|
69
|
-
*
|
|
297
|
+
* Normalize `GET /api/scenes/{sceneId}`.
|
|
298
|
+
* Reads `id`, `name`, `tileset`, `center`, `bounds`, and `auth`.
|
|
299
|
+
* A `{ scene }` envelope is accepted only when the root has no id of its own
|
|
300
|
+
* (proto-shaped responses). The server returns the metadata object itself.
|
|
301
|
+
*/
|
|
302
|
+
export function normalizeSceneMetadata(raw) {
|
|
303
|
+
return readScene(unwrapSceneEnvelope(raw), "Scene metadata is missing an id.");
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Normalize a scene payload. Prefer {@link normalizeSceneSummary} or
|
|
307
|
+
* {@link normalizeSceneMetadata} at the route boundary. This entry point
|
|
308
|
+
* accepts either of those contracts and the documented proto field names.
|
|
70
309
|
*/
|
|
71
310
|
export function normalizeScene(raw) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const
|
|
311
|
+
return readScene(unwrapSceneEnvelope(raw), "Scene response is missing an id.");
|
|
312
|
+
}
|
|
313
|
+
function tilesetEndpointUrl(endpoints) {
|
|
314
|
+
const match = endpoints.find((endpoint) => endpoint.kind === "3d-tiles" || endpoint.format === "3d-tiles");
|
|
315
|
+
return match && isUsableSceneResourceUrl(match.url) ? match.url.trim() : undefined;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Normalize `GET /api/scenes/{sceneId}/resolve`.
|
|
319
|
+
* Reads `sceneId`, `endpoints`, and `auth`. The runtime tileset URL is the
|
|
320
|
+
* response `tilesetUrl` when usable, otherwise the `3d-tiles` endpoint.
|
|
321
|
+
*/
|
|
322
|
+
export function normalizeSceneResolution(raw) {
|
|
323
|
+
const record = asRecord(raw, "Scene resolution must be a JSON object.");
|
|
324
|
+
const sceneId = requireSceneId(record, "Scene resolution is missing a sceneId.");
|
|
325
|
+
const endpoints = readEndpoints(record.endpoints);
|
|
326
|
+
const flat = readText(record.tilesetUrl) ?? readText(record.tileset_url);
|
|
327
|
+
const tilesetUrl = (isUsableSceneResourceUrl(flat) ? flat.trim() : undefined) ?? tilesetEndpointUrl(endpoints);
|
|
328
|
+
const auth = readAuth(record.auth) ?? { requiresAuthentication: false, schemes: [] };
|
|
85
329
|
return {
|
|
86
330
|
sceneId,
|
|
87
|
-
...(raw.title !== undefined ? { title: raw.title } : {}),
|
|
88
|
-
...(raw.description !== undefined ? { description: raw.description } : {}),
|
|
89
331
|
...(tilesetUrl !== undefined ? { tilesetUrl } : {}),
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
viewpoints,
|
|
94
|
-
...(styleExpression !== undefined ? { styleExpression } : {}),
|
|
95
|
-
...(raw.edition !== undefined ? { edition: raw.edition } : {}),
|
|
96
|
-
capabilities: raw.capabilities ?? [],
|
|
332
|
+
endpoints,
|
|
333
|
+
capabilities: readStringList(record.capabilities) ?? [],
|
|
334
|
+
auth,
|
|
97
335
|
};
|
|
98
336
|
}
|
|
99
337
|
/**
|
|
100
|
-
* List the catalog of available 3D scenes from `GET /api/scenes
|
|
101
|
-
*
|
|
338
|
+
* List the catalog of available 3D scenes from `GET /api/scenes`.
|
|
339
|
+
* Returns the normalized {@link HonuaScene}s. A list item with no id throws;
|
|
340
|
+
* it is not returned with an empty id.
|
|
102
341
|
*/
|
|
103
342
|
export async function listScenes(execute, signal) {
|
|
104
343
|
const raw = await execute("GET", SCENES_BASE_PATH, undefined, signal);
|
|
105
|
-
|
|
344
|
+
const record = asRecord(raw, "Scene list response must be a JSON object.");
|
|
345
|
+
if (!Array.isArray(record.scenes)) {
|
|
346
|
+
throw new Error("Scene list response must contain a scenes array.");
|
|
347
|
+
}
|
|
348
|
+
return record.scenes.map((item) => normalizeSceneSummary(item));
|
|
106
349
|
}
|
|
107
350
|
/**
|
|
108
|
-
* Fetch a single scene's metadata from `GET /api/scenes/{sceneId}
|
|
109
|
-
*
|
|
110
|
-
* object or a `{ scene }` envelope.
|
|
351
|
+
* Fetch a single scene's metadata from `GET /api/scenes/{sceneId}`.
|
|
352
|
+
* Fails closed before the request when `sceneId` is empty.
|
|
111
353
|
*/
|
|
112
354
|
export async function getScene(execute, sceneId, signal) {
|
|
113
|
-
if (
|
|
355
|
+
if (typeof sceneId !== "string" || sceneId.trim() === "") {
|
|
114
356
|
throw new Error("getScene requires a non-empty sceneId.");
|
|
115
|
-
|
|
116
|
-
|
|
357
|
+
}
|
|
358
|
+
const raw = await execute("GET", `${SCENES_BASE_PATH}/${encodeURIComponent(sceneId.trim())}`, undefined, signal);
|
|
359
|
+
return normalizeSceneMetadata(raw);
|
|
117
360
|
}
|
|
118
361
|
/**
|
|
119
|
-
* Resolve
|
|
120
|
-
*
|
|
121
|
-
* `tilesetUrl
|
|
122
|
-
* when the scene omits one. Returns `undefined` when neither is available.
|
|
362
|
+
* Resolve a scene's runtime endpoints from `GET /api/scenes/{sceneId}/resolve`.
|
|
363
|
+
* Fails closed before the request when `sceneId` is empty. The returned
|
|
364
|
+
* `tilesetUrl` is taken from the server payload only.
|
|
123
365
|
*/
|
|
124
|
-
export function
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
366
|
+
export async function resolveScene(execute, sceneId, signal) {
|
|
367
|
+
if (typeof sceneId !== "string" || sceneId.trim() === "") {
|
|
368
|
+
throw new Error("resolveScene requires a non-empty sceneId.");
|
|
369
|
+
}
|
|
370
|
+
const raw = await execute("GET", `${SCENES_BASE_PATH}/${encodeURIComponent(sceneId.trim())}/resolve`, undefined, signal);
|
|
371
|
+
return normalizeSceneResolution(raw);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* The scene's advertised 3D-Tiles entry-point URL, or `undefined` when the
|
|
375
|
+
* scene has none. Does not synthesize a `/scenes/{id}/tileset.json` path.
|
|
376
|
+
*/
|
|
377
|
+
export function resolveSceneTilesetUrl(scene) {
|
|
378
|
+
return isUsableSceneResourceUrl(scene.tilesetUrl) ? scene.tilesetUrl.trim() : undefined;
|
|
131
379
|
}
|
|
132
380
|
/**
|
|
133
381
|
* Build the camera primitive for a scene's suggested initial view, or
|
|
@@ -147,8 +395,8 @@ export function sceneCameraPrimitive(scene) {
|
|
|
147
395
|
* Build the 3D-Tiles model-layer primitive for a scene's root tileset, or
|
|
148
396
|
* `undefined` when the scene has no resolvable tileset URL. Pure.
|
|
149
397
|
*/
|
|
150
|
-
export function sceneTilesetPrimitive(scene
|
|
151
|
-
const uri = resolveSceneTilesetUrl(scene
|
|
398
|
+
export function sceneTilesetPrimitive(scene) {
|
|
399
|
+
const uri = resolveSceneTilesetUrl(scene);
|
|
152
400
|
if (!uri)
|
|
153
401
|
return undefined;
|
|
154
402
|
return {
|
|
@@ -165,23 +413,23 @@ export function sceneTilesetPrimitive(scene, baseUrl) {
|
|
|
165
413
|
* treated as a quantized-mesh endpoint (Cesium's `CesiumTerrainProvider`).
|
|
166
414
|
*/
|
|
167
415
|
export function sceneTerrainPrimitive(scene) {
|
|
168
|
-
if (!scene.terrainUrl
|
|
416
|
+
if (!isUsableSceneResourceUrl(scene.terrainUrl))
|
|
169
417
|
return undefined;
|
|
170
418
|
return {
|
|
171
419
|
kind: "elevation-source",
|
|
172
420
|
id: `${scene.sceneId}:terrain`,
|
|
173
421
|
sourceId: `${scene.sceneId}:terrain`,
|
|
174
422
|
protocol: "quantized-mesh",
|
|
175
|
-
url: scene.terrainUrl,
|
|
423
|
+
url: scene.terrainUrl.trim(),
|
|
176
424
|
};
|
|
177
425
|
}
|
|
178
426
|
/**
|
|
179
427
|
* Map a discovered scene onto the renderer-neutral primitives the Cesium
|
|
180
428
|
* adapter renders: an initial-camera primitive, the terrain elevation source
|
|
181
|
-
* (when present), and the 3D-Tiles tileset (when
|
|
182
|
-
* feeds straight into `applyCesiumScenePrimitives` / a `SceneView`.
|
|
429
|
+
* (when present), and the 3D-Tiles tileset (when the scene advertises a URL).
|
|
430
|
+
* Pure; the result feeds straight into `applyCesiumScenePrimitives` / a `SceneView`.
|
|
183
431
|
*/
|
|
184
|
-
export function sceneToRuntimePrimitives(scene
|
|
432
|
+
export function sceneToRuntimePrimitives(scene) {
|
|
185
433
|
const primitives = [];
|
|
186
434
|
const camera = sceneCameraPrimitive(scene);
|
|
187
435
|
if (camera)
|
|
@@ -189,7 +437,7 @@ export function sceneToRuntimePrimitives(scene, baseUrl) {
|
|
|
189
437
|
const terrain = sceneTerrainPrimitive(scene);
|
|
190
438
|
if (terrain)
|
|
191
439
|
primitives.push(terrain);
|
|
192
|
-
const tileset = sceneTilesetPrimitive(scene
|
|
440
|
+
const tileset = sceneTilesetPrimitive(scene);
|
|
193
441
|
if (tileset)
|
|
194
442
|
primitives.push(tileset);
|
|
195
443
|
return primitives;
|
|
@@ -199,9 +447,9 @@ export function sceneToRuntimePrimitives(scene, baseUrl) {
|
|
|
199
447
|
* primitive), so a {@link module:scene-workspace/workspace.SceneWorkspace} can
|
|
200
448
|
* seed its layer list from the scene. Pure.
|
|
201
449
|
*/
|
|
202
|
-
export function sceneLayerStates(scene
|
|
450
|
+
export function sceneLayerStates(scene) {
|
|
203
451
|
const layers = [];
|
|
204
|
-
if (sceneTilesetPrimitive(scene
|
|
452
|
+
if (sceneTilesetPrimitive(scene)) {
|
|
205
453
|
layers.push({
|
|
206
454
|
id: `${scene.sceneId}:tileset`,
|
|
207
455
|
title: scene.title ?? scene.sceneId,
|
|
@@ -43,7 +43,7 @@ import type { QueryMethod } from "../core/types.js";
|
|
|
43
43
|
import { type CesiumEntityCollectionLike, type ElevationProfileRequest, type ElevationProfileResult, type LineOfSightRequest, type LineOfSightResult, type SceneAnalysisCesiumModule, type SceneAnalysisOverlay, type SceneAnalysisPosition, type SceneMeasurement, type ViewshedRequest, type ViewshedResult } from "./analysis-widgets.js";
|
|
44
44
|
import { type CesiumSceneRuntimeTarget } from "./cesium-adapter.js";
|
|
45
45
|
import type { ScenePrimitiveDiagnostic } from "./primitives.js";
|
|
46
|
-
import { type HonuaScene } from "./scene-discovery.js";
|
|
46
|
+
import { type HonuaScene, type HonuaSceneResolution } from "./scene-discovery.js";
|
|
47
47
|
import type { SceneBookmark, SceneCameraState, SceneLayerState } from "./types.js";
|
|
48
48
|
/**
|
|
49
49
|
* The request transport a {@link SceneView} uses for scene discovery and
|
|
@@ -71,11 +71,6 @@ export interface SceneViewOptions {
|
|
|
71
71
|
* rendering). Omit to load + diagnose scenes headlessly without rendering.
|
|
72
72
|
*/
|
|
73
73
|
readonly target?: CesiumSceneRuntimeTarget;
|
|
74
|
-
/**
|
|
75
|
-
* Base URL used to resolve a scene's static `tileset.json` entry point when
|
|
76
|
-
* the scene omits an explicit `tilesetUrl`. Defaults to `client.serverBaseUrl`.
|
|
77
|
-
*/
|
|
78
|
-
readonly baseUrl?: string;
|
|
79
74
|
}
|
|
80
75
|
/** Events emitted by a {@link SceneView}. */
|
|
81
76
|
export type SceneViewEvent = {
|
|
@@ -115,6 +110,11 @@ export declare class SceneView {
|
|
|
115
110
|
listScenes(signal?: AbortSignal): Promise<HonuaScene[]>;
|
|
116
111
|
/** Fetch a single scene's metadata without loading it (`GET /api/scenes/{id}`). */
|
|
117
112
|
getScene(sceneId: string, signal?: AbortSignal): Promise<HonuaScene>;
|
|
113
|
+
/**
|
|
114
|
+
* Resolve a scene's runtime endpoints (`GET /api/scenes/{id}/resolve`).
|
|
115
|
+
* The tileset URL in the result is the server's. This view does not invent one.
|
|
116
|
+
*/
|
|
117
|
+
resolveScene(sceneId: string, signal?: AbortSignal): Promise<HonuaSceneResolution>;
|
|
118
118
|
/**
|
|
119
119
|
* Load a scene by id (or a pre-fetched {@link HonuaScene}) and render it onto
|
|
120
120
|
* the live target: the initial camera, terrain provider, and 3D-Tiles
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-view.d.ts","sourceRoot":"","sources":["../../../src/scene-workspace/scene-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAE1B,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EASpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,KAAK,wBAAwB,EAG9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EACL,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"scene-view.d.ts","sourceRoot":"","sources":["../../../src/scene-workspace/scene-view.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
*/
|
|
41
41
|
import { measureScenePositions, renderElevationProfilePolyline, renderLineOfSight, renderMeasurement, renderViewshed, requestElevationProfile, requestLineOfSight, requestViewshed, } from "./analysis-widgets.js";
|
|
42
42
|
import { applyCesiumScenePrimitives, cesiumCameraToSceneState, } from "./cesium-adapter.js";
|
|
43
|
-
import { getScene, listScenes, sceneLayerStates, sceneToRuntimePrimitives, sceneViewpointBookmarks, } from "./scene-discovery.js";
|
|
43
|
+
import { getScene, listScenes, resolveScene as requestSceneResolution, sceneLayerStates, sceneToRuntimePrimitives, sceneViewpointBookmarks, } from "./scene-discovery.js";
|
|
44
44
|
/**
|
|
45
45
|
* First-class 3D scene container. Loads a Honua scene, renders it through the
|
|
46
46
|
* Cesium adapter, and exposes the analysis/measurement widgets.
|
|
@@ -48,7 +48,6 @@ import { getScene, listScenes, sceneLayerStates, sceneToRuntimePrimitives, scene
|
|
|
48
48
|
export class SceneView {
|
|
49
49
|
#execute;
|
|
50
50
|
#target;
|
|
51
|
-
#baseUrl;
|
|
52
51
|
#listeners = new Set();
|
|
53
52
|
#layerHandles = new Map();
|
|
54
53
|
#scene;
|
|
@@ -62,7 +61,6 @@ export class SceneView {
|
|
|
62
61
|
}
|
|
63
62
|
this.#execute = execute;
|
|
64
63
|
this.#target = options.target;
|
|
65
|
-
this.#baseUrl = options.baseUrl ?? options.client?.serverBaseUrl;
|
|
66
64
|
}
|
|
67
65
|
// ── Discovery ───────────────────────────────────────────────
|
|
68
66
|
/** List the catalog of available 3D scenes (`GET /api/scenes`). */
|
|
@@ -73,6 +71,13 @@ export class SceneView {
|
|
|
73
71
|
getScene(sceneId, signal) {
|
|
74
72
|
return getScene(this.#discoveryExecutor(), sceneId, signal);
|
|
75
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Resolve a scene's runtime endpoints (`GET /api/scenes/{id}/resolve`).
|
|
76
|
+
* The tileset URL in the result is the server's. This view does not invent one.
|
|
77
|
+
*/
|
|
78
|
+
resolveScene(sceneId, signal) {
|
|
79
|
+
return requestSceneResolution(this.#discoveryExecutor(), sceneId, signal);
|
|
80
|
+
}
|
|
76
81
|
// ── Loading / rendering ─────────────────────────────────────
|
|
77
82
|
/**
|
|
78
83
|
* Load a scene by id (or a pre-fetched {@link HonuaScene}) and render it onto
|
|
@@ -82,13 +87,23 @@ export class SceneView {
|
|
|
82
87
|
* rendered.
|
|
83
88
|
*/
|
|
84
89
|
async loadScene(scene, signal) {
|
|
85
|
-
const
|
|
90
|
+
const requestedId = typeof scene === "string" ? scene : scene.sceneId;
|
|
91
|
+
if (typeof requestedId !== "string" || requestedId.trim() === "") {
|
|
92
|
+
throw new Error("loadScene requires a non-empty sceneId.");
|
|
93
|
+
}
|
|
94
|
+
const sceneId = requestedId.trim();
|
|
95
|
+
const execute = this.#discoveryExecutor();
|
|
96
|
+
const metadata = typeof scene === "string" ? await getScene(execute, sceneId, signal) : scene;
|
|
97
|
+
// Resolve is the only source of the runtime tileset URL. Do not synthesize
|
|
98
|
+
// `/scenes/{id}/tileset.json` from the client origin when the payload omits one.
|
|
99
|
+
const resolution = await requestSceneResolution(execute, sceneId, signal);
|
|
100
|
+
const resolved = sceneWithResolvedRuntime(metadata, resolution);
|
|
86
101
|
this.#teardownLayers();
|
|
87
102
|
this.#scene = resolved;
|
|
88
103
|
this.#bookmarks = sceneViewpointBookmarks(resolved);
|
|
89
|
-
this.#layers = sceneLayerStates(resolved
|
|
104
|
+
this.#layers = sceneLayerStates(resolved);
|
|
90
105
|
if (this.#target) {
|
|
91
|
-
const primitives = sceneToRuntimePrimitives(resolved
|
|
106
|
+
const primitives = sceneToRuntimePrimitives(resolved);
|
|
92
107
|
const result = await applyCesiumScenePrimitives(this.#target, primitives);
|
|
93
108
|
this.#diagnostics = result.diagnostics;
|
|
94
109
|
for (const [id, handle] of result.layers)
|
|
@@ -268,3 +283,14 @@ function bindClientExecutor(client) {
|
|
|
268
283
|
return undefined;
|
|
269
284
|
return (method, path, init, signal) => client.pipelineRequestJson(method, path, init, signal);
|
|
270
285
|
}
|
|
286
|
+
/** Keep metadata for display, but take the runtime tileset URL only from resolve. */
|
|
287
|
+
function sceneWithResolvedRuntime(scene, resolution) {
|
|
288
|
+
const { tilesetUrl: _metadataTilesetUrl, ...rest } = scene;
|
|
289
|
+
return {
|
|
290
|
+
...rest,
|
|
291
|
+
sceneId: resolution.sceneId,
|
|
292
|
+
capabilities: resolution.capabilities,
|
|
293
|
+
auth: resolution.auth,
|
|
294
|
+
...(resolution.tilesetUrl ? { tilesetUrl: resolution.tilesetUrl } : {}),
|
|
295
|
+
};
|
|
296
|
+
}
|