cesiumjs-anywidget 0.2.4__tar.gz → 0.4.0__tar.gz
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.
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/.gitignore +1 -1
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/PKG-INFO +1 -1
- cesiumjs_anywidget-0.4.0/fix_tests.py +62 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/pyproject.toml +1 -1
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/src/cesiumjs_anywidget/index.js +432 -57
- cesiumjs_anywidget-0.4.0/src/cesiumjs_anywidget/widget.py +1087 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/uv.lock +1 -1
- cesiumjs_anywidget-0.2.4/src/cesiumjs_anywidget/widget.py +0 -376
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/DEVELOPMENT.md +0 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/LICENSE +0 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/Makefile +0 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/README.md +0 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/TROUBLESHOOTING.md +0 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/build.js +0 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/package.json +0 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/src/cesiumjs_anywidget/__init__.py +0 -0
- {cesiumjs_anywidget-0.2.4 → cesiumjs_anywidget-0.4.0}/src/cesiumjs_anywidget/styles.css +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cesiumjs-anywidget
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: A Jupyter widget for CesiumJS 3D globe visualization using anywidget
|
|
5
5
|
Project-URL: Homepage, https://github.com/Alex-PLACET/cesiumjs_anywidget
|
|
6
6
|
Project-URL: Repository, https://github.com/Alex-PLACET/cesiumjs_anywidget
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
# Read the test file
|
|
4
|
+
with open('tests/test_methods.py', 'r') as f:
|
|
5
|
+
content = f.read()
|
|
6
|
+
|
|
7
|
+
# Fix the assertions
|
|
8
|
+
# Change: assert widget_instance.geojson_data == geojson
|
|
9
|
+
# To: assert widget_instance.geojson_data == [geojson]
|
|
10
|
+
content = re.sub(
|
|
11
|
+
r'assert widget_instance\.geojson_data == (sample_geojson|geojson|new_geojson)([^\[])',
|
|
12
|
+
r'assert widget_instance.geojson_data == [\1]\2',
|
|
13
|
+
content
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Fix: assert len(widget_instance.geojson_data["features"]) == 2
|
|
17
|
+
# To: assert len(widget_instance.geojson_data[0]["features"]) == 2
|
|
18
|
+
content = re.sub(
|
|
19
|
+
r'widget_instance\.geojson_data\["features"\]',
|
|
20
|
+
r'widget_instance.geojson_data[0]["features"]',
|
|
21
|
+
content
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Write back
|
|
25
|
+
with open('tests/test_methods.py', 'w') as f:
|
|
26
|
+
f.write(content)
|
|
27
|
+
|
|
28
|
+
print("Fixed test_methods.py")
|
|
29
|
+
|
|
30
|
+
# Also fix test_widget.py
|
|
31
|
+
with open('tests/test_widget.py', 'r') as f:
|
|
32
|
+
content = f.read()
|
|
33
|
+
|
|
34
|
+
# Change: assert widget_instance.geojson_data is None
|
|
35
|
+
# To: assert widget_instance.geojson_data == []
|
|
36
|
+
content = re.sub(
|
|
37
|
+
r'assert widget_instance\.geojson_data is None',
|
|
38
|
+
r'assert widget_instance.geojson_data == []',
|
|
39
|
+
content
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
with open('tests/test_widget.py', 'w') as f:
|
|
43
|
+
f.write(content)
|
|
44
|
+
|
|
45
|
+
print("Fixed test_widget.py")
|
|
46
|
+
|
|
47
|
+
# Fix test_integration.py
|
|
48
|
+
with open('tests/test_integration.py', 'r') as f:
|
|
49
|
+
content = f.read()
|
|
50
|
+
|
|
51
|
+
# Change: assert widget_instance.geojson_data == geojson
|
|
52
|
+
# To: assert widget_instance.geojson_data == [geojson]
|
|
53
|
+
content = re.sub(
|
|
54
|
+
r'assert widget_instance\.geojson_data == (empty_geojson|geojson)([^\[])',
|
|
55
|
+
r'assert widget_instance.geojson_data == [\1]\2',
|
|
56
|
+
content
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
with open('tests/test_integration.py', 'w') as f:
|
|
60
|
+
f.write(content)
|
|
61
|
+
|
|
62
|
+
print("Fixed test_integration.py")
|
|
@@ -85,64 +85,318 @@ function setupViewerListeners(viewer, model, container, Cesium) {
|
|
|
85
85
|
return;
|
|
86
86
|
viewer.animation.container.style.visibility = model.get("show_animation") ? "visible" : "hidden";
|
|
87
87
|
});
|
|
88
|
+
model.on("change:atmosphere_settings", () => {
|
|
89
|
+
if (!viewer || !viewer.scene || !viewer.scene.atmosphere)
|
|
90
|
+
return;
|
|
91
|
+
const settings = model.get("atmosphere_settings");
|
|
92
|
+
if (!settings || Object.keys(settings).length === 0)
|
|
93
|
+
return;
|
|
94
|
+
const atmosphere = viewer.scene.atmosphere;
|
|
95
|
+
if (settings.brightnessShift !== void 0) {
|
|
96
|
+
atmosphere.brightnessShift = settings.brightnessShift;
|
|
97
|
+
}
|
|
98
|
+
if (settings.hueShift !== void 0) {
|
|
99
|
+
atmosphere.hueShift = settings.hueShift;
|
|
100
|
+
}
|
|
101
|
+
if (settings.saturationShift !== void 0) {
|
|
102
|
+
atmosphere.saturationShift = settings.saturationShift;
|
|
103
|
+
}
|
|
104
|
+
if (settings.lightIntensity !== void 0) {
|
|
105
|
+
atmosphere.lightIntensity = settings.lightIntensity;
|
|
106
|
+
}
|
|
107
|
+
if (settings.rayleighCoefficient !== void 0 && Array.isArray(settings.rayleighCoefficient) && settings.rayleighCoefficient.length === 3) {
|
|
108
|
+
atmosphere.rayleighCoefficient = new Cesium.Cartesian3(
|
|
109
|
+
settings.rayleighCoefficient[0],
|
|
110
|
+
settings.rayleighCoefficient[1],
|
|
111
|
+
settings.rayleighCoefficient[2]
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
if (settings.rayleighScaleHeight !== void 0) {
|
|
115
|
+
atmosphere.rayleighScaleHeight = settings.rayleighScaleHeight;
|
|
116
|
+
}
|
|
117
|
+
if (settings.mieCoefficient !== void 0 && Array.isArray(settings.mieCoefficient) && settings.mieCoefficient.length === 3) {
|
|
118
|
+
atmosphere.mieCoefficient = new Cesium.Cartesian3(
|
|
119
|
+
settings.mieCoefficient[0],
|
|
120
|
+
settings.mieCoefficient[1],
|
|
121
|
+
settings.mieCoefficient[2]
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
if (settings.mieScaleHeight !== void 0) {
|
|
125
|
+
atmosphere.mieScaleHeight = settings.mieScaleHeight;
|
|
126
|
+
}
|
|
127
|
+
if (settings.mieAnisotropy !== void 0) {
|
|
128
|
+
atmosphere.mieAnisotropy = settings.mieAnisotropy;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
model.on("change:sky_atmosphere_settings", () => {
|
|
132
|
+
if (!viewer || !viewer.scene || !viewer.scene.skyAtmosphere)
|
|
133
|
+
return;
|
|
134
|
+
const settings = model.get("sky_atmosphere_settings");
|
|
135
|
+
if (!settings || Object.keys(settings).length === 0)
|
|
136
|
+
return;
|
|
137
|
+
const skyAtmosphere = viewer.scene.skyAtmosphere;
|
|
138
|
+
if (settings.show !== void 0) {
|
|
139
|
+
skyAtmosphere.show = settings.show;
|
|
140
|
+
}
|
|
141
|
+
if (settings.brightnessShift !== void 0) {
|
|
142
|
+
skyAtmosphere.brightnessShift = settings.brightnessShift;
|
|
143
|
+
}
|
|
144
|
+
if (settings.hueShift !== void 0) {
|
|
145
|
+
skyAtmosphere.hueShift = settings.hueShift;
|
|
146
|
+
}
|
|
147
|
+
if (settings.saturationShift !== void 0) {
|
|
148
|
+
skyAtmosphere.saturationShift = settings.saturationShift;
|
|
149
|
+
}
|
|
150
|
+
if (settings.atmosphereLightIntensity !== void 0) {
|
|
151
|
+
skyAtmosphere.atmosphereLightIntensity = settings.atmosphereLightIntensity;
|
|
152
|
+
}
|
|
153
|
+
if (settings.atmosphereRayleighCoefficient !== void 0 && Array.isArray(settings.atmosphereRayleighCoefficient) && settings.atmosphereRayleighCoefficient.length === 3) {
|
|
154
|
+
skyAtmosphere.atmosphereRayleighCoefficient = new Cesium.Cartesian3(
|
|
155
|
+
settings.atmosphereRayleighCoefficient[0],
|
|
156
|
+
settings.atmosphereRayleighCoefficient[1],
|
|
157
|
+
settings.atmosphereRayleighCoefficient[2]
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
if (settings.atmosphereRayleighScaleHeight !== void 0) {
|
|
161
|
+
skyAtmosphere.atmosphereRayleighScaleHeight = settings.atmosphereRayleighScaleHeight;
|
|
162
|
+
}
|
|
163
|
+
if (settings.atmosphereMieCoefficient !== void 0 && Array.isArray(settings.atmosphereMieCoefficient) && settings.atmosphereMieCoefficient.length === 3) {
|
|
164
|
+
skyAtmosphere.atmosphereMieCoefficient = new Cesium.Cartesian3(
|
|
165
|
+
settings.atmosphereMieCoefficient[0],
|
|
166
|
+
settings.atmosphereMieCoefficient[1],
|
|
167
|
+
settings.atmosphereMieCoefficient[2]
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
if (settings.atmosphereMieScaleHeight !== void 0) {
|
|
171
|
+
skyAtmosphere.atmosphereMieScaleHeight = settings.atmosphereMieScaleHeight;
|
|
172
|
+
}
|
|
173
|
+
if (settings.atmosphereMieAnisotropy !== void 0) {
|
|
174
|
+
skyAtmosphere.atmosphereMieAnisotropy = settings.atmosphereMieAnisotropy;
|
|
175
|
+
}
|
|
176
|
+
if (settings.perFragmentAtmosphere !== void 0) {
|
|
177
|
+
skyAtmosphere.perFragmentAtmosphere = settings.perFragmentAtmosphere;
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
model.on("change:skybox_settings", () => {
|
|
181
|
+
if (!viewer || !viewer.scene || !viewer.scene.skyBox)
|
|
182
|
+
return;
|
|
183
|
+
const settings = model.get("skybox_settings");
|
|
184
|
+
if (!settings || Object.keys(settings).length === 0)
|
|
185
|
+
return;
|
|
186
|
+
const skyBox = viewer.scene.skyBox;
|
|
187
|
+
if (settings.show !== void 0) {
|
|
188
|
+
skyBox.show = settings.show;
|
|
189
|
+
}
|
|
190
|
+
if (settings.sources !== void 0 && settings.sources !== null) {
|
|
191
|
+
const sources = settings.sources;
|
|
192
|
+
if (sources.positiveX && sources.negativeX && sources.positiveY && sources.negativeY && sources.positiveZ && sources.negativeZ) {
|
|
193
|
+
viewer.scene.skyBox = new Cesium.SkyBox({
|
|
194
|
+
sources: {
|
|
195
|
+
positiveX: sources.positiveX,
|
|
196
|
+
negativeX: sources.negativeX,
|
|
197
|
+
positiveY: sources.positiveY,
|
|
198
|
+
negativeY: sources.negativeY,
|
|
199
|
+
positiveZ: sources.positiveZ,
|
|
200
|
+
negativeZ: sources.negativeZ
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
if (settings.show !== void 0) {
|
|
204
|
+
viewer.scene.skyBox.show = settings.show;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
function getCameraState() {
|
|
210
|
+
const cartographic = viewer.camera.positionCartographic;
|
|
211
|
+
return {
|
|
212
|
+
latitude: Cesium.Math.toDegrees(cartographic.latitude),
|
|
213
|
+
longitude: Cesium.Math.toDegrees(cartographic.longitude),
|
|
214
|
+
altitude: cartographic.height,
|
|
215
|
+
heading: Cesium.Math.toDegrees(viewer.camera.heading),
|
|
216
|
+
pitch: Cesium.Math.toDegrees(viewer.camera.pitch),
|
|
217
|
+
roll: Cesium.Math.toDegrees(viewer.camera.roll)
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function getClockState() {
|
|
221
|
+
if (!viewer.clock)
|
|
222
|
+
return null;
|
|
223
|
+
return {
|
|
224
|
+
current_time: Cesium.JulianDate.toIso8601(viewer.clock.currentTime),
|
|
225
|
+
multiplier: viewer.clock.multiplier,
|
|
226
|
+
is_animating: viewer.clock.shouldAnimate
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function sendInteractionEvent(type, additionalData = {}) {
|
|
230
|
+
const event = {
|
|
231
|
+
type,
|
|
232
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
233
|
+
camera: getCameraState(),
|
|
234
|
+
clock: getClockState(),
|
|
235
|
+
...additionalData
|
|
236
|
+
};
|
|
237
|
+
console.log("[CesiumWidget] Interaction event:", type, event);
|
|
238
|
+
model.set("interaction_event", event);
|
|
239
|
+
model.save_changes();
|
|
240
|
+
}
|
|
241
|
+
const camera = viewer.camera;
|
|
242
|
+
camera.moveEnd.addEventListener(() => {
|
|
243
|
+
sendInteractionEvent("camera_move");
|
|
244
|
+
});
|
|
245
|
+
const scene = viewer.scene;
|
|
246
|
+
const handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
|
|
247
|
+
handler.setInputAction((click) => {
|
|
248
|
+
const pickedData = {};
|
|
249
|
+
const ray = viewer.camera.getPickRay(click.position);
|
|
250
|
+
const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
|
|
251
|
+
if (cartesian) {
|
|
252
|
+
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
|
|
253
|
+
pickedData.picked_position = {
|
|
254
|
+
latitude: Cesium.Math.toDegrees(cartographic.latitude),
|
|
255
|
+
longitude: Cesium.Math.toDegrees(cartographic.longitude),
|
|
256
|
+
altitude: cartographic.height
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
const pickedObject = viewer.scene.pick(click.position);
|
|
260
|
+
if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
|
|
261
|
+
const entity = pickedObject.id;
|
|
262
|
+
pickedData.picked_entity = {
|
|
263
|
+
id: entity.id,
|
|
264
|
+
name: entity.name || null
|
|
265
|
+
};
|
|
266
|
+
if (entity.properties) {
|
|
267
|
+
const props = {};
|
|
268
|
+
const propertyNames = entity.properties.propertyNames;
|
|
269
|
+
if (propertyNames && propertyNames.length > 0) {
|
|
270
|
+
propertyNames.forEach((name) => {
|
|
271
|
+
try {
|
|
272
|
+
props[name] = entity.properties[name].getValue(viewer.clock.currentTime);
|
|
273
|
+
} catch (e) {
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
if (Object.keys(props).length > 0) {
|
|
277
|
+
pickedData.picked_entity.properties = props;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
sendInteractionEvent("left_click", pickedData);
|
|
283
|
+
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
|
284
|
+
handler.setInputAction((click) => {
|
|
285
|
+
const pickedData = {};
|
|
286
|
+
const ray = viewer.camera.getPickRay(click.position);
|
|
287
|
+
const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
|
|
288
|
+
if (cartesian) {
|
|
289
|
+
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
|
|
290
|
+
pickedData.picked_position = {
|
|
291
|
+
latitude: Cesium.Math.toDegrees(cartographic.latitude),
|
|
292
|
+
longitude: Cesium.Math.toDegrees(cartographic.longitude),
|
|
293
|
+
altitude: cartographic.height
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
sendInteractionEvent("right_click", pickedData);
|
|
297
|
+
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
|
|
298
|
+
if (viewer.timeline) {
|
|
299
|
+
let timelineScrubbing = false;
|
|
300
|
+
let scrubTimeout = null;
|
|
301
|
+
viewer.clock.onTick.addEventListener(() => {
|
|
302
|
+
if (viewer.timeline) {
|
|
303
|
+
if (scrubTimeout) {
|
|
304
|
+
clearTimeout(scrubTimeout);
|
|
305
|
+
}
|
|
306
|
+
scrubTimeout = setTimeout(() => {
|
|
307
|
+
if (timelineScrubbing) {
|
|
308
|
+
timelineScrubbing = false;
|
|
309
|
+
sendInteractionEvent("timeline_scrub");
|
|
310
|
+
}
|
|
311
|
+
}, 500);
|
|
312
|
+
timelineScrubbing = true;
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
88
316
|
}
|
|
89
317
|
function setupGeoJSONLoader(viewer, model, Cesium) {
|
|
90
|
-
let
|
|
318
|
+
let geojsonDataSources = [];
|
|
91
319
|
model.on("change:geojson_data", async () => {
|
|
92
|
-
if (!viewer)
|
|
320
|
+
if (!viewer || !viewer.dataSources)
|
|
93
321
|
return;
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
viewer.dataSources
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
322
|
+
const geojsonDataArray = model.get("geojson_data");
|
|
323
|
+
geojsonDataSources.forEach((dataSource) => {
|
|
324
|
+
if (viewer && viewer.dataSources) {
|
|
325
|
+
viewer.dataSources.remove(dataSource);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
geojsonDataSources = [];
|
|
329
|
+
if (geojsonDataArray && Array.isArray(geojsonDataArray)) {
|
|
330
|
+
for (const geojsonData of geojsonDataArray) {
|
|
331
|
+
try {
|
|
332
|
+
const dataSource = await Cesium.GeoJsonDataSource.load(geojsonData, {
|
|
333
|
+
stroke: Cesium.Color.HOTPINK,
|
|
334
|
+
fill: Cesium.Color.PINK.withAlpha(0.5),
|
|
335
|
+
strokeWidth: 3
|
|
336
|
+
});
|
|
337
|
+
if (viewer && viewer.dataSources) {
|
|
338
|
+
viewer.dataSources.add(dataSource);
|
|
339
|
+
geojsonDataSources.push(dataSource);
|
|
340
|
+
}
|
|
341
|
+
} catch (error) {
|
|
342
|
+
console.error("Error loading GeoJSON:", error);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (geojsonDataSources.length > 0 && viewer && viewer.flyTo) {
|
|
346
|
+
viewer.flyTo(geojsonDataSources[0]);
|
|
110
347
|
}
|
|
111
348
|
}
|
|
112
349
|
});
|
|
113
350
|
return {
|
|
114
351
|
destroy: () => {
|
|
115
|
-
|
|
116
|
-
viewer
|
|
117
|
-
|
|
352
|
+
geojsonDataSources.forEach((dataSource) => {
|
|
353
|
+
if (viewer) {
|
|
354
|
+
viewer.dataSources.remove(dataSource);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
geojsonDataSources = [];
|
|
118
358
|
}
|
|
119
359
|
};
|
|
120
360
|
}
|
|
121
361
|
function setupCZMLLoader(viewer, model, Cesium) {
|
|
122
|
-
let
|
|
362
|
+
let czmlDataSources = [];
|
|
123
363
|
model.on("change:czml_data", async () => {
|
|
124
|
-
if (!viewer)
|
|
364
|
+
if (!viewer || !viewer.dataSources)
|
|
125
365
|
return;
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
viewer.dataSources
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
366
|
+
const czmlDataArray = model.get("czml_data");
|
|
367
|
+
czmlDataSources.forEach((dataSource) => {
|
|
368
|
+
if (viewer && viewer.dataSources) {
|
|
369
|
+
viewer.dataSources.remove(dataSource);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
czmlDataSources = [];
|
|
373
|
+
if (czmlDataArray && Array.isArray(czmlDataArray)) {
|
|
374
|
+
for (const czmlData of czmlDataArray) {
|
|
375
|
+
if (Array.isArray(czmlData) && czmlData.length > 0) {
|
|
376
|
+
try {
|
|
377
|
+
const dataSource = await Cesium.CzmlDataSource.load(czmlData);
|
|
378
|
+
if (viewer && viewer.dataSources) {
|
|
379
|
+
viewer.dataSources.add(dataSource);
|
|
380
|
+
czmlDataSources.push(dataSource);
|
|
381
|
+
}
|
|
382
|
+
} catch (error) {
|
|
383
|
+
console.error("Error loading CZML:", error);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (czmlDataSources.length > 0 && viewer && viewer.flyTo) {
|
|
388
|
+
viewer.flyTo(czmlDataSources[0]);
|
|
138
389
|
}
|
|
139
390
|
}
|
|
140
391
|
});
|
|
141
392
|
return {
|
|
142
393
|
destroy: () => {
|
|
143
|
-
|
|
144
|
-
viewer
|
|
145
|
-
|
|
394
|
+
czmlDataSources.forEach((dataSource) => {
|
|
395
|
+
if (viewer) {
|
|
396
|
+
viewer.dataSources.remove(dataSource);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
czmlDataSources = [];
|
|
146
400
|
}
|
|
147
401
|
};
|
|
148
402
|
}
|
|
@@ -194,6 +448,99 @@ function initializeCameraSync(viewer, model) {
|
|
|
194
448
|
model.on("change:heading", updateCameraFromModel);
|
|
195
449
|
model.on("change:pitch", updateCameraFromModel);
|
|
196
450
|
model.on("change:roll", updateCameraFromModel);
|
|
451
|
+
model.on("change:camera_command", () => {
|
|
452
|
+
const command = model.get("camera_command");
|
|
453
|
+
if (!command || !command.command || !command.timestamp)
|
|
454
|
+
return;
|
|
455
|
+
const cmd = command.command;
|
|
456
|
+
try {
|
|
457
|
+
switch (cmd) {
|
|
458
|
+
case "flyTo":
|
|
459
|
+
viewer.camera.flyTo({
|
|
460
|
+
destination: Cesium.Cartesian3.fromDegrees(
|
|
461
|
+
command.longitude,
|
|
462
|
+
command.latitude,
|
|
463
|
+
command.altitude
|
|
464
|
+
),
|
|
465
|
+
orientation: {
|
|
466
|
+
heading: Cesium.Math.toRadians(command.heading || 0),
|
|
467
|
+
pitch: Cesium.Math.toRadians(command.pitch || -15),
|
|
468
|
+
roll: Cesium.Math.toRadians(command.roll || 0)
|
|
469
|
+
},
|
|
470
|
+
duration: command.duration || 3
|
|
471
|
+
});
|
|
472
|
+
break;
|
|
473
|
+
case "setView":
|
|
474
|
+
viewer.camera.setView({
|
|
475
|
+
destination: Cesium.Cartesian3.fromDegrees(
|
|
476
|
+
command.longitude,
|
|
477
|
+
command.latitude,
|
|
478
|
+
command.altitude
|
|
479
|
+
),
|
|
480
|
+
orientation: {
|
|
481
|
+
heading: Cesium.Math.toRadians(command.heading || 0),
|
|
482
|
+
pitch: Cesium.Math.toRadians(command.pitch || -15),
|
|
483
|
+
roll: Cesium.Math.toRadians(command.roll || 0)
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
break;
|
|
487
|
+
case "lookAt":
|
|
488
|
+
const target = Cesium.Cartesian3.fromDegrees(
|
|
489
|
+
command.targetLongitude,
|
|
490
|
+
command.targetLatitude,
|
|
491
|
+
command.targetAltitude || 0
|
|
492
|
+
);
|
|
493
|
+
const offset = new Cesium.HeadingPitchRange(
|
|
494
|
+
Cesium.Math.toRadians(command.offsetHeading || 0),
|
|
495
|
+
Cesium.Math.toRadians(command.offsetPitch || -45),
|
|
496
|
+
command.offsetRange || 1e3
|
|
497
|
+
);
|
|
498
|
+
viewer.camera.lookAt(target, offset);
|
|
499
|
+
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
|
|
500
|
+
break;
|
|
501
|
+
case "moveForward":
|
|
502
|
+
viewer.camera.moveForward(command.distance || 100);
|
|
503
|
+
break;
|
|
504
|
+
case "moveBackward":
|
|
505
|
+
viewer.camera.moveBackward(command.distance || 100);
|
|
506
|
+
break;
|
|
507
|
+
case "moveUp":
|
|
508
|
+
viewer.camera.moveUp(command.distance || 100);
|
|
509
|
+
break;
|
|
510
|
+
case "moveDown":
|
|
511
|
+
viewer.camera.moveDown(command.distance || 100);
|
|
512
|
+
break;
|
|
513
|
+
case "moveLeft":
|
|
514
|
+
viewer.camera.moveLeft(command.distance || 100);
|
|
515
|
+
break;
|
|
516
|
+
case "moveRight":
|
|
517
|
+
viewer.camera.moveRight(command.distance || 100);
|
|
518
|
+
break;
|
|
519
|
+
case "rotateLeft":
|
|
520
|
+
viewer.camera.rotateLeft(Cesium.Math.toRadians(command.angle || 15));
|
|
521
|
+
break;
|
|
522
|
+
case "rotateRight":
|
|
523
|
+
viewer.camera.rotateRight(Cesium.Math.toRadians(command.angle || 15));
|
|
524
|
+
break;
|
|
525
|
+
case "rotateUp":
|
|
526
|
+
viewer.camera.rotateUp(Cesium.Math.toRadians(command.angle || 15));
|
|
527
|
+
break;
|
|
528
|
+
case "rotateDown":
|
|
529
|
+
viewer.camera.rotateDown(Cesium.Math.toRadians(command.angle || 15));
|
|
530
|
+
break;
|
|
531
|
+
case "zoomIn":
|
|
532
|
+
viewer.camera.zoomIn(command.distance || 100);
|
|
533
|
+
break;
|
|
534
|
+
case "zoomOut":
|
|
535
|
+
viewer.camera.zoomOut(command.distance || 100);
|
|
536
|
+
break;
|
|
537
|
+
default:
|
|
538
|
+
console.warn(`Unknown camera command: ${cmd}`);
|
|
539
|
+
}
|
|
540
|
+
} catch (error) {
|
|
541
|
+
console.error(`Error executing camera command ${cmd}:`, error);
|
|
542
|
+
}
|
|
543
|
+
});
|
|
197
544
|
return {
|
|
198
545
|
updateCameraFromModel,
|
|
199
546
|
updateModelFromCamera,
|
|
@@ -588,23 +935,42 @@ function initializeMeasurementTools(viewer, model, container) {
|
|
|
588
935
|
</button>
|
|
589
936
|
`;
|
|
590
937
|
editorPanel.style.display = "block";
|
|
591
|
-
document.getElementById("apply-coords")
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
if (e.key === "Enter") {
|
|
605
|
-
document.getElementById("apply-coords").click();
|
|
938
|
+
const applyBtn = document.getElementById("apply-coords");
|
|
939
|
+
const closeBtn = document.getElementById("close-editor");
|
|
940
|
+
const editLonInput = document.getElementById("edit-lon");
|
|
941
|
+
const editLatInput = document.getElementById("edit-lat");
|
|
942
|
+
const editAltInput = document.getElementById("edit-alt");
|
|
943
|
+
if (!applyBtn || !closeBtn || !editLonInput || !editLatInput || !editAltInput) {
|
|
944
|
+
console.warn("[CesiumWidget] Editor panel input elements not found in DOM");
|
|
945
|
+
}
|
|
946
|
+
if (applyBtn) {
|
|
947
|
+
applyBtn.onclick = () => {
|
|
948
|
+
if (!editLonInput || !editLatInput || !editAltInput) {
|
|
949
|
+
console.warn("[CesiumWidget] Editor input fields not available");
|
|
950
|
+
return;
|
|
606
951
|
}
|
|
952
|
+
const lon = parseFloat(editLonInput.value);
|
|
953
|
+
const lat = parseFloat(editLatInput.value);
|
|
954
|
+
const alt = parseFloat(editAltInput.value);
|
|
955
|
+
const newPosition = Cesium.Cartesian3.fromDegrees(lon, lat, alt);
|
|
956
|
+
updatePointPosition(newPosition);
|
|
957
|
+
finalizeMeasurementUpdate();
|
|
607
958
|
};
|
|
959
|
+
}
|
|
960
|
+
if (closeBtn) {
|
|
961
|
+
closeBtn.onclick = () => {
|
|
962
|
+
deselectPoint();
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
["edit-lon", "edit-lat", "edit-alt"].forEach((id) => {
|
|
966
|
+
const element = document.getElementById(id);
|
|
967
|
+
if (element) {
|
|
968
|
+
element.onkeypress = (e) => {
|
|
969
|
+
if (e.key === "Enter" && applyBtn) {
|
|
970
|
+
applyBtn.click();
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
}
|
|
608
974
|
});
|
|
609
975
|
}
|
|
610
976
|
function updatePointPosition(newPosition) {
|
|
@@ -758,6 +1124,10 @@ function initializeMeasurementTools(viewer, model, container) {
|
|
|
758
1124
|
function updateMeasurementsList() {
|
|
759
1125
|
const results = model.get("measurement_results") || [];
|
|
760
1126
|
const listContent = document.getElementById("measurements-list-content");
|
|
1127
|
+
if (!listContent) {
|
|
1128
|
+
console.warn("[CesiumWidget] Measurements list content element not found in DOM");
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
761
1131
|
if (results.length === 0) {
|
|
762
1132
|
listContent.innerHTML = '<div style="color: #888; font-style: italic;">No measurements yet</div>';
|
|
763
1133
|
return;
|
|
@@ -808,10 +1178,15 @@ function initializeMeasurementTools(viewer, model, container) {
|
|
|
808
1178
|
}
|
|
809
1179
|
};
|
|
810
1180
|
listContent.appendChild(measurementDiv);
|
|
811
|
-
document.getElementById(`rename-${index}`)
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
1181
|
+
const renameBtn = document.getElementById(`rename-${index}`);
|
|
1182
|
+
if (renameBtn) {
|
|
1183
|
+
renameBtn.onclick = (e) => {
|
|
1184
|
+
e.stopPropagation();
|
|
1185
|
+
renameMeasurement(index, name);
|
|
1186
|
+
};
|
|
1187
|
+
} else {
|
|
1188
|
+
console.warn(`[CesiumWidget] Rename button not found for measurement ${index}`);
|
|
1189
|
+
}
|
|
815
1190
|
});
|
|
816
1191
|
}
|
|
817
1192
|
function getMeasurementColor(type) {
|