@loaders.gl/tiles 5.0.0-alpha.1 → 5.0.0-alpha.3
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/LICENSE +14 -3
- package/dist/dist.dev.js +17482 -3685
- package/dist/dist.min.js +4 -1
- package/dist/index.cjs +4594 -422
- package/dist/index.cjs.map +3 -4
- package/dist/index.d.ts +16 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/point-cloud/point-cloud-tile.d.ts.map +1 -1
- package/dist/point-cloud/point-cloud-tile.js +3 -0
- package/dist/point-cloud/point-cloud-tile.js.map +1 -1
- package/dist/point-cloud/point-cloud-tileset.d.ts +4 -0
- package/dist/point-cloud/point-cloud-tileset.d.ts.map +1 -1
- package/dist/point-cloud/point-cloud-tileset.js +54 -12
- package/dist/point-cloud/point-cloud-tileset.js.map +1 -1
- package/dist/point-cloud/types.d.ts +17 -0
- package/dist/point-cloud/types.d.ts.map +1 -1
- package/dist/point-cloud/types.js +3 -0
- package/dist/point-cloud/types.js.map +1 -1
- package/dist/raster-set.d.ts +37 -29
- package/dist/raster-set.d.ts.map +1 -1
- package/dist/raster-set.js +25 -2
- package/dist/raster-set.js.map +1 -1
- package/dist/spatial/format-spatial-reference.d.ts +67 -0
- package/dist/spatial/format-spatial-reference.d.ts.map +1 -0
- package/dist/spatial/format-spatial-reference.js +233 -0
- package/dist/spatial/format-spatial-reference.js.map +1 -0
- package/dist/spatial/get-spatial-coordinate-frame.d.ts +9 -0
- package/dist/spatial/get-spatial-coordinate-frame.d.ts.map +1 -0
- package/dist/spatial/get-spatial-coordinate-frame.js +58 -0
- package/dist/spatial/get-spatial-coordinate-frame.js.map +1 -0
- package/dist/spatial/i3s-elevation.d.ts +20 -0
- package/dist/spatial/i3s-elevation.d.ts.map +1 -0
- package/dist/spatial/i3s-elevation.js +90 -0
- package/dist/spatial/i3s-elevation.js.map +1 -0
- package/dist/spatial/i3s-spatial-transformer.d.ts +189 -0
- package/dist/spatial/i3s-spatial-transformer.d.ts.map +1 -0
- package/dist/spatial/i3s-spatial-transformer.js +686 -0
- package/dist/spatial/i3s-spatial-transformer.js.map +1 -0
- package/dist/spatial/spatial-coordinate-transformer.d.ts +48 -0
- package/dist/spatial/spatial-coordinate-transformer.d.ts.map +1 -0
- package/dist/spatial/spatial-coordinate-transformer.js +211 -0
- package/dist/spatial/spatial-coordinate-transformer.js.map +1 -0
- package/dist/spatial/spatial-resource-registry.d.ts +44 -0
- package/dist/spatial/spatial-resource-registry.d.ts.map +1 -0
- package/dist/spatial/spatial-resource-registry.js +67 -0
- package/dist/spatial/spatial-resource-registry.js.map +1 -0
- package/dist/spatial/spatial-types.d.ts +190 -0
- package/dist/spatial/spatial-types.d.ts.map +1 -0
- package/dist/spatial/spatial-types.js +192 -0
- package/dist/spatial/spatial-types.js.map +1 -0
- package/dist/tileset-3d/common/tile-3d.d.ts +147 -4
- package/dist/tileset-3d/common/tile-3d.d.ts.map +1 -1
- package/dist/tileset-3d/common/tile-3d.js +358 -76
- package/dist/tileset-3d/common/tile-3d.js.map +1 -1
- package/dist/tileset-3d/common/tileset-3d.d.ts +168 -3
- package/dist/tileset-3d/common/tileset-3d.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-3d.js +306 -23
- package/dist/tileset-3d/common/tileset-3d.js.map +1 -1
- package/dist/tileset-3d/common/tileset-cache.d.ts +11 -1
- package/dist/tileset-3d/common/tileset-cache.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-cache.js +11 -3
- package/dist/tileset-3d/common/tileset-cache.js.map +1 -1
- package/dist/tileset-3d/common/tileset-source.d.ts +32 -0
- 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 +19 -1
- package/dist/tileset-3d/common/tileset-traverser.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-traverser.js +39 -7
- package/dist/tileset-3d/common/tileset-traverser.js.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts +136 -0
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts.map +1 -0
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js +384 -0
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js.map +1 -0
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts +86 -3
- 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 +196 -21
- 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 +36 -0
- 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 +66 -0
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.d.ts.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.js +3 -0
- package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.js.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-source.d.ts +14 -1
- package/dist/tileset-3d/format-i3s/i3s-source.d.ts.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-source.js +107 -17
- package/dist/tileset-3d/format-i3s/i3s-source.js.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-tile-manager.d.ts.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-tile-manager.js +3 -0
- package/dist/tileset-3d/format-i3s/i3s-tile-manager.js.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.d.ts.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.js +3 -0
- package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.js.map +1 -1
- package/dist/tileset-3d/helpers/3d-tiles-options.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/3d-tiles-options.js +3 -0
- package/dist/tileset-3d/helpers/3d-tiles-options.js.map +1 -1
- package/dist/tileset-3d/helpers/bounding-volume.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/bounding-volume.js +4 -33
- package/dist/tileset-3d/helpers/bounding-volume.js.map +1 -1
- package/dist/tileset-3d/helpers/frame-state.d.ts +62 -2
- package/dist/tileset-3d/helpers/frame-state.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/frame-state.js +85 -9
- package/dist/tileset-3d/helpers/frame-state.js.map +1 -1
- package/dist/tileset-3d/helpers/i3s-lod.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/i3s-lod.js +20 -8
- package/dist/tileset-3d/helpers/i3s-lod.js.map +1 -1
- package/dist/tileset-3d/helpers/tiles-3d-lod.d.ts +61 -9
- package/dist/tileset-3d/helpers/tiles-3d-lod.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/tiles-3d-lod.js +198 -93
- package/dist/tileset-3d/helpers/tiles-3d-lod.js.map +1 -1
- package/dist/tileset-3d/helpers/tiles-3d-request-priority.d.ts +134 -0
- package/dist/tileset-3d/helpers/tiles-3d-request-priority.d.ts.map +1 -0
- package/dist/tileset-3d/helpers/tiles-3d-request-priority.js +179 -0
- package/dist/tileset-3d/helpers/tiles-3d-request-priority.js.map +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/doubly-linked-list.d.ts.map +1 -1
- package/dist/utils/doubly-linked-list.js +1 -0
- package/dist/utils/doubly-linked-list.js.map +1 -1
- package/dist/utils/managed-array.d.ts.map +1 -1
- package/dist/utils/managed-array.js +1 -0
- package/dist/utils/managed-array.js.map +1 -1
- package/package.json +12 -9
- package/src/index.ts +61 -1
- package/src/point-cloud/point-cloud-tile.ts +4 -0
- package/src/point-cloud/point-cloud-tileset.ts +70 -12
- package/src/point-cloud/types.ts +21 -0
- package/src/raster-set.ts +118 -45
- package/src/spatial/format-spatial-reference.ts +311 -0
- package/src/spatial/get-spatial-coordinate-frame.ts +74 -0
- package/src/spatial/i3s-elevation.ts +96 -0
- package/src/spatial/i3s-spatial-transformer.ts +957 -0
- package/src/spatial/spatial-coordinate-transformer.ts +276 -0
- package/src/spatial/spatial-resource-registry.ts +79 -0
- package/src/spatial/spatial-types.ts +422 -0
- package/src/tileset-3d/common/tile-3d.ts +435 -84
- package/src/tileset-3d/common/tileset-3d.ts +445 -23
- package/src/tileset-3d/common/tileset-cache.ts +15 -7
- package/src/tileset-3d/common/tileset-source.ts +36 -0
- package/src/tileset-3d/common/tileset-traverser.ts +40 -7
- package/src/tileset-3d/format-3d-tiles/implicit-tiling.ts +612 -0
- package/src/tileset-3d/format-3d-tiles/tiles-3d-source.ts +254 -21
- package/src/tileset-3d/format-3d-tiles/tileset-3d-traverser.ts +77 -0
- package/src/tileset-3d/format-i3s/i3s-pending-tiles-register.ts +4 -0
- package/src/tileset-3d/format-i3s/i3s-source.ts +119 -18
- package/src/tileset-3d/format-i3s/i3s-tile-manager.ts +4 -0
- package/src/tileset-3d/format-i3s/i3s-tileset-traverser.ts +4 -0
- package/src/tileset-3d/helpers/3d-tiles-options.ts +4 -0
- package/src/tileset-3d/helpers/bounding-volume.ts +5 -55
- package/src/tileset-3d/helpers/frame-state.ts +142 -11
- package/src/tileset-3d/helpers/i3s-lod.ts +22 -8
- package/src/tileset-3d/helpers/tiles-3d-lod.ts +291 -112
- package/src/tileset-3d/helpers/tiles-3d-request-priority.ts +301 -0
- package/src/types.ts +9 -0
- package/src/utils/doubly-linked-list.ts +2 -0
- package/src/utils/managed-array.ts +2 -0
package/src/raster-set.ts
CHANGED
|
@@ -10,57 +10,76 @@ import type {
|
|
|
10
10
|
} from '@loaders.gl/loader-utils';
|
|
11
11
|
|
|
12
12
|
/** Accepted raster request currently retained by {@link RasterSet}. */
|
|
13
|
-
export type RasterSetRequest<
|
|
13
|
+
export type RasterSetRequest<
|
|
14
|
+
DataT extends RasterData = RasterData,
|
|
15
|
+
ParametersT extends object = GetRasterParameters
|
|
16
|
+
> = {
|
|
14
17
|
/** Unique request id assigned by the manager. */
|
|
15
18
|
requestId: number;
|
|
16
19
|
/** Raster request parameters that produced the accepted raster payload. */
|
|
17
|
-
parameters:
|
|
20
|
+
parameters: ParametersT;
|
|
18
21
|
/** Raster retained as the current output. */
|
|
19
22
|
raster: DataT;
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
/** Arguments supplied to {@link RasterSetBaseProps.shouldRefetch}. */
|
|
23
|
-
export type RasterSetShouldRefetchArgs<
|
|
26
|
+
export type RasterSetShouldRefetchArgs<
|
|
27
|
+
DataT extends RasterData = RasterData,
|
|
28
|
+
ParametersT extends object = GetRasterParameters,
|
|
29
|
+
MetadataT extends RasterSourceMetadata = RasterSourceMetadata
|
|
30
|
+
> = {
|
|
24
31
|
/** Current accepted request retained by the raster manager, if any. */
|
|
25
|
-
currentRequest: RasterSetRequest<DataT> | null;
|
|
32
|
+
currentRequest: RasterSetRequest<DataT, ParametersT> | null;
|
|
26
33
|
/** Source metadata resolved by {@link RasterSet.loadMetadata}, if available. */
|
|
27
|
-
metadata:
|
|
34
|
+
metadata: MetadataT | null;
|
|
28
35
|
/** Candidate raster request parameters under evaluation. */
|
|
29
|
-
nextParameters:
|
|
36
|
+
nextParameters: ParametersT;
|
|
30
37
|
};
|
|
31
38
|
|
|
32
39
|
/** Configuration shared by all {@link RasterSet} instances. */
|
|
33
|
-
export type RasterSetBaseProps<
|
|
40
|
+
export type RasterSetBaseProps<
|
|
41
|
+
DataT extends RasterData = RasterData,
|
|
42
|
+
ParametersT extends object = GetRasterParameters,
|
|
43
|
+
MetadataT extends RasterSourceMetadata = RasterSourceMetadata
|
|
44
|
+
> = {
|
|
34
45
|
/** Callback used to load source metadata. */
|
|
35
|
-
getMetadata: () => Promise<
|
|
46
|
+
getMetadata: () => Promise<MetadataT>;
|
|
36
47
|
/** Callback used to load raster data for a viewport-derived request. */
|
|
37
|
-
getRaster: (parameters:
|
|
48
|
+
getRaster: (parameters: ParametersT) => Promise<DataT>;
|
|
38
49
|
/** Debounce interval applied before issuing raster requests. */
|
|
39
50
|
debounceTime?: number;
|
|
40
51
|
/** Optional policy callback that can skip redundant raster requests. */
|
|
41
|
-
shouldRefetch?: (args: RasterSetShouldRefetchArgs<DataT>) => boolean;
|
|
52
|
+
shouldRefetch?: (args: RasterSetShouldRefetchArgs<DataT, ParametersT, MetadataT>) => boolean;
|
|
42
53
|
};
|
|
43
54
|
|
|
44
55
|
/** Options for creating a {@link RasterSet}. */
|
|
45
|
-
export type RasterSetProps<
|
|
56
|
+
export type RasterSetProps<
|
|
57
|
+
DataT extends RasterData = RasterData,
|
|
58
|
+
ParametersT extends object = GetRasterParameters,
|
|
59
|
+
MetadataT extends RasterSourceMetadata = RasterSourceMetadata
|
|
60
|
+
> = Partial<RasterSetBaseProps<DataT, ParametersT, MetadataT>> & {
|
|
46
61
|
/** Optional loaders.gl raster source backing this manager. */
|
|
47
|
-
rasterSource?: RasterSource | null;
|
|
62
|
+
rasterSource?: RasterSource<DataT, ParametersT & GetRasterParameters, MetadataT> | null;
|
|
48
63
|
};
|
|
49
64
|
|
|
50
65
|
/** Subscription callbacks emitted by {@link RasterSet}. */
|
|
51
|
-
export type RasterSetListener<
|
|
66
|
+
export type RasterSetListener<
|
|
67
|
+
DataT extends RasterData = RasterData,
|
|
68
|
+
ParametersT extends object = GetRasterParameters,
|
|
69
|
+
MetadataT extends RasterSourceMetadata = RasterSourceMetadata
|
|
70
|
+
> = {
|
|
52
71
|
/** Fired when metadata/raster loading starts or stops. */
|
|
53
72
|
onLoadingStateChange?: (isLoading: boolean) => void;
|
|
54
73
|
/** Fired when source metadata resolves successfully. */
|
|
55
|
-
onMetadataLoad?: (metadata:
|
|
74
|
+
onMetadataLoad?: (metadata: MetadataT) => void;
|
|
56
75
|
/** Fired when metadata loading fails. */
|
|
57
76
|
onMetadataLoadError?: (error: Error) => void;
|
|
58
77
|
/** Fired when a new raster request is issued. */
|
|
59
|
-
onRasterLoadStart?: (requestId: number, parameters:
|
|
78
|
+
onRasterLoadStart?: (requestId: number, parameters: ParametersT) => void;
|
|
60
79
|
/** Fired when a raster request resolves and becomes current. */
|
|
61
|
-
onRasterLoad?: (request: RasterSetRequest<DataT>) => void;
|
|
80
|
+
onRasterLoad?: (request: RasterSetRequest<DataT, ParametersT>) => void;
|
|
62
81
|
/** Fired when a raster request fails. */
|
|
63
|
-
onRasterLoadError?: (requestId: number, error: Error, parameters:
|
|
82
|
+
onRasterLoadError?: (requestId: number, error: Error, parameters: ParametersT) => void;
|
|
64
83
|
/** Fired when metadata or the current raster changes. */
|
|
65
84
|
onUpdate?: () => void;
|
|
66
85
|
};
|
|
@@ -84,14 +103,24 @@ const DEFAULT_RASTERSET_PROPS: Required<Omit<RasterSetProps, 'rasterSource'>> =
|
|
|
84
103
|
shouldRefetch: () => true
|
|
85
104
|
};
|
|
86
105
|
|
|
87
|
-
/**
|
|
88
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Shared raster request manager used by viewport-driven raster examples and layers.
|
|
108
|
+
*
|
|
109
|
+
* @typeParam DataT Raster payload retained by the manager.
|
|
110
|
+
* @typeParam ParametersT Request parameters accepted by the source.
|
|
111
|
+
* @typeParam MetadataT Metadata returned by the source.
|
|
112
|
+
*/
|
|
113
|
+
export class RasterSet<
|
|
114
|
+
DataT extends RasterData = RasterData,
|
|
115
|
+
ParametersT extends object = GetRasterParameters,
|
|
116
|
+
MetadataT extends RasterSourceMetadata = RasterSourceMetadata
|
|
117
|
+
> {
|
|
89
118
|
/** Cached metadata returned by the backing source, if any. */
|
|
90
|
-
metadata:
|
|
119
|
+
metadata: MetadataT | null = null;
|
|
91
120
|
|
|
92
|
-
private _opts: Required<RasterSetProps<DataT>>;
|
|
93
|
-
private _listeners = new Set<RasterSetListener<DataT>>();
|
|
94
|
-
private _currentRequest: RasterSetRequest<DataT> | null = null;
|
|
121
|
+
private _opts: Required<RasterSetProps<DataT, ParametersT, MetadataT>>;
|
|
122
|
+
private _listeners = new Set<RasterSetListener<DataT, ParametersT, MetadataT>>();
|
|
123
|
+
private _currentRequest: RasterSetRequest<DataT, ParametersT> | null = null;
|
|
95
124
|
private _lastAcceptedRequestId = -1;
|
|
96
125
|
private _nextRequestId = 0;
|
|
97
126
|
private _loadCounter = 0;
|
|
@@ -100,7 +129,7 @@ export class RasterSet<DataT = RasterData> {
|
|
|
100
129
|
private _finalized = false;
|
|
101
130
|
|
|
102
131
|
/** Creates a raster manager from a source or direct callbacks. */
|
|
103
|
-
constructor(opts: RasterSetProps<DataT>) {
|
|
132
|
+
constructor(opts: RasterSetProps<DataT, ParametersT, MetadataT>) {
|
|
104
133
|
this._opts = this._normalizeOptions(opts);
|
|
105
134
|
if (!this._opts.rasterSource && (!opts.getRaster || !opts.getMetadata)) {
|
|
106
135
|
throw new Error(
|
|
@@ -110,11 +139,29 @@ export class RasterSet<DataT = RasterData> {
|
|
|
110
139
|
}
|
|
111
140
|
|
|
112
141
|
/** Convenience factory for wrapping a loaders.gl {@link RasterSource}. */
|
|
113
|
-
static fromRasterSource<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
142
|
+
static fromRasterSource<
|
|
143
|
+
DataT extends RasterData = RasterData,
|
|
144
|
+
ParametersT extends GetRasterParameters = GetRasterParameters,
|
|
145
|
+
MetadataT extends RasterSourceMetadata = RasterSourceMetadata
|
|
146
|
+
>(
|
|
147
|
+
rasterSource: RasterSource<DataT, ParametersT, MetadataT>,
|
|
148
|
+
opts: Omit<
|
|
149
|
+
RasterSetProps<DataT, ParametersT, MetadataT>,
|
|
150
|
+
'rasterSource' | 'getRaster' | 'getMetadata'
|
|
151
|
+
> = {}
|
|
152
|
+
): RasterSet<DataT, ParametersT, MetadataT> {
|
|
153
|
+
return new RasterSet<DataT, ParametersT, MetadataT>({...opts, rasterSource});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Convenience factory for sources whose requests are not viewport-shaped. */
|
|
157
|
+
static fromCallbacks<
|
|
158
|
+
DataT extends RasterData = RasterData,
|
|
159
|
+
ParametersT extends object = GetRasterParameters,
|
|
160
|
+
MetadataT extends RasterSourceMetadata = RasterSourceMetadata
|
|
161
|
+
>(
|
|
162
|
+
opts: RasterSetBaseProps<DataT, ParametersT, MetadataT>
|
|
163
|
+
): RasterSet<DataT, ParametersT, MetadataT> {
|
|
164
|
+
return new RasterSet<DataT, ParametersT, MetadataT>(opts);
|
|
118
165
|
}
|
|
119
166
|
|
|
120
167
|
/** Whether the manager has no requests in flight and a current raster. */
|
|
@@ -128,23 +175,23 @@ export class RasterSet<DataT = RasterData> {
|
|
|
128
175
|
}
|
|
129
176
|
|
|
130
177
|
/** Current accepted request and raster payload, if any. */
|
|
131
|
-
get currentRequest(): RasterSetRequest<DataT> | null {
|
|
178
|
+
get currentRequest(): RasterSetRequest<DataT, ParametersT> | null {
|
|
132
179
|
return this._currentRequest;
|
|
133
180
|
}
|
|
134
181
|
|
|
135
182
|
/** Backing raster source when constructed from one. */
|
|
136
|
-
get rasterSource(): RasterSource | null {
|
|
183
|
+
get rasterSource(): RasterSource<DataT, ParametersT & GetRasterParameters, MetadataT> | null {
|
|
137
184
|
return this._opts.rasterSource;
|
|
138
185
|
}
|
|
139
186
|
|
|
140
187
|
/** Subscribes to metadata and raster lifecycle events. */
|
|
141
|
-
subscribe(listener: RasterSetListener<DataT>): () => void {
|
|
188
|
+
subscribe(listener: RasterSetListener<DataT, ParametersT, MetadataT>): () => void {
|
|
142
189
|
this._listeners.add(listener);
|
|
143
190
|
return () => this._listeners.delete(listener);
|
|
144
191
|
}
|
|
145
192
|
|
|
146
193
|
/** Updates source callbacks or debounce settings, resetting state when the source changes. */
|
|
147
|
-
setOptions(opts: RasterSetProps<DataT>): void {
|
|
194
|
+
setOptions(opts: RasterSetProps<DataT, ParametersT, MetadataT>): void {
|
|
148
195
|
const previousRasterSource = this._opts.rasterSource;
|
|
149
196
|
const nextOptions = this._normalizeOptions({...this._opts, ...opts});
|
|
150
197
|
const sourceChanged =
|
|
@@ -165,7 +212,7 @@ export class RasterSet<DataT = RasterData> {
|
|
|
165
212
|
}
|
|
166
213
|
|
|
167
214
|
/** Loads metadata from the current raster source or callbacks. */
|
|
168
|
-
async loadMetadata(): Promise<
|
|
215
|
+
async loadMetadata(): Promise<MetadataT> {
|
|
169
216
|
this._startLoading();
|
|
170
217
|
try {
|
|
171
218
|
const metadata = await this._opts.getMetadata();
|
|
@@ -192,7 +239,7 @@ export class RasterSet<DataT = RasterData> {
|
|
|
192
239
|
}
|
|
193
240
|
|
|
194
241
|
/** Debounces and issues a new raster request for the supplied parameters. */
|
|
195
|
-
requestRaster(parameters:
|
|
242
|
+
requestRaster(parameters: ParametersT, debounceTime = this._opts.debounceTime): number {
|
|
196
243
|
if (!this.shouldRefetchRaster(parameters)) {
|
|
197
244
|
return this._currentRequest?.requestId ?? -1;
|
|
198
245
|
}
|
|
@@ -213,7 +260,7 @@ export class RasterSet<DataT = RasterData> {
|
|
|
213
260
|
}
|
|
214
261
|
|
|
215
262
|
/** Returns `true` when the supplied parameters warrant a new raster fetch. */
|
|
216
|
-
shouldRefetchRaster(parameters:
|
|
263
|
+
shouldRefetchRaster(parameters: ParametersT): boolean {
|
|
217
264
|
return this._opts.shouldRefetch({
|
|
218
265
|
currentRequest: this._currentRequest,
|
|
219
266
|
metadata: this.metadata,
|
|
@@ -230,7 +277,7 @@ export class RasterSet<DataT = RasterData> {
|
|
|
230
277
|
}
|
|
231
278
|
|
|
232
279
|
/** Loads a raster immediately and accepts it only if it is the newest completed request. */
|
|
233
|
-
private async _loadRaster(requestId: number, parameters:
|
|
280
|
+
private async _loadRaster(requestId: number, parameters: ParametersT): Promise<void> {
|
|
234
281
|
if (this._finalized) {
|
|
235
282
|
return;
|
|
236
283
|
}
|
|
@@ -243,7 +290,9 @@ export class RasterSet<DataT = RasterData> {
|
|
|
243
290
|
try {
|
|
244
291
|
const abortController = new AbortController();
|
|
245
292
|
this._abortController = abortController;
|
|
246
|
-
const raster = await this._opts.getRaster(
|
|
293
|
+
const raster = await this._opts.getRaster(
|
|
294
|
+
withAbortSignal(parameters, abortController.signal)
|
|
295
|
+
);
|
|
247
296
|
if (
|
|
248
297
|
this._finalized ||
|
|
249
298
|
abortController.signal.aborted ||
|
|
@@ -276,7 +325,9 @@ export class RasterSet<DataT = RasterData> {
|
|
|
276
325
|
}
|
|
277
326
|
|
|
278
327
|
/** Resolves current options from either a source or direct callbacks. */
|
|
279
|
-
private _normalizeOptions(
|
|
328
|
+
private _normalizeOptions(
|
|
329
|
+
opts: RasterSetProps<DataT, ParametersT, MetadataT>
|
|
330
|
+
): Required<RasterSetProps<DataT, ParametersT, MetadataT>> {
|
|
280
331
|
const rasterSource = opts.rasterSource || null;
|
|
281
332
|
return {
|
|
282
333
|
...DEFAULT_RASTERSET_PROPS,
|
|
@@ -288,22 +339,24 @@ export class RasterSet<DataT = RasterData> {
|
|
|
288
339
|
if (rasterSource) {
|
|
289
340
|
return rasterSource.getMetadata();
|
|
290
341
|
}
|
|
291
|
-
return DEFAULT_RASTERSET_PROPS.getMetadata()
|
|
342
|
+
return DEFAULT_RASTERSET_PROPS.getMetadata() as Promise<MetadataT>;
|
|
292
343
|
}),
|
|
293
344
|
getRaster:
|
|
294
345
|
opts.getRaster ||
|
|
295
|
-
((parameters:
|
|
346
|
+
((parameters: ParametersT) => {
|
|
296
347
|
if (rasterSource) {
|
|
297
|
-
return rasterSource.getRaster(parameters
|
|
348
|
+
return rasterSource.getRaster(parameters as ParametersT & GetRasterParameters);
|
|
298
349
|
}
|
|
299
|
-
return DEFAULT_RASTERSET_PROPS.getRaster(
|
|
350
|
+
return DEFAULT_RASTERSET_PROPS.getRaster(
|
|
351
|
+
parameters as GetRasterParameters
|
|
352
|
+
) as Promise<DataT>;
|
|
300
353
|
}),
|
|
301
354
|
debounceTime: opts.debounceTime ?? DEFAULT_RASTERSET_PROPS.debounceTime,
|
|
302
355
|
shouldRefetch:
|
|
303
356
|
(opts.shouldRefetch as
|
|
304
|
-
| ((args: RasterSetShouldRefetchArgs<DataT>) => boolean)
|
|
357
|
+
| ((args: RasterSetShouldRefetchArgs<DataT, ParametersT, MetadataT>) => boolean)
|
|
305
358
|
| undefined) ||
|
|
306
|
-
((args: RasterSetShouldRefetchArgs<DataT>) =>
|
|
359
|
+
((args: RasterSetShouldRefetchArgs<DataT, ParametersT, MetadataT>) =>
|
|
307
360
|
DEFAULT_RASTERSET_PROPS.shouldRefetch(args as RasterSetShouldRefetchArgs))
|
|
308
361
|
};
|
|
309
362
|
}
|
|
@@ -357,6 +410,26 @@ export class RasterSet<DataT = RasterData> {
|
|
|
357
410
|
}
|
|
358
411
|
}
|
|
359
412
|
|
|
413
|
+
/** Adds cancellation to a request while preserving its array/prototype shape. */
|
|
414
|
+
function withAbortSignal<ParametersT extends object>(
|
|
415
|
+
parameters: ParametersT,
|
|
416
|
+
signal: AbortSignal
|
|
417
|
+
): ParametersT {
|
|
418
|
+
const request = Array.isArray(parameters)
|
|
419
|
+
? parameters.slice()
|
|
420
|
+
: Object.create(
|
|
421
|
+
Object.getPrototypeOf(parameters),
|
|
422
|
+
Object.getOwnPropertyDescriptors(parameters)
|
|
423
|
+
);
|
|
424
|
+
Object.defineProperty(request, 'signal', {
|
|
425
|
+
configurable: true,
|
|
426
|
+
enumerable: true,
|
|
427
|
+
value: signal,
|
|
428
|
+
writable: true
|
|
429
|
+
});
|
|
430
|
+
return request as ParametersT;
|
|
431
|
+
}
|
|
432
|
+
|
|
360
433
|
/** Normalizes arbitrary thrown values to `Error` instances for raster-set callbacks. */
|
|
361
434
|
function normalizeRasterSetError(error: unknown, message: string): Error {
|
|
362
435
|
if (error instanceof Error) {
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {ReadonlyCRSDefinition} from '@math.gl/crs';
|
|
6
|
+
import {getI3SLinearUnitScale, getI3SVerticalUnitScale} from './i3s-elevation';
|
|
7
|
+
import {createTilesetSpatialReference} from './spatial-types';
|
|
8
|
+
import type {TilesetElevationMode, TilesetSpatialReference} from './spatial-types';
|
|
9
|
+
|
|
10
|
+
/** ArcGIS/I3S spatial reference fields used without depending on the I3S package. */
|
|
11
|
+
type I3SSpatialReferenceLike = {
|
|
12
|
+
wkid?: number;
|
|
13
|
+
latestWkid?: number;
|
|
14
|
+
vcsWkid?: number;
|
|
15
|
+
latestVcsWkid?: number;
|
|
16
|
+
wkt?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** I3S layer fields needed for spatial metadata discovery. */
|
|
20
|
+
type I3SLayerLike = {
|
|
21
|
+
spatialReference?: I3SSpatialReferenceLike;
|
|
22
|
+
fullExtent?: {spatialReference?: I3SSpatialReferenceLike};
|
|
23
|
+
heightModelInfo?: {
|
|
24
|
+
heightModel?: string;
|
|
25
|
+
vertCRS?: ReadonlyCRSDefinition;
|
|
26
|
+
heightUnit?: string;
|
|
27
|
+
};
|
|
28
|
+
ZFactor?: number;
|
|
29
|
+
elevationInfo?: {mode?: string; offset?: number; unit?: string};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/** 3D Tiles metadata schema property used for semantic lookup. */
|
|
33
|
+
type Tiles3DMetadataProperty = {semantic?: string};
|
|
34
|
+
|
|
35
|
+
/** 3D Tiles document fields needed for CRS semantic discovery. */
|
|
36
|
+
type Tiles3DLike = {
|
|
37
|
+
schema?: {
|
|
38
|
+
classes?: Record<string, unknown>;
|
|
39
|
+
};
|
|
40
|
+
schemaUri?: string;
|
|
41
|
+
metadata?: {class?: string; properties?: Record<string, unknown>};
|
|
42
|
+
root?: {boundingVolume?: {region?: unknown}};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Discovers normalized spatial metadata from an I3S scene-layer document.
|
|
47
|
+
*
|
|
48
|
+
* I3S encodes geographic coordinates in longitude/latitude wire order even for authority
|
|
49
|
+
* definitions whose formal axis order differs.
|
|
50
|
+
*
|
|
51
|
+
* @param layer - Parsed I3S layer document.
|
|
52
|
+
* @returns Normalized source spatial metadata.
|
|
53
|
+
*/
|
|
54
|
+
export function getI3SSpatialReference(layer: I3SLayerLike): TilesetSpatialReference {
|
|
55
|
+
const spatialReference = layer.spatialReference || layer.fullExtent?.spatialReference;
|
|
56
|
+
const sourceCrs = getI3SCrsDefinition(spatialReference);
|
|
57
|
+
const verticalCrs =
|
|
58
|
+
layer.heightModelInfo?.vertCRS || getI3SVerticalCrsDefinition(spatialReference);
|
|
59
|
+
const heightModel = layer.heightModelInfo?.heightModel;
|
|
60
|
+
const verticalUnit = layer.heightModelInfo?.heightUnit;
|
|
61
|
+
const verticalUnitScale = getI3SVerticalUnitScale(verticalUnit, layer.ZFactor);
|
|
62
|
+
const heightReference =
|
|
63
|
+
heightModel === 'ellipsoidal'
|
|
64
|
+
? 'ellipsoidal'
|
|
65
|
+
: heightModel === 'gravity_related_height'
|
|
66
|
+
? 'orthometric'
|
|
67
|
+
: 'unknown';
|
|
68
|
+
const sourceIdentifier = getCrsIdentifier(spatialReference);
|
|
69
|
+
const coordinateFrame =
|
|
70
|
+
sourceIdentifier === undefined
|
|
71
|
+
? getWktCoordinateFrame(spatialReference?.wkt)
|
|
72
|
+
: getIdentifierCoordinateFrame(sourceIdentifier);
|
|
73
|
+
const units = getI3SCoordinateUnits(coordinateFrame, verticalUnit, layer.ZFactor);
|
|
74
|
+
const warnings: string[] = [];
|
|
75
|
+
const elevationMode = getI3SElevationMode(layer.elevationInfo?.mode);
|
|
76
|
+
const elevationUnit = layer.elevationInfo ? layer.elevationInfo.unit || 'meter' : undefined;
|
|
77
|
+
const elevationUnitScale = getI3SLinearUnitScale(elevationUnit);
|
|
78
|
+
if (verticalUnitScale === undefined) {
|
|
79
|
+
warnings.push(
|
|
80
|
+
layer.ZFactor !== undefined
|
|
81
|
+
? `I3S ZFactor ${layer.ZFactor} is not a positive finite conversion factor`
|
|
82
|
+
: `Unsupported I3S vertical unit ${verticalUnit}`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (layer.elevationInfo && elevationUnitScale === undefined) {
|
|
86
|
+
warnings.push(`Unsupported I3S elevation unit ${elevationUnit}`);
|
|
87
|
+
}
|
|
88
|
+
if (layer.elevationInfo?.mode && !elevationMode) {
|
|
89
|
+
warnings.push(`Unsupported I3S elevation mode ${layer.elevationInfo.mode}`);
|
|
90
|
+
}
|
|
91
|
+
if (elevationMode && elevationMode !== 'absoluteHeight') {
|
|
92
|
+
warnings.push(
|
|
93
|
+
`I3S elevation mode ${elevationMode} requires a terrain or scene elevation provider`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return createTilesetSpatialReference({
|
|
98
|
+
sourceCrs,
|
|
99
|
+
sourceCrsRepresentation:
|
|
100
|
+
sourceIdentifier !== undefined ? 'identifier' : sourceCrs ? 'wkt' : undefined,
|
|
101
|
+
sourceCrsAlternatives:
|
|
102
|
+
sourceIdentifier !== undefined && spatialReference?.wkt
|
|
103
|
+
? [{definition: spatialReference.wkt, representation: 'wkt'}]
|
|
104
|
+
: undefined,
|
|
105
|
+
verticalCrs,
|
|
106
|
+
units,
|
|
107
|
+
verticalUnitScale: verticalUnitScale ?? Number.NaN,
|
|
108
|
+
heightReference,
|
|
109
|
+
elevationMode,
|
|
110
|
+
elevationOffset: layer.elevationInfo?.offset,
|
|
111
|
+
elevationUnit,
|
|
112
|
+
elevationUnitScale:
|
|
113
|
+
layer.elevationInfo?.mode && !elevationMode
|
|
114
|
+
? Number.NaN
|
|
115
|
+
: (elevationUnitScale ?? (layer.elevationInfo ? Number.NaN : 1)),
|
|
116
|
+
coordinateFrame,
|
|
117
|
+
axisOrder: sourceCrs ? 'xyz' : 'unknown',
|
|
118
|
+
provenance: sourceCrs ? 'metadata' : 'unknown',
|
|
119
|
+
warnings
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Return per-component I3S units only when their coordinate association is unambiguous. */
|
|
124
|
+
function getI3SCoordinateUnits(
|
|
125
|
+
coordinateFrame: TilesetSpatialReference['coordinateFrame'],
|
|
126
|
+
verticalUnit: string | undefined,
|
|
127
|
+
zFactor: number | undefined
|
|
128
|
+
): readonly string[] | undefined {
|
|
129
|
+
if (coordinateFrame === 'geocentric') {
|
|
130
|
+
return ['meter', 'meter', 'meter'];
|
|
131
|
+
}
|
|
132
|
+
if (coordinateFrame === 'geographic' && (verticalUnit || zFactor === undefined)) {
|
|
133
|
+
return ['degree', 'degree', verticalUnit || 'meter'];
|
|
134
|
+
}
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Return a supported I3S elevation mode without widening the public descriptor. */
|
|
139
|
+
function getI3SElevationMode(mode: string | undefined): TilesetElevationMode | undefined {
|
|
140
|
+
switch (mode) {
|
|
141
|
+
case 'absoluteHeight':
|
|
142
|
+
case 'onTheGround':
|
|
143
|
+
case 'relativeToGround':
|
|
144
|
+
case 'relativeToScene':
|
|
145
|
+
return mode;
|
|
146
|
+
default:
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Discovers the 3D Tiles geocentric CRS and coordinate epoch from structured metadata semantics.
|
|
153
|
+
*
|
|
154
|
+
* The method intentionally does not infer ECEF from coordinate magnitude. A root `region`
|
|
155
|
+
* establishes the format's global ellipsoidal frame, while local tilesets without an explicit
|
|
156
|
+
* semantic remain unknown.
|
|
157
|
+
*
|
|
158
|
+
* @param tileset - Parsed 3D Tiles tileset document.
|
|
159
|
+
* @returns Normalized source spatial metadata.
|
|
160
|
+
*/
|
|
161
|
+
export function get3DTilesSpatialReference(tileset: Tiles3DLike): TilesetSpatialReference {
|
|
162
|
+
const geocentricCrs = getTilesetSemanticValue(tileset, 'TILESET_CRS_GEOCENTRIC');
|
|
163
|
+
const coordinateEpoch = getTilesetSemanticValue(tileset, 'TILESET_CRS_COORDINATE_EPOCH');
|
|
164
|
+
const warnings: string[] = [];
|
|
165
|
+
|
|
166
|
+
let sourceCrs: ReadonlyCRSDefinition | undefined;
|
|
167
|
+
let provenance: TilesetSpatialReference['provenance'] = 'unknown';
|
|
168
|
+
let sourceCrsState: 'explicit' | 'default' | 'unknown' | 'absent' | undefined;
|
|
169
|
+
if (typeof geocentricCrs === 'string' && geocentricCrs.toUpperCase() !== 'UNKNOWN') {
|
|
170
|
+
sourceCrs = geocentricCrs;
|
|
171
|
+
provenance = 'metadata';
|
|
172
|
+
sourceCrsState = 'explicit';
|
|
173
|
+
} else if (geocentricCrs !== undefined) {
|
|
174
|
+
warnings.push('3D Tiles geocentric CRS is explicitly unknown');
|
|
175
|
+
provenance = 'metadata';
|
|
176
|
+
sourceCrsState = 'unknown';
|
|
177
|
+
} else if (tileset.root?.boundingVolume?.region) {
|
|
178
|
+
sourceCrs = 'EPSG:4978';
|
|
179
|
+
provenance = 'format-default';
|
|
180
|
+
sourceCrsState = 'default';
|
|
181
|
+
} else if (tileset.schemaUri && !tileset.schema) {
|
|
182
|
+
warnings.push(
|
|
183
|
+
'External 3D Tiles metadata schema must be loaded before CRS semantics can resolve'
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const epoch = parseCoordinateEpoch(coordinateEpoch);
|
|
188
|
+
if (coordinateEpoch !== undefined && epoch === undefined) {
|
|
189
|
+
warnings.push('3D Tiles coordinate epoch is not a finite decimal year');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return createTilesetSpatialReference({
|
|
193
|
+
sourceCrs,
|
|
194
|
+
sourceCrsState,
|
|
195
|
+
sourceCrsRepresentation: sourceCrs ? 'identifier' : undefined,
|
|
196
|
+
coordinateEpoch: epoch,
|
|
197
|
+
heightReference: sourceCrs ? 'ellipsoidal' : 'unknown',
|
|
198
|
+
coordinateFrame: sourceCrs ? 'geocentric' : 'unknown',
|
|
199
|
+
axisOrder: sourceCrs ? 'xyz' : 'unknown',
|
|
200
|
+
provenance,
|
|
201
|
+
warnings
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Parse the 3D Tiles decimal-year string while tolerating legacy numeric producer output. */
|
|
206
|
+
function parseCoordinateEpoch(value: unknown): number | undefined {
|
|
207
|
+
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
if (typeof value === 'string' && !value.trim()) {
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
const epoch = Number(value);
|
|
214
|
+
return Number.isFinite(epoch) ? epoch : undefined;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Return an I3S horizontal CRS definition, preferring current WKID aliases over legacy values. */
|
|
218
|
+
function getI3SCrsDefinition(
|
|
219
|
+
spatialReference?: I3SSpatialReferenceLike
|
|
220
|
+
): ReadonlyCRSDefinition | undefined {
|
|
221
|
+
const identifier = getCrsIdentifier(spatialReference);
|
|
222
|
+
if (identifier !== undefined) {
|
|
223
|
+
return `EPSG:${identifier}`;
|
|
224
|
+
}
|
|
225
|
+
return spatialReference?.wkt;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Return an I3S vertical CRS definition. */
|
|
229
|
+
function getI3SVerticalCrsDefinition(
|
|
230
|
+
spatialReference?: I3SSpatialReferenceLike
|
|
231
|
+
): ReadonlyCRSDefinition | undefined {
|
|
232
|
+
const identifier = spatialReference?.latestVcsWkid ?? spatialReference?.vcsWkid;
|
|
233
|
+
return identifier === undefined ? undefined : `EPSG:${identifier}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Return the preferred horizontal WKID. */
|
|
237
|
+
function getCrsIdentifier(spatialReference?: I3SSpatialReferenceLike): number | undefined {
|
|
238
|
+
return spatialReference?.latestWkid ?? spatialReference?.wkid;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Classify common EPSG identifiers used by I3S into their coordinate frames. */
|
|
242
|
+
function getIdentifierCoordinateFrame(
|
|
243
|
+
identifier: number
|
|
244
|
+
): TilesetSpatialReference['coordinateFrame'] {
|
|
245
|
+
if (identifier === 4978) {
|
|
246
|
+
return 'geocentric';
|
|
247
|
+
}
|
|
248
|
+
if (identifier === 4326 || identifier === 4490 || identifier === 4979) {
|
|
249
|
+
return 'geographic';
|
|
250
|
+
}
|
|
251
|
+
return 'projected';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Classify a WKT root coordinate system without guessing when the declaration is ambiguous.
|
|
256
|
+
*
|
|
257
|
+
* WKT2 uses `GEODCRS` for both geographic and geocentric systems, so its `CS` declaration is
|
|
258
|
+
* inspected before assigning a frame.
|
|
259
|
+
*/
|
|
260
|
+
function getWktCoordinateFrame(wkt?: string): TilesetSpatialReference['coordinateFrame'] {
|
|
261
|
+
if (!wkt) {
|
|
262
|
+
return 'unknown';
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const normalizedWkt = wkt.trim().toUpperCase();
|
|
266
|
+
const rootKeyword = normalizedWkt.match(/^([A-Z][A-Z0-9_]*)\s*[\[(]/)?.[1];
|
|
267
|
+
if (rootKeyword === 'GEOCCS') {
|
|
268
|
+
return 'geocentric';
|
|
269
|
+
}
|
|
270
|
+
if (
|
|
271
|
+
rootKeyword === 'GEOGCS' ||
|
|
272
|
+
rootKeyword === 'GEOGRAPHICCRS' ||
|
|
273
|
+
rootKeyword === 'GEOGRAPHIC2DCRS' ||
|
|
274
|
+
rootKeyword === 'GEOGRAPHIC3DCRS'
|
|
275
|
+
) {
|
|
276
|
+
return 'geographic';
|
|
277
|
+
}
|
|
278
|
+
if (rootKeyword === 'PROJCS' || rootKeyword === 'PROJCRS' || rootKeyword === 'PROJECTEDCRS') {
|
|
279
|
+
return 'projected';
|
|
280
|
+
}
|
|
281
|
+
if (rootKeyword === 'GEODCRS' || rootKeyword === 'GEODETICCRS') {
|
|
282
|
+
if (/\bCS\s*[\[(]\s*CARTESIAN\s*,\s*3\b/.test(normalizedWkt)) {
|
|
283
|
+
return 'geocentric';
|
|
284
|
+
}
|
|
285
|
+
if (/\bCS\s*[\[(]\s*ELLIPSOIDAL\s*,\s*[23]\b/.test(normalizedWkt)) {
|
|
286
|
+
return 'geographic';
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return 'unknown';
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** Resolve a tileset-wide structured metadata property by its standard semantic. */
|
|
293
|
+
function getTilesetSemanticValue(tileset: Tiles3DLike, semantic: string): unknown {
|
|
294
|
+
const classIdentifier = tileset.metadata?.class;
|
|
295
|
+
if (!classIdentifier) {
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
const classDefinition = tileset.schema?.classes?.[classIdentifier] as
|
|
299
|
+
| {properties?: Record<string, Tiles3DMetadataProperty>}
|
|
300
|
+
| undefined;
|
|
301
|
+
const propertyDefinitions = classDefinition?.properties;
|
|
302
|
+
const propertyValues = tileset.metadata?.properties;
|
|
303
|
+
for (const [propertyIdentifier, propertyDefinition] of Object.entries(
|
|
304
|
+
propertyDefinitions || {}
|
|
305
|
+
)) {
|
|
306
|
+
if (propertyDefinition.semantic === semantic) {
|
|
307
|
+
return propertyValues?.[propertyIdentifier];
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return undefined;
|
|
311
|
+
}
|