@reearth/core 0.0.7-alpha.62 → 0.0.7-alpha.63
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/core.js +62227 -67254
- package/dist/core.umd.cjs +682 -662
- package/dist/{index-CUJ6HGQn.js → index-DqGWVPtz.js} +907 -1021
- package/dist/index.d.ts +62 -56
- package/package.json +1 -1
- package/src/Map/Sketch/sketchMachine.ts +473 -395
- package/src/Map/types/customProvider.ts +32 -0
- package/src/Map/types/index.ts +3 -0
- package/src/Map/types/viewerProperty.ts +2 -1
- package/src/Visualizer/index.tsx +4 -0
- package/src/engines/Cesium/Feature/Tileset/hooks.ts +50 -22
- package/src/engines/Cesium/Feature/context.ts +2 -0
- package/src/engines/Cesium/Feature/index.tsx +1 -0
- package/src/engines/Cesium/core/Globe/index.tsx +1 -5
- package/src/engines/Cesium/core/Globe/useTerrainProviderPromise.ts +18 -16
- package/src/engines/Cesium/core/Imagery.test.ts +79 -44
- package/src/engines/Cesium/core/Imagery.tsx +171 -53
- package/src/engines/Cesium/core/presets.ts +106 -28
- package/src/engines/Cesium/hooks/useOverrideGlobeShader/useOverrideGlobeShader.ts +17 -17
- package/src/engines/Cesium/hooks.ts +14 -4
- package/src/engines/Cesium/index.tsx +13 -1
- package/src/mantle/types/index.ts +2 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Color,
|
|
3
|
+
ImageryLayer as CesiumImageryLayer,
|
|
3
4
|
ImageryProvider,
|
|
4
5
|
TextureMagnificationFilter,
|
|
5
6
|
TextureMinificationFilter,
|
|
7
|
+
UrlTemplateImageryProvider,
|
|
6
8
|
} from "cesium";
|
|
7
9
|
import { isEqual } from "lodash-es";
|
|
8
|
-
import { useCallback, useMemo, useRef,
|
|
9
|
-
import {
|
|
10
|
+
import { useCallback, useMemo, useRef, useEffect } from "react";
|
|
11
|
+
import { useCesium } from "resium";
|
|
12
|
+
|
|
13
|
+
import type { CustomProviderConfig } from "../../../Map/types/customProvider";
|
|
10
14
|
|
|
11
15
|
import { isValidPresetTileType, PresetTileType, tiles as tilePresets } from "./presets";
|
|
12
16
|
|
|
@@ -22,6 +26,7 @@ export type Tile = {
|
|
|
22
26
|
id: string;
|
|
23
27
|
url?: string;
|
|
24
28
|
type?: string;
|
|
29
|
+
cesiumIonAssetId?: number;
|
|
25
30
|
opacity?: number;
|
|
26
31
|
zoomLevel?: number[];
|
|
27
32
|
zoomLevelForURL?: number[];
|
|
@@ -31,64 +36,127 @@ export type Tile = {
|
|
|
31
36
|
export type Props = {
|
|
32
37
|
tiles?: Tile[];
|
|
33
38
|
cesiumIonAccessToken?: string;
|
|
39
|
+
customProvider?: CustomProviderConfig;
|
|
34
40
|
onTilesChange?: () => void;
|
|
35
41
|
};
|
|
36
42
|
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
// NOTE: This component intentionally bypasses Resium's declarative <ImageryLayer />.
|
|
44
|
+
// Resium wraps provider creation in queueMicrotask; under React 18 Strict Mode the effect
|
|
45
|
+
// cleanup runs before that microtask resolves, so the layer reference is undefined at cleanup
|
|
46
|
+
// time and old layers are never removed — they accumulate silently behind new ones.
|
|
47
|
+
// Direct imageryLayerCollection management with a `cancelled` flag is the only safe fix.
|
|
48
|
+
export default function ImageryLayers({
|
|
49
|
+
tiles,
|
|
50
|
+
cesiumIonAccessToken,
|
|
51
|
+
customProvider,
|
|
52
|
+
onTilesChange,
|
|
53
|
+
}: Props) {
|
|
54
|
+
const { imageryLayerCollection, scene } = useCesium();
|
|
55
|
+
|
|
56
|
+
const { providers } = useImageryProviders({
|
|
39
57
|
tiles,
|
|
40
58
|
cesiumIonAccessToken,
|
|
59
|
+
customProvider,
|
|
41
60
|
presets: tilePresets,
|
|
42
61
|
});
|
|
43
62
|
|
|
44
|
-
// force rerendering all layers when any provider is updated
|
|
45
|
-
// since Resium does not sort layers according to ImageryLayer component order
|
|
46
|
-
const [counter, setCounter] = useState(0);
|
|
47
|
-
useLayoutEffect(() => {
|
|
48
|
-
if (updated) setCounter(c => c + 1);
|
|
49
|
-
}, [providers, updated]);
|
|
50
|
-
|
|
51
63
|
useEffect(() => {
|
|
64
|
+
if (!imageryLayerCollection || !scene) return;
|
|
65
|
+
|
|
66
|
+
let cancelled = false;
|
|
67
|
+
const addedLayers: CesiumImageryLayer[] = [];
|
|
68
|
+
// Track layers by their intended index to maintain order with async loading
|
|
69
|
+
const layersByIndex: (CesiumImageryLayer | null)[] = new Array(tiles?.length || 0).fill(null);
|
|
70
|
+
|
|
71
|
+
const reorderLayers = () => {
|
|
72
|
+
if (cancelled || scene.isDestroyed()) return;
|
|
73
|
+
|
|
74
|
+
// Move each layer to its correct position based on layersByIndex
|
|
75
|
+
layersByIndex.forEach((layer, targetIndex) => {
|
|
76
|
+
if (!layer) return;
|
|
77
|
+
|
|
78
|
+
const currentIndex = imageryLayerCollection.indexOf(layer);
|
|
79
|
+
if (currentIndex === -1) return; // Layer not in collection
|
|
80
|
+
|
|
81
|
+
// Calculate where this layer should be: count non-null layers before it
|
|
82
|
+
const desiredIndex = layersByIndex.slice(0, targetIndex).filter(l => l !== null).length;
|
|
83
|
+
|
|
84
|
+
if (currentIndex !== desiredIndex) {
|
|
85
|
+
// Move layer to correct position
|
|
86
|
+
imageryLayerCollection.remove(layer, false); // Don't destroy
|
|
87
|
+
imageryLayerCollection.add(layer, desiredIndex);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
scene.requestRender();
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
tiles?.forEach(({ id, zoomLevel, opacity, heatmap }, i) => {
|
|
95
|
+
const providerOrPromise = providers[id]?.[3];
|
|
96
|
+
if (!providerOrPromise) return;
|
|
97
|
+
|
|
98
|
+
const doAdd = (provider: ImageryProvider) => {
|
|
99
|
+
if (!provider || cancelled || scene.isDestroyed()) return;
|
|
100
|
+
const layer = new CesiumImageryLayer(provider, {
|
|
101
|
+
minimumTerrainLevel: zoomLevel?.[0],
|
|
102
|
+
maximumTerrainLevel: zoomLevel?.[1],
|
|
103
|
+
alpha: opacity,
|
|
104
|
+
colorToAlpha: heatmap ? Color.WHITE : undefined,
|
|
105
|
+
colorToAlphaThreshold: heatmap ? 1 : undefined,
|
|
106
|
+
magnificationFilter: heatmap ? TextureMagnificationFilter.LINEAR : undefined,
|
|
107
|
+
minificationFilter: heatmap ? TextureMinificationFilter.NEAREST : undefined,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Always append to avoid index out of bounds
|
|
111
|
+
imageryLayerCollection.add(layer);
|
|
112
|
+
layersByIndex[i] = layer;
|
|
113
|
+
addedLayers.push(layer);
|
|
114
|
+
|
|
115
|
+
// Reorder all layers after each addition
|
|
116
|
+
reorderLayers();
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
if (providerOrPromise instanceof Promise) {
|
|
120
|
+
providerOrPromise.then(doAdd).catch(err => console.error("Failed to load imagery provider:", err));
|
|
121
|
+
} else {
|
|
122
|
+
doAdd(providerOrPromise);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
scene.requestRender();
|
|
52
127
|
onTilesChange?.();
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<ImageryLayer
|
|
66
|
-
key={`${id}_${i}_${counter}`}
|
|
67
|
-
imageryProvider={provider}
|
|
68
|
-
minimumTerrainLevel={zoomLevel?.[0]}
|
|
69
|
-
maximumTerrainLevel={zoomLevel?.[1]}
|
|
70
|
-
alpha={opacity}
|
|
71
|
-
index={i}
|
|
72
|
-
colorToAlpha={heatmap ? Color.WHITE : undefined}
|
|
73
|
-
colorToAlphaThreshold={heatmap ? 1 : undefined}
|
|
74
|
-
magnificationFilter={heatmap ? TextureMagnificationFilter.LINEAR : undefined}
|
|
75
|
-
minificationFilter={heatmap ? TextureMinificationFilter.NEAREST : undefined}
|
|
76
|
-
/>
|
|
77
|
-
) : null,
|
|
78
|
-
)}
|
|
79
|
-
</>
|
|
80
|
-
);
|
|
128
|
+
|
|
129
|
+
return () => {
|
|
130
|
+
cancelled = true;
|
|
131
|
+
for (const layer of addedLayers) {
|
|
132
|
+
if (!scene.isDestroyed() && imageryLayerCollection.contains(layer)) {
|
|
133
|
+
imageryLayerCollection.remove(layer);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}, [providers, tiles, imageryLayerCollection, scene, onTilesChange]);
|
|
138
|
+
|
|
139
|
+
return null;
|
|
81
140
|
}
|
|
82
141
|
|
|
83
|
-
type Providers = {
|
|
142
|
+
type Providers = {
|
|
143
|
+
[id: string]: [
|
|
144
|
+
string | undefined,
|
|
145
|
+
string | undefined,
|
|
146
|
+
number | undefined,
|
|
147
|
+
Promise<ImageryProvider> | ImageryProvider,
|
|
148
|
+
];
|
|
149
|
+
};
|
|
84
150
|
|
|
85
151
|
export function useImageryProviders({
|
|
86
152
|
tiles = [],
|
|
87
153
|
cesiumIonAccessToken,
|
|
154
|
+
customProvider,
|
|
88
155
|
presets,
|
|
89
156
|
}: {
|
|
90
157
|
tiles?: Tile[];
|
|
91
158
|
cesiumIonAccessToken?: string;
|
|
159
|
+
customProvider?: CustomProviderConfig;
|
|
92
160
|
presets: {
|
|
93
161
|
[K in PresetTileType]: (opts?: {
|
|
94
162
|
url?: string;
|
|
@@ -99,17 +167,34 @@ export function useImageryProviders({
|
|
|
99
167
|
};
|
|
100
168
|
}): { providers: Providers; updated: boolean } {
|
|
101
169
|
const newTile = useCallback(
|
|
102
|
-
(t: Tile, ciat?: string) =>
|
|
103
|
-
|
|
170
|
+
(t: Tile, ciat?: string, tp?: CustomProviderConfig) => {
|
|
171
|
+
const opts = {
|
|
104
172
|
url: t.url,
|
|
105
173
|
cesiumIonAccessToken: ciat,
|
|
174
|
+
cesiumIonAssetId: t.cesiumIonAssetId,
|
|
106
175
|
heatmap: t.heatmap,
|
|
107
|
-
|
|
108
|
-
}
|
|
176
|
+
tile_zoomLevel: t.zoomLevelForURL,
|
|
177
|
+
};
|
|
178
|
+
if (isValidPresetTileType(t.type)) {
|
|
179
|
+
return presets[t.type](opts);
|
|
180
|
+
}
|
|
181
|
+
// Dynamic: check customProvider.imagery.providers for a matching id
|
|
182
|
+
const customEntry = tp?.imagery?.providers?.find(p => p.id === t.type);
|
|
183
|
+
if (customEntry) {
|
|
184
|
+
return new UrlTemplateImageryProvider({
|
|
185
|
+
url: customEntry.url,
|
|
186
|
+
credit: customEntry.credit,
|
|
187
|
+
maximumLevel: customEntry.maximumLevel,
|
|
188
|
+
minimumLevel: customEntry.minimumLevel,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return presets["open_street_map"](opts);
|
|
192
|
+
},
|
|
109
193
|
[presets],
|
|
110
194
|
);
|
|
111
195
|
|
|
112
196
|
const prevCesiumIonAccessToken = useRef(cesiumIonAccessToken);
|
|
197
|
+
const prevCustomProvider = useRef(customProvider);
|
|
113
198
|
const tileKeys = tiles.map(t => t.id).join(",");
|
|
114
199
|
const prevTileKeys = useRef(tileKeys);
|
|
115
200
|
const prevProviders = useRef<Providers>({});
|
|
@@ -123,9 +208,10 @@ export function useImageryProviders({
|
|
|
123
208
|
);
|
|
124
209
|
const prevZoomLevels = useRef(zoomLevels);
|
|
125
210
|
|
|
126
|
-
// Manage
|
|
211
|
+
// Manage CustomProviders so that CustomProvider does not need to be recreated each time tiles are updated.
|
|
127
212
|
const { providers, updated } = useMemo(() => {
|
|
128
213
|
const isCesiumAccessTokenUpdated = prevCesiumIonAccessToken.current !== cesiumIonAccessToken;
|
|
214
|
+
const isTileProviderUpdated = prevCustomProvider.current !== customProvider;
|
|
129
215
|
const prevProvidersKeys = Object.keys(prevProviders.current);
|
|
130
216
|
const added = tiles.map(t => t.id).filter(t => t && !prevProvidersKeys.includes(t));
|
|
131
217
|
|
|
@@ -137,7 +223,8 @@ export function useImageryProviders({
|
|
|
137
223
|
added: added.includes(k),
|
|
138
224
|
prevType: v?.[0],
|
|
139
225
|
prevUrl: v?.[1],
|
|
140
|
-
|
|
226
|
+
prevIonAssetId: v?.[2],
|
|
227
|
+
prevProvider: v?.[3],
|
|
141
228
|
tile: tiles.find(t => t.id === k),
|
|
142
229
|
}));
|
|
143
230
|
|
|
@@ -149,6 +236,7 @@ export function useImageryProviders({
|
|
|
149
236
|
added,
|
|
150
237
|
prevType,
|
|
151
238
|
prevUrl,
|
|
239
|
+
prevIonAssetId,
|
|
152
240
|
prevProvider,
|
|
153
241
|
tile,
|
|
154
242
|
}):
|
|
@@ -157,6 +245,7 @@ export function useImageryProviders({
|
|
|
157
245
|
[
|
|
158
246
|
string | undefined,
|
|
159
247
|
string | undefined,
|
|
248
|
+
number | undefined,
|
|
160
249
|
Promise<ImageryProvider> | ImageryProvider | null | undefined,
|
|
161
250
|
],
|
|
162
251
|
]
|
|
@@ -168,30 +257,59 @@ export function useImageryProviders({
|
|
|
168
257
|
added ||
|
|
169
258
|
prevType !== tile.type ||
|
|
170
259
|
prevUrl !== tile.url ||
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
260
|
+
prevIonAssetId !== tile.cesiumIonAssetId ||
|
|
261
|
+
isTileProviderUpdated ||
|
|
262
|
+
(isCesiumAccessTokenUpdated &&
|
|
263
|
+
(tile.type?.startsWith("cesium_ion") ||
|
|
264
|
+
tile.type === "default" ||
|
|
265
|
+
tile.type === "default_road" ||
|
|
266
|
+
tile.type === "default_label" ||
|
|
267
|
+
tile.type === "black_marble"))
|
|
268
|
+
? [
|
|
269
|
+
tile.type,
|
|
270
|
+
tile.url,
|
|
271
|
+
tile.cesiumIonAssetId,
|
|
272
|
+
newTile(tile, cesiumIonAccessToken, customProvider),
|
|
273
|
+
]
|
|
274
|
+
: [prevType, prevUrl, prevIonAssetId, prevProvider],
|
|
174
275
|
],
|
|
175
276
|
)
|
|
176
277
|
.filter(
|
|
177
|
-
(
|
|
178
|
-
|
|
278
|
+
(
|
|
279
|
+
e,
|
|
280
|
+
): e is [
|
|
281
|
+
string,
|
|
282
|
+
[
|
|
283
|
+
string | undefined,
|
|
284
|
+
string | undefined,
|
|
285
|
+
number | undefined,
|
|
286
|
+
Promise<ImageryProvider> | ImageryProvider,
|
|
287
|
+
],
|
|
288
|
+
] => !!e?.[1][3],
|
|
179
289
|
),
|
|
180
290
|
);
|
|
181
291
|
|
|
182
292
|
const updated =
|
|
183
293
|
!!added.length ||
|
|
184
294
|
!!isCesiumAccessTokenUpdated ||
|
|
295
|
+
!!isTileProviderUpdated ||
|
|
185
296
|
!isEqual(prevTileKeys.current, tileKeys) ||
|
|
186
297
|
!isEqual(prevZoomLevels.current, zoomLevels) ||
|
|
187
|
-
rawProviders.some(
|
|
298
|
+
rawProviders.some(
|
|
299
|
+
p =>
|
|
300
|
+
p.tile &&
|
|
301
|
+
(p.prevType !== p.tile.type ||
|
|
302
|
+
p.prevUrl !== p.tile.url ||
|
|
303
|
+
p.prevIonAssetId !== p.tile.cesiumIonAssetId),
|
|
304
|
+
);
|
|
188
305
|
|
|
189
306
|
prevTileKeys.current = tileKeys;
|
|
190
307
|
prevZoomLevels.current = zoomLevels;
|
|
191
308
|
prevCesiumIonAccessToken.current = cesiumIonAccessToken;
|
|
309
|
+
prevCustomProvider.current = customProvider;
|
|
192
310
|
|
|
193
311
|
return { providers, updated };
|
|
194
|
-
}, [cesiumIonAccessToken, tiles, tileKeys, newTile, zoomLevels]);
|
|
312
|
+
}, [cesiumIonAccessToken, customProvider, tiles, tileKeys, newTile, zoomLevels]);
|
|
195
313
|
|
|
196
314
|
prevProviders.current = providers;
|
|
197
315
|
return { providers, updated };
|
|
@@ -11,13 +11,27 @@ import {
|
|
|
11
11
|
import { JapanGSIOptimalBVmapLabelImageryProvider } from "./labels/JapanGSIOptimalBVmapVectorMapLabel/JapanGSIOptimalBVmapLabelImageryProvider";
|
|
12
12
|
|
|
13
13
|
const PRESET_TILE_TYPES = [
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
|
|
14
|
+
// Dynamic Cesium Ion asset — asset ID supplied per-tile via cesiumIonAssetId field
|
|
15
|
+
"cesium_ion",
|
|
16
|
+
|
|
17
|
+
// Public presets — always available, no auth required
|
|
17
18
|
"open_street_map",
|
|
18
|
-
"black_marble",
|
|
19
19
|
"japan_gsi_standard",
|
|
20
|
+
"stamen_watercolor",
|
|
21
|
+
"carto_light",
|
|
20
22
|
"url",
|
|
23
|
+
|
|
24
|
+
// Cesium Ion presets — require user-provided Ion token (scene.default.ion)
|
|
25
|
+
"cesium_ion_default",
|
|
26
|
+
"cesium_ion_labelled",
|
|
27
|
+
"cesium_ion_road",
|
|
28
|
+
"cesium_ion_earth_at_night",
|
|
29
|
+
|
|
30
|
+
// Legacy aliases — kept for backward compatibility with existing apps
|
|
31
|
+
"default", // → cesium_ion_default
|
|
32
|
+
"default_road", // → cesium_ion_road
|
|
33
|
+
"default_label", // → cesium_ion_labelled
|
|
34
|
+
"black_marble", // → cesium_ion_earth_at_night
|
|
21
35
|
];
|
|
22
36
|
|
|
23
37
|
export type PresetTileType = (typeof PRESET_TILE_TYPES)[number];
|
|
@@ -26,35 +40,61 @@ export const isValidPresetTileType = (type: string | undefined): type is PresetT
|
|
|
26
40
|
return PRESET_TILE_TYPES.includes(type as PresetTileType);
|
|
27
41
|
};
|
|
28
42
|
|
|
43
|
+
export type TileOptions = {
|
|
44
|
+
url?: string;
|
|
45
|
+
cesiumIonAccessToken?: string;
|
|
46
|
+
cesiumIonAssetId?: number | string;
|
|
47
|
+
heatmap?: boolean;
|
|
48
|
+
tile_zoomLevel?: number[];
|
|
49
|
+
};
|
|
50
|
+
|
|
29
51
|
export const tiles = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
IonImageryProvider.fromAssetId(
|
|
40
|
-
accessToken: cesiumIonAccessToken,
|
|
41
|
-
}).catch(
|
|
52
|
+
// --- Dynamic Cesium Ion asset ---
|
|
53
|
+
// Uses per-tile cesiumIonAssetId; requires cesiumIonAccessToken.
|
|
54
|
+
cesium_ion: (opts?: TileOptions) => {
|
|
55
|
+
if (!opts?.cesiumIonAssetId) return null;
|
|
56
|
+
const NumberAssetId = parseInt(String(opts.cesiumIonAssetId), 10);
|
|
57
|
+
if (isNaN(NumberAssetId)) {
|
|
58
|
+
console.warn(`Invalid cesiumIonAssetId: ${opts.cesiumIonAssetId}`);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return IonImageryProvider.fromAssetId(NumberAssetId, {
|
|
62
|
+
accessToken: opts?.cesiumIonAccessToken,
|
|
63
|
+
}).catch(err => {
|
|
64
|
+
console.error(err);
|
|
65
|
+
return undefined as unknown as ImageryProvider;
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
// --- Public presets ---
|
|
42
70
|
open_street_map: () =>
|
|
43
71
|
new OpenStreetMapImageryProvider({
|
|
44
72
|
url: "https://tile.openstreetmap.org",
|
|
45
73
|
credit: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
|
46
74
|
}),
|
|
47
|
-
|
|
48
|
-
IonImageryProvider.fromAssetId(3812, {
|
|
49
|
-
accessToken: cesiumIonAccessToken,
|
|
50
|
-
}).catch(console.error),
|
|
75
|
+
|
|
51
76
|
japan_gsi_standard: () =>
|
|
52
77
|
new OpenStreetMapImageryProvider({
|
|
53
78
|
url: "https://cyberjapandata.gsi.go.jp/xyz/std/",
|
|
54
79
|
credit:
|
|
55
80
|
"<a href='https://maps.gsi.go.jp/development/ichiran.html'>国土地理院</a>, Shoreline data is derived from: United States. National Imagery and Mapping Agency. \"Vector Map Level 0 (VMAP0).\" Bethesda, MD: Denver, CO: The Agency; USGS Information Services, 1997.",
|
|
56
81
|
}),
|
|
57
|
-
|
|
82
|
+
|
|
83
|
+
stamen_watercolor: () =>
|
|
84
|
+
new UrlTemplateImageryProvider({
|
|
85
|
+
url: "https://watercolormaps.collection.cooperhewitt.org/tile/watercolor/{z}/{x}/{y}.jpg",
|
|
86
|
+
credit: "Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.",
|
|
87
|
+
maximumLevel: 16,
|
|
88
|
+
}),
|
|
89
|
+
|
|
90
|
+
carto_light: () =>
|
|
91
|
+
new UrlTemplateImageryProvider({
|
|
92
|
+
url: "https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
|
|
93
|
+
credit:
|
|
94
|
+
"© <a href='https://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors, © <a href='https://carto.com/attributions'>CARTO</a>",
|
|
95
|
+
}),
|
|
96
|
+
|
|
97
|
+
url: ({ url, heatmap, tile_zoomLevel }: TileOptions = {}) =>
|
|
58
98
|
url
|
|
59
99
|
? new UrlTemplateImageryProvider({
|
|
60
100
|
url,
|
|
@@ -63,15 +103,53 @@ export const tiles = {
|
|
|
63
103
|
maximumLevel: tile_zoomLevel?.[1],
|
|
64
104
|
})
|
|
65
105
|
: null,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
106
|
+
|
|
107
|
+
// --- Cesium Ion presets ---
|
|
108
|
+
// Require the user to configure a Cesium Ion access token in their scene (scene.default.ion).
|
|
109
|
+
cesium_ion_default: (opts?: TileOptions) =>
|
|
110
|
+
IonImageryProvider.fromAssetId(IonWorldImageryStyle.AERIAL, {
|
|
111
|
+
accessToken: opts?.cesiumIonAccessToken,
|
|
112
|
+
}).catch(err => {
|
|
113
|
+
console.error(err);
|
|
114
|
+
return undefined as unknown as ImageryProvider;
|
|
115
|
+
}),
|
|
116
|
+
|
|
117
|
+
cesium_ion_labelled: (opts?: TileOptions) =>
|
|
118
|
+
IonImageryProvider.fromAssetId(IonWorldImageryStyle.AERIAL_WITH_LABELS, {
|
|
119
|
+
accessToken: opts?.cesiumIonAccessToken,
|
|
120
|
+
}).catch(err => {
|
|
121
|
+
console.error(err);
|
|
122
|
+
return undefined as unknown as ImageryProvider;
|
|
123
|
+
}),
|
|
124
|
+
|
|
125
|
+
cesium_ion_road: (opts?: TileOptions) =>
|
|
126
|
+
IonImageryProvider.fromAssetId(IonWorldImageryStyle.ROAD, {
|
|
127
|
+
accessToken: opts?.cesiumIonAccessToken,
|
|
128
|
+
}).catch(err => {
|
|
129
|
+
console.error(err);
|
|
130
|
+
return undefined as unknown as ImageryProvider;
|
|
131
|
+
}),
|
|
132
|
+
|
|
133
|
+
cesium_ion_earth_at_night: (opts?: TileOptions) =>
|
|
134
|
+
IonImageryProvider.fromAssetId(3812, {
|
|
135
|
+
accessToken: opts?.cesiumIonAccessToken,
|
|
136
|
+
}).catch(err => {
|
|
137
|
+
console.error(err);
|
|
138
|
+
return undefined as unknown as ImageryProvider;
|
|
139
|
+
}),
|
|
140
|
+
// --- Legacy aliases ---
|
|
141
|
+
} as any as {
|
|
142
|
+
[K in PresetTileType]: (opts?: TileOptions) => Promise<ImageryProvider> | ImageryProvider | null;
|
|
73
143
|
};
|
|
74
144
|
|
|
145
|
+
// Populate legacy aliases after object literal to allow forward references.
|
|
146
|
+
Object.assign(tiles, {
|
|
147
|
+
default: tiles.cesium_ion_default,
|
|
148
|
+
default_road: tiles.cesium_ion_road,
|
|
149
|
+
default_label: tiles.cesium_ion_labelled,
|
|
150
|
+
black_marble: tiles.cesium_ion_earth_at_night,
|
|
151
|
+
});
|
|
152
|
+
|
|
75
153
|
export const labelTiles = {
|
|
76
154
|
japan_gsi_optimal_bvmap: (params: {
|
|
77
155
|
url: string;
|
|
@@ -42,23 +42,23 @@ const defaultMatcher = new StringMatcher()
|
|
|
42
42
|
#endif
|
|
43
43
|
vec4 color = computeDayColor(initialColor`,
|
|
44
44
|
);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
45
|
+
// Note: Commented out erase() call as it's not needed for Cesium 1.118.x
|
|
46
|
+
// The replace() above already handles the material code modification
|
|
47
|
+
// .erase([
|
|
48
|
+
// "#ifdef APPLY_MATERIAL",
|
|
49
|
+
// "czm_materialInput materialInput;",
|
|
50
|
+
// "materialInput.st = v_textureCoordinates.st;",
|
|
51
|
+
// "materialInput.normalEC = normalize(v_normalEC);",
|
|
52
|
+
// "materialInput.positionToEyeEC = -v_positionEC;",
|
|
53
|
+
// "materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, normalize(v_normalEC));",
|
|
54
|
+
// "materialInput.slope = v_slope;",
|
|
55
|
+
// "materialInput.height = v_height;",
|
|
56
|
+
// "materialInput.aspect = v_aspect;",
|
|
57
|
+
// "czm_material material = czm_getMaterial(materialInput);",
|
|
58
|
+
// "vec4 materialColor = vec4(material.diffuse, material.alpha);",
|
|
59
|
+
// "color = alphaBlend(materialColor, color);",
|
|
60
|
+
// "#endif",
|
|
61
|
+
// ]);
|
|
62
62
|
|
|
63
63
|
function makeGlobeShadersDirty(globe: Globe): void {
|
|
64
64
|
// Invoke the internal makeShadersDirty() by setting a material to globe to
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Entity,
|
|
3
3
|
Cesium3DTileFeature,
|
|
4
|
-
Ion,
|
|
5
4
|
Cesium3DTileset,
|
|
6
5
|
JulianDate,
|
|
7
6
|
Cesium3DTilePointFeature,
|
|
@@ -28,6 +27,7 @@ import { e2eAccessToken, setE2ECesiumViewer } from "../../e2eConfig";
|
|
|
28
27
|
import { ComputedFeature, DataType, SelectedFeatureInfo, LatLng, Camera } from "../../mantle";
|
|
29
28
|
import {
|
|
30
29
|
Credits,
|
|
30
|
+
CustomProviderConfig,
|
|
31
31
|
LayerLoadEvent,
|
|
32
32
|
LayerSelectWithRectEnd,
|
|
33
33
|
LayerSelectWithRectMove,
|
|
@@ -70,6 +70,7 @@ export default ({
|
|
|
70
70
|
selectedLayerId,
|
|
71
71
|
selectionReason,
|
|
72
72
|
meta,
|
|
73
|
+
customProvider,
|
|
73
74
|
layersRef,
|
|
74
75
|
featureFlags,
|
|
75
76
|
timelineManagerRef,
|
|
@@ -102,6 +103,7 @@ export default ({
|
|
|
102
103
|
layersRef?: RefObject<LayersRef | null>;
|
|
103
104
|
selectionReason?: LayerSelectionReason;
|
|
104
105
|
meta?: Record<string, unknown>;
|
|
106
|
+
customProvider?: CustomProviderConfig;
|
|
105
107
|
featureFlags: number;
|
|
106
108
|
timelineManagerRef?: TimelineManagerRef;
|
|
107
109
|
isLayerDraggable?: boolean;
|
|
@@ -137,7 +139,7 @@ export default ({
|
|
|
137
139
|
const cesiumIonAccessToken =
|
|
138
140
|
typeof meta?.cesiumIonAccessToken === "string" && meta.cesiumIonAccessToken
|
|
139
141
|
? meta.cesiumIonAccessToken
|
|
140
|
-
:
|
|
142
|
+
: undefined;
|
|
141
143
|
|
|
142
144
|
// expose ref
|
|
143
145
|
const engineAPI = useEngineRef(ref, cesium);
|
|
@@ -674,6 +676,7 @@ export default ({
|
|
|
674
676
|
() => ({
|
|
675
677
|
selectionReason,
|
|
676
678
|
timelineManagerRef,
|
|
679
|
+
customProvider,
|
|
677
680
|
flyTo: engineAPI.flyTo,
|
|
678
681
|
getCamera: engineAPI.getCamera,
|
|
679
682
|
onLayerEdit,
|
|
@@ -688,11 +691,12 @@ export default ({
|
|
|
688
691
|
}),
|
|
689
692
|
[
|
|
690
693
|
selectionReason,
|
|
694
|
+
timelineManagerRef,
|
|
695
|
+
customProvider,
|
|
691
696
|
engineAPI,
|
|
692
697
|
onLayerEdit,
|
|
693
698
|
onLayerVisibility,
|
|
694
699
|
onLayerLoad,
|
|
695
|
-
timelineManagerRef,
|
|
696
700
|
updateCredits,
|
|
697
701
|
],
|
|
698
702
|
);
|
|
@@ -730,7 +734,13 @@ export default ({
|
|
|
730
734
|
|
|
731
735
|
useLayerDragDrop({ cesium, onLayerDrag, onLayerDrop, isLayerDraggable });
|
|
732
736
|
|
|
733
|
-
useExplicitRender({
|
|
737
|
+
useExplicitRender({
|
|
738
|
+
cesium,
|
|
739
|
+
requestingRenderMode,
|
|
740
|
+
isLayerDragging,
|
|
741
|
+
shouldRender,
|
|
742
|
+
property,
|
|
743
|
+
});
|
|
734
744
|
|
|
735
745
|
const {
|
|
736
746
|
cameraViewBoundaries,
|
|
@@ -47,6 +47,7 @@ const Cesium: React.ForwardRefRenderFunction<EngineRef, EngineProps> = (
|
|
|
47
47
|
shouldRender,
|
|
48
48
|
layerSelectionReason,
|
|
49
49
|
meta,
|
|
50
|
+
customProvider,
|
|
50
51
|
displayCredits,
|
|
51
52
|
layersRef,
|
|
52
53
|
featureFlags,
|
|
@@ -96,6 +97,7 @@ const Cesium: React.ForwardRefRenderFunction<EngineRef, EngineProps> = (
|
|
|
96
97
|
selectedLayerId,
|
|
97
98
|
selectionReason: layerSelectionReason,
|
|
98
99
|
meta,
|
|
100
|
+
customProvider,
|
|
99
101
|
layersRef,
|
|
100
102
|
featureFlags,
|
|
101
103
|
timelineManagerRef,
|
|
@@ -167,6 +169,7 @@ const Cesium: React.ForwardRefRenderFunction<EngineRef, EngineProps> = (
|
|
|
167
169
|
<ImageryLayers
|
|
168
170
|
tiles={property?.tiles}
|
|
169
171
|
cesiumIonAccessToken={cesiumIonAccessToken}
|
|
172
|
+
customProvider={customProvider}
|
|
170
173
|
onTilesChange={handleTilesChange}
|
|
171
174
|
/>
|
|
172
175
|
<LabelImageryLayers tileLabels={property?.tileLabels} />
|
|
@@ -293,5 +296,14 @@ export const engine: Engine = {
|
|
|
293
296
|
featureComponent: Feature,
|
|
294
297
|
clusterComponent: Cluster,
|
|
295
298
|
sketchComponent: Sketch,
|
|
296
|
-
delegatedDataTypes: [
|
|
299
|
+
delegatedDataTypes: [
|
|
300
|
+
"czml",
|
|
301
|
+
"wms",
|
|
302
|
+
"mvt",
|
|
303
|
+
"3dtiles",
|
|
304
|
+
"osm-buildings",
|
|
305
|
+
"reearth-buildings",
|
|
306
|
+
"google-photorealistic",
|
|
307
|
+
"kml",
|
|
308
|
+
],
|
|
297
309
|
};
|
|
@@ -76,6 +76,7 @@ export type Data = {
|
|
|
76
76
|
updateInterval?: number; // milliseconds
|
|
77
77
|
parameters?: Record<string, any>;
|
|
78
78
|
idProperty?: string;
|
|
79
|
+
provider?: string;
|
|
79
80
|
serviceTokens?: {
|
|
80
81
|
googleMapApiKey?: string;
|
|
81
82
|
};
|
|
@@ -107,6 +108,7 @@ export type DataType =
|
|
|
107
108
|
| "geojson"
|
|
108
109
|
| "3dtiles"
|
|
109
110
|
| "osm-buildings"
|
|
111
|
+
| "reearth-buildings"
|
|
110
112
|
| "google-photorealistic"
|
|
111
113
|
| "czml"
|
|
112
114
|
| "csv"
|