cesiumjs-anywidget 0.4.0__py3-none-any.whl → 0.5.0__py3-none-any.whl

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.
@@ -3,16 +3,26 @@
3
3
 
4
4
  // src/cesiumjs_anywidget/js/viewer-init.js
5
5
  async function loadCesiumJS() {
6
+ console.log("[CesiumWidget:ViewerInit] Loading CesiumJS...");
6
7
  if (window.Cesium) {
8
+ console.log("[CesiumWidget:ViewerInit] CesiumJS already loaded, reusing existing instance");
7
9
  return window.Cesium;
8
10
  }
9
11
  const script = document.createElement("script");
10
12
  script.src = "https://cesium.com/downloads/cesiumjs/releases/1.135/Build/Cesium/Cesium.js";
13
+ console.log("[CesiumWidget:ViewerInit] Loading CesiumJS from CDN...");
11
14
  await new Promise((resolve, reject) => {
12
- script.onload = resolve;
13
- script.onerror = reject;
15
+ script.onload = () => {
16
+ console.log("[CesiumWidget:ViewerInit] CesiumJS script loaded successfully");
17
+ resolve();
18
+ };
19
+ script.onerror = (error) => {
20
+ console.error("[CesiumWidget:ViewerInit] Failed to load CesiumJS script:", error);
21
+ reject(error);
22
+ };
14
23
  document.head.appendChild(script);
15
24
  });
25
+ console.log("[CesiumWidget:ViewerInit] CesiumJS initialized");
16
26
  return window.Cesium;
17
27
  }
18
28
  function createLoadingIndicator(container, hasToken) {
@@ -34,6 +44,7 @@ function createLoadingIndicator(container, hasToken) {
34
44
  return loadingDiv;
35
45
  }
36
46
  function createViewer(container, model, Cesium) {
47
+ console.log("[CesiumWidget:ViewerInit] Creating viewer with options...");
37
48
  const viewerOptions = {
38
49
  timeline: model.get("show_timeline"),
39
50
  animation: model.get("show_animation"),
@@ -47,17 +58,28 @@ function createViewer(container, model, Cesium) {
47
58
  shadows: false,
48
59
  shouldAnimate: false
49
60
  };
61
+ console.log("[CesiumWidget:ViewerInit] Viewer options:", viewerOptions);
50
62
  if (model.get("enable_terrain")) {
51
63
  viewerOptions.terrain = Cesium.Terrain.fromWorldTerrain();
64
+ console.log("[CesiumWidget:ViewerInit] Terrain enabled");
52
65
  }
53
66
  const viewer = new Cesium.Viewer(container, viewerOptions);
54
67
  viewer.scene.globe.enableLighting = model.get("enable_lighting");
68
+ console.log("[CesiumWidget:ViewerInit] Viewer created, lighting:", model.get("enable_lighting"));
55
69
  return viewer;
56
70
  }
57
71
  function setupViewerListeners(viewer, model, container, Cesium) {
72
+ console.log("[CesiumWidget:ViewerInit] Setting up viewer listeners");
73
+ let isDestroyed = false;
74
+ let scrubTimeout = null;
58
75
  model.on("change:enable_terrain", () => {
76
+ if (isDestroyed) {
77
+ console.log("[CesiumWidget:ViewerInit] Skipping enable_terrain change - destroyed");
78
+ return;
79
+ }
59
80
  if (!viewer)
60
81
  return;
82
+ console.log("[CesiumWidget:ViewerInit] Terrain setting changed:", model.get("enable_terrain"));
61
83
  if (model.get("enable_terrain")) {
62
84
  viewer.scene.setTerrain(Cesium.Terrain.fromWorldTerrain());
63
85
  } else {
@@ -65,32 +87,47 @@ function setupViewerListeners(viewer, model, container, Cesium) {
65
87
  }
66
88
  });
67
89
  model.on("change:enable_lighting", () => {
90
+ if (isDestroyed)
91
+ return;
68
92
  if (!viewer)
69
93
  return;
94
+ console.log("[CesiumWidget:ViewerInit] Lighting setting changed:", model.get("enable_lighting"));
70
95
  viewer.scene.globe.enableLighting = model.get("enable_lighting");
71
96
  });
72
97
  model.on("change:height", () => {
98
+ if (isDestroyed)
99
+ return;
73
100
  if (!viewer)
74
101
  return;
102
+ console.log("[CesiumWidget:ViewerInit] Height changed:", model.get("height"));
75
103
  container.style.height = model.get("height");
76
104
  viewer.resize();
77
105
  });
78
106
  model.on("change:show_timeline", () => {
107
+ if (isDestroyed)
108
+ return;
79
109
  if (!viewer || !viewer.timeline)
80
110
  return;
111
+ console.log("[CesiumWidget:ViewerInit] Timeline visibility changed:", model.get("show_timeline"));
81
112
  viewer.timeline.container.style.visibility = model.get("show_timeline") ? "visible" : "hidden";
82
113
  });
83
114
  model.on("change:show_animation", () => {
115
+ if (isDestroyed)
116
+ return;
84
117
  if (!viewer || !viewer.animation)
85
118
  return;
119
+ console.log("[CesiumWidget:ViewerInit] Animation visibility changed:", model.get("show_animation"));
86
120
  viewer.animation.container.style.visibility = model.get("show_animation") ? "visible" : "hidden";
87
121
  });
88
122
  model.on("change:atmosphere_settings", () => {
123
+ if (isDestroyed)
124
+ return;
89
125
  if (!viewer || !viewer.scene || !viewer.scene.atmosphere)
90
126
  return;
91
127
  const settings = model.get("atmosphere_settings");
92
128
  if (!settings || Object.keys(settings).length === 0)
93
129
  return;
130
+ console.log("[CesiumWidget:ViewerInit] Atmosphere settings changed:", settings);
94
131
  const atmosphere = viewer.scene.atmosphere;
95
132
  if (settings.brightnessShift !== void 0) {
96
133
  atmosphere.brightnessShift = settings.brightnessShift;
@@ -129,11 +166,14 @@ function setupViewerListeners(viewer, model, container, Cesium) {
129
166
  }
130
167
  });
131
168
  model.on("change:sky_atmosphere_settings", () => {
169
+ if (isDestroyed)
170
+ return;
132
171
  if (!viewer || !viewer.scene || !viewer.scene.skyAtmosphere)
133
172
  return;
134
173
  const settings = model.get("sky_atmosphere_settings");
135
174
  if (!settings || Object.keys(settings).length === 0)
136
175
  return;
176
+ console.log("[CesiumWidget:ViewerInit] Sky atmosphere settings changed:", settings);
137
177
  const skyAtmosphere = viewer.scene.skyAtmosphere;
138
178
  if (settings.show !== void 0) {
139
179
  skyAtmosphere.show = settings.show;
@@ -178,11 +218,14 @@ function setupViewerListeners(viewer, model, container, Cesium) {
178
218
  }
179
219
  });
180
220
  model.on("change:skybox_settings", () => {
221
+ if (isDestroyed)
222
+ return;
181
223
  if (!viewer || !viewer.scene || !viewer.scene.skyBox)
182
224
  return;
183
225
  const settings = model.get("skybox_settings");
184
226
  if (!settings || Object.keys(settings).length === 0)
185
227
  return;
228
+ console.log("[CesiumWidget:ViewerInit] SkyBox settings changed:", settings);
186
229
  const skyBox = viewer.scene.skyBox;
187
230
  if (settings.show !== void 0) {
188
231
  skyBox.show = settings.show;
@@ -207,104 +250,155 @@ function setupViewerListeners(viewer, model, container, Cesium) {
207
250
  }
208
251
  });
209
252
  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
- };
253
+ if (!viewer || !viewer.camera || !viewer.camera.positionCartographic) {
254
+ console.warn("[CesiumWidget:ViewerInit] Cannot get camera state - viewer or camera not available");
255
+ return null;
256
+ }
257
+ try {
258
+ const cartographic = viewer.camera.positionCartographic;
259
+ return {
260
+ latitude: Cesium.Math.toDegrees(cartographic.latitude),
261
+ longitude: Cesium.Math.toDegrees(cartographic.longitude),
262
+ altitude: cartographic.height,
263
+ heading: Cesium.Math.toDegrees(viewer.camera.heading),
264
+ pitch: Cesium.Math.toDegrees(viewer.camera.pitch),
265
+ roll: Cesium.Math.toDegrees(viewer.camera.roll)
266
+ };
267
+ } catch (error) {
268
+ console.warn("[CesiumWidget:ViewerInit] Error getting camera state:", error);
269
+ return null;
270
+ }
219
271
  }
220
272
  function getClockState() {
221
- if (!viewer.clock)
273
+ if (!viewer || !viewer.clock)
222
274
  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
- };
275
+ try {
276
+ return {
277
+ current_time: Cesium.JulianDate.toIso8601(viewer.clock.currentTime),
278
+ multiplier: viewer.clock.multiplier,
279
+ is_animating: viewer.clock.shouldAnimate
280
+ };
281
+ } catch (error) {
282
+ console.warn("[CesiumWidget:ViewerInit] Error getting clock state:", error);
283
+ return null;
284
+ }
228
285
  }
229
286
  function sendInteractionEvent(type, additionalData = {}) {
287
+ if (isDestroyed) {
288
+ console.log("[CesiumWidget:ViewerInit] Skipping interaction event - destroyed:", type);
289
+ return;
290
+ }
291
+ if (!viewer) {
292
+ console.warn("[CesiumWidget:ViewerInit] Cannot send interaction event - viewer not available");
293
+ return;
294
+ }
295
+ const cameraState = getCameraState();
296
+ if (!cameraState) {
297
+ console.warn("[CesiumWidget:ViewerInit] Skipping interaction event - camera state not available");
298
+ return;
299
+ }
230
300
  const event = {
231
301
  type,
232
302
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
233
- camera: getCameraState(),
303
+ camera: cameraState,
234
304
  clock: getClockState(),
235
305
  ...additionalData
236
306
  };
237
- console.log("[CesiumWidget] Interaction event:", type, event);
307
+ console.log("[CesiumWidget:ViewerInit] Interaction event:", type, event);
238
308
  model.set("interaction_event", event);
239
309
  model.save_changes();
240
310
  }
241
311
  const camera = viewer.camera;
242
312
  camera.moveEnd.addEventListener(() => {
313
+ if (isDestroyed || !viewer)
314
+ return;
243
315
  sendInteractionEvent("camera_move");
244
316
  });
245
317
  const scene = viewer.scene;
246
318
  const handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
247
319
  handler.setInputAction((click) => {
320
+ if (isDestroyed || !viewer || !viewer.scene || !viewer.camera)
321
+ return;
248
322
  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
- };
323
+ try {
324
+ const ray = viewer.camera.getPickRay(click.position);
325
+ if (ray && viewer.scene.globe) {
326
+ const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
327
+ if (cartesian) {
328
+ const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
329
+ pickedData.picked_position = {
330
+ latitude: Cesium.Math.toDegrees(cartographic.latitude),
331
+ longitude: Cesium.Math.toDegrees(cartographic.longitude),
332
+ altitude: cartographic.height
333
+ };
334
+ }
335
+ }
336
+ } catch (error) {
337
+ console.warn("[CesiumWidget:ViewerInit] Error picking position:", error);
258
338
  }
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) {
339
+ try {
340
+ const pickedObject = viewer.scene.pick(click.position);
341
+ if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
342
+ const entity = pickedObject.id;
343
+ pickedData.picked_entity = {
344
+ id: entity.id,
345
+ name: entity.name || null
346
+ };
347
+ if (entity.properties) {
348
+ const props = {};
349
+ const propertyNames = entity.properties.propertyNames;
350
+ if (propertyNames && propertyNames.length > 0) {
351
+ propertyNames.forEach((name) => {
352
+ try {
353
+ props[name] = entity.properties[name].getValue(viewer.clock.currentTime);
354
+ } catch (e) {
355
+ }
356
+ });
357
+ if (Object.keys(props).length > 0) {
358
+ pickedData.picked_entity.properties = props;
274
359
  }
275
- });
276
- if (Object.keys(props).length > 0) {
277
- pickedData.picked_entity.properties = props;
278
360
  }
279
361
  }
280
362
  }
363
+ } catch (error) {
364
+ console.warn("[CesiumWidget:ViewerInit] Error picking entity:", error);
281
365
  }
282
366
  sendInteractionEvent("left_click", pickedData);
283
367
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
284
368
  handler.setInputAction((click) => {
369
+ if (isDestroyed || !viewer || !viewer.scene || !viewer.camera)
370
+ return;
285
371
  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
- };
372
+ try {
373
+ const ray = viewer.camera.getPickRay(click.position);
374
+ if (ray && viewer.scene.globe) {
375
+ const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
376
+ if (cartesian) {
377
+ const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
378
+ pickedData.picked_position = {
379
+ latitude: Cesium.Math.toDegrees(cartographic.latitude),
380
+ longitude: Cesium.Math.toDegrees(cartographic.longitude),
381
+ altitude: cartographic.height
382
+ };
383
+ }
384
+ }
385
+ } catch (error) {
386
+ console.warn("[CesiumWidget:ViewerInit] Error picking position:", error);
295
387
  }
296
388
  sendInteractionEvent("right_click", pickedData);
297
389
  }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
298
390
  if (viewer.timeline) {
299
391
  let timelineScrubbing = false;
300
- let scrubTimeout = null;
301
392
  viewer.clock.onTick.addEventListener(() => {
393
+ if (isDestroyed)
394
+ return;
302
395
  if (viewer.timeline) {
303
396
  if (scrubTimeout) {
304
397
  clearTimeout(scrubTimeout);
398
+ scrubTimeout = null;
305
399
  }
306
400
  scrubTimeout = setTimeout(() => {
307
- if (timelineScrubbing) {
401
+ if (!isDestroyed && timelineScrubbing) {
308
402
  timelineScrubbing = false;
309
403
  sendInteractionEvent("timeline_scrub");
310
404
  }
@@ -313,13 +407,23 @@ function setupViewerListeners(viewer, model, container, Cesium) {
313
407
  }
314
408
  });
315
409
  }
410
+ console.log("[CesiumWidget:ViewerInit] Viewer listeners setup complete");
316
411
  }
317
412
  function setupGeoJSONLoader(viewer, model, Cesium) {
413
+ console.log("[CesiumWidget:ViewerInit] Setting up GeoJSON loader");
318
414
  let geojsonDataSources = [];
319
- model.on("change:geojson_data", async () => {
320
- if (!viewer || !viewer.dataSources)
415
+ let isDestroyed = false;
416
+ async function loadGeoJSONData(flyToData = true) {
417
+ if (isDestroyed) {
418
+ console.log("[CesiumWidget:ViewerInit] Skipping geojson_data load - destroyed");
321
419
  return;
420
+ }
421
+ if (!viewer || !viewer.dataSources) {
422
+ console.warn("[CesiumWidget:ViewerInit] Cannot load GeoJSON - viewer or dataSources not available");
423
+ return;
424
+ }
322
425
  const geojsonDataArray = model.get("geojson_data");
426
+ console.log("[CesiumWidget:ViewerInit] Loading GeoJSON data, count:", geojsonDataArray?.length || 0);
323
427
  geojsonDataSources.forEach((dataSource) => {
324
428
  if (viewer && viewer.dataSources) {
325
429
  viewer.dataSources.remove(dataSource);
@@ -329,6 +433,7 @@ function setupGeoJSONLoader(viewer, model, Cesium) {
329
433
  if (geojsonDataArray && Array.isArray(geojsonDataArray)) {
330
434
  for (const geojsonData of geojsonDataArray) {
331
435
  try {
436
+ console.log("[CesiumWidget:ViewerInit] Loading GeoJSON dataset...");
332
437
  const dataSource = await Cesium.GeoJsonDataSource.load(geojsonData, {
333
438
  stroke: Cesium.Color.HOTPINK,
334
439
  fill: Cesium.Color.PINK.withAlpha(0.5),
@@ -337,18 +442,28 @@ function setupGeoJSONLoader(viewer, model, Cesium) {
337
442
  if (viewer && viewer.dataSources) {
338
443
  viewer.dataSources.add(dataSource);
339
444
  geojsonDataSources.push(dataSource);
445
+ console.log("[CesiumWidget:ViewerInit] GeoJSON dataset loaded successfully");
340
446
  }
341
447
  } catch (error) {
342
- console.error("Error loading GeoJSON:", error);
448
+ console.error("[CesiumWidget:ViewerInit] Error loading GeoJSON:", error);
343
449
  }
344
450
  }
345
- if (geojsonDataSources.length > 0 && viewer && viewer.flyTo) {
451
+ if (flyToData && geojsonDataSources.length > 0 && viewer && viewer.flyTo) {
452
+ console.log("[CesiumWidget:ViewerInit] Flying to GeoJSON data");
346
453
  viewer.flyTo(geojsonDataSources[0]);
347
454
  }
348
455
  }
349
- });
456
+ }
457
+ model.on("change:geojson_data", () => loadGeoJSONData(true));
458
+ const initialData = model.get("geojson_data");
459
+ if (initialData && Array.isArray(initialData) && initialData.length > 0) {
460
+ console.log("[CesiumWidget:ViewerInit] Loading initial GeoJSON data...");
461
+ loadGeoJSONData(true);
462
+ }
350
463
  return {
351
464
  destroy: () => {
465
+ console.log("[CesiumWidget:ViewerInit] Destroying GeoJSON loader");
466
+ isDestroyed = true;
352
467
  geojsonDataSources.forEach((dataSource) => {
353
468
  if (viewer) {
354
469
  viewer.dataSources.remove(dataSource);
@@ -359,11 +474,20 @@ function setupGeoJSONLoader(viewer, model, Cesium) {
359
474
  };
360
475
  }
361
476
  function setupCZMLLoader(viewer, model, Cesium) {
477
+ console.log("[CesiumWidget:ViewerInit] Setting up CZML loader");
362
478
  let czmlDataSources = [];
363
- model.on("change:czml_data", async () => {
364
- if (!viewer || !viewer.dataSources)
479
+ let isDestroyed = false;
480
+ async function loadCZMLData(flyToData = true) {
481
+ if (isDestroyed) {
482
+ console.log("[CesiumWidget:ViewerInit] Skipping czml_data load - destroyed");
365
483
  return;
484
+ }
485
+ if (!viewer || !viewer.dataSources) {
486
+ console.warn("[CesiumWidget:ViewerInit] Cannot load CZML - viewer or dataSources not available");
487
+ return;
488
+ }
366
489
  const czmlDataArray = model.get("czml_data");
490
+ console.log("[CesiumWidget:ViewerInit] Loading CZML data, count:", czmlDataArray?.length || 0);
367
491
  czmlDataSources.forEach((dataSource) => {
368
492
  if (viewer && viewer.dataSources) {
369
493
  viewer.dataSources.remove(dataSource);
@@ -374,23 +498,36 @@ function setupCZMLLoader(viewer, model, Cesium) {
374
498
  for (const czmlData of czmlDataArray) {
375
499
  if (Array.isArray(czmlData) && czmlData.length > 0) {
376
500
  try {
501
+ console.log("[CesiumWidget:ViewerInit] Loading CZML document with", czmlData.length, "packets...");
377
502
  const dataSource = await Cesium.CzmlDataSource.load(czmlData);
378
503
  if (viewer && viewer.dataSources) {
379
504
  viewer.dataSources.add(dataSource);
380
505
  czmlDataSources.push(dataSource);
506
+ console.log("[CesiumWidget:ViewerInit] CZML document loaded successfully, entities:", dataSource.entities.values.length);
381
507
  }
382
508
  } catch (error) {
383
- console.error("Error loading CZML:", error);
509
+ console.error("[CesiumWidget:ViewerInit] Error loading CZML:", error);
384
510
  }
511
+ } else {
512
+ console.warn("[CesiumWidget:ViewerInit] Skipping invalid CZML data (not an array or empty):", czmlData);
385
513
  }
386
514
  }
387
- if (czmlDataSources.length > 0 && viewer && viewer.flyTo) {
515
+ if (flyToData && czmlDataSources.length > 0 && viewer && viewer.flyTo) {
516
+ console.log("[CesiumWidget:ViewerInit] Flying to CZML data");
388
517
  viewer.flyTo(czmlDataSources[0]);
389
518
  }
390
519
  }
391
- });
520
+ }
521
+ model.on("change:czml_data", () => loadCZMLData(true));
522
+ const initialData = model.get("czml_data");
523
+ if (initialData && Array.isArray(initialData) && initialData.length > 0) {
524
+ console.log("[CesiumWidget:ViewerInit] Loading initial CZML data...");
525
+ loadCZMLData(true);
526
+ }
392
527
  return {
393
528
  destroy: () => {
529
+ console.log("[CesiumWidget:ViewerInit] Destroying CZML loader");
530
+ isDestroyed = true;
394
531
  czmlDataSources.forEach((dataSource) => {
395
532
  if (viewer) {
396
533
  viewer.dataSources.remove(dataSource);
@@ -404,28 +541,48 @@ function setupCZMLLoader(viewer, model, Cesium) {
404
541
  // src/cesiumjs_anywidget/js/camera-sync.js
405
542
  function initializeCameraSync(viewer, model) {
406
543
  const Cesium = window.Cesium;
407
- let cameraUpdateTimeout;
544
+ let cameraUpdateTimeout = null;
545
+ let isDestroyed = false;
546
+ console.log("[CesiumWidget:CameraSync] Initializing camera synchronization");
408
547
  function updateCameraFromModel() {
409
- if (!viewer)
548
+ if (isDestroyed) {
549
+ console.log("[CesiumWidget:CameraSync] Skipping updateCameraFromModel - module destroyed");
410
550
  return;
551
+ }
552
+ if (!viewer) {
553
+ console.warn("[CesiumWidget:CameraSync] updateCameraFromModel called but viewer is null");
554
+ return;
555
+ }
411
556
  const lat = model.get("latitude");
412
557
  const lon = model.get("longitude");
413
558
  const alt = model.get("altitude");
414
559
  const heading = Cesium.Math.toRadians(model.get("heading"));
415
560
  const pitch = Cesium.Math.toRadians(model.get("pitch"));
416
561
  const roll = Cesium.Math.toRadians(model.get("roll"));
562
+ console.log("[CesiumWidget:CameraSync] Updating camera from model:", { lat, lon, alt });
417
563
  viewer.camera.setView({
418
564
  destination: Cesium.Cartesian3.fromDegrees(lon, lat, alt),
419
565
  orientation: { heading, pitch, roll }
420
566
  });
421
567
  }
422
568
  function updateModelFromCamera() {
423
- if (!viewer)
569
+ if (isDestroyed) {
570
+ console.log("[CesiumWidget:CameraSync] Skipping updateModelFromCamera - module destroyed");
424
571
  return;
572
+ }
573
+ if (!viewer) {
574
+ console.warn("[CesiumWidget:CameraSync] updateModelFromCamera called but viewer is null");
575
+ return;
576
+ }
425
577
  const position = viewer.camera.positionCartographic;
426
578
  const heading = viewer.camera.heading;
427
579
  const pitch = viewer.camera.pitch;
428
580
  const roll = viewer.camera.roll;
581
+ console.log("[CesiumWidget:CameraSync] Updating model from camera:", {
582
+ lat: Cesium.Math.toDegrees(position.latitude),
583
+ lon: Cesium.Math.toDegrees(position.longitude),
584
+ alt: position.height
585
+ });
429
586
  model.set("latitude", Cesium.Math.toDegrees(position.latitude));
430
587
  model.set("longitude", Cesium.Math.toDegrees(position.longitude));
431
588
  model.set("altitude", position.height);
@@ -435,9 +592,17 @@ function initializeCameraSync(viewer, model) {
435
592
  model.save_changes();
436
593
  }
437
594
  function handleCameraChanged() {
438
- clearTimeout(cameraUpdateTimeout);
595
+ if (isDestroyed) {
596
+ console.log("[CesiumWidget:CameraSync] Skipping handleCameraChanged - module destroyed");
597
+ return;
598
+ }
599
+ if (cameraUpdateTimeout) {
600
+ clearTimeout(cameraUpdateTimeout);
601
+ }
439
602
  cameraUpdateTimeout = setTimeout(() => {
440
- updateModelFromCamera();
603
+ if (!isDestroyed) {
604
+ updateModelFromCamera();
605
+ }
441
606
  }, 500);
442
607
  }
443
608
  updateCameraFromModel();
@@ -449,10 +614,15 @@ function initializeCameraSync(viewer, model) {
449
614
  model.on("change:pitch", updateCameraFromModel);
450
615
  model.on("change:roll", updateCameraFromModel);
451
616
  model.on("change:camera_command", () => {
617
+ if (isDestroyed) {
618
+ console.log("[CesiumWidget:CameraSync] Skipping camera_command - module destroyed");
619
+ return;
620
+ }
452
621
  const command = model.get("camera_command");
453
622
  if (!command || !command.command || !command.timestamp)
454
623
  return;
455
624
  const cmd = command.command;
625
+ console.log("[CesiumWidget:CameraSync] Executing camera command:", cmd, command);
456
626
  try {
457
627
  switch (cmd) {
458
628
  case "flyTo":
@@ -545,17 +715,25 @@ function initializeCameraSync(viewer, model) {
545
715
  updateCameraFromModel,
546
716
  updateModelFromCamera,
547
717
  destroy: () => {
548
- clearTimeout(cameraUpdateTimeout);
718
+ console.log("[CesiumWidget:CameraSync] Destroying camera sync module");
719
+ isDestroyed = true;
720
+ if (cameraUpdateTimeout) {
721
+ clearTimeout(cameraUpdateTimeout);
722
+ cameraUpdateTimeout = null;
723
+ }
549
724
  viewer.camera.changed.removeEventListener(handleCameraChanged);
725
+ console.log("[CesiumWidget:CameraSync] Camera sync module destroyed");
550
726
  }
551
727
  };
552
728
  }
553
729
 
554
730
  // src/cesiumjs_anywidget/js/measurement-tools.js
555
731
  function initializeMeasurementTools(viewer, model, container) {
732
+ console.log("[CesiumWidget:MeasurementTools] Initializing measurement tools");
556
733
  const Cesium = window.Cesium;
557
734
  let measurementHandler = null;
558
735
  let editHandler = null;
736
+ let isDestroyed = false;
559
737
  let measurementState = {
560
738
  mode: null,
561
739
  points: [],
@@ -777,6 +955,7 @@ function initializeMeasurementTools(viewer, model, container) {
777
955
  };
778
956
  }
779
957
  function clearAllMeasurements() {
958
+ console.log("[CesiumWidget:MeasurementTools] Clearing all measurements");
780
959
  measurementState.entities.forEach((e) => viewer.entities.remove(e));
781
960
  measurementState.labels.forEach((l) => viewer.entities.remove(l));
782
961
  measurementState.polylines.forEach((p) => viewer.entities.remove(p));
@@ -1123,6 +1302,7 @@ function initializeMeasurementTools(viewer, model, container) {
1123
1302
  }
1124
1303
  function updateMeasurementsList() {
1125
1304
  const results = model.get("measurement_results") || [];
1305
+ console.log("[CesiumWidget:MeasurementTools] Updating measurements list, count:", results.length);
1126
1306
  const listContent = document.getElementById("measurements-list-content");
1127
1307
  if (!listContent) {
1128
1308
  console.warn("[CesiumWidget] Measurements list content element not found in DOM");
@@ -1488,6 +1668,7 @@ function initializeMeasurementTools(viewer, model, container) {
1488
1668
  }
1489
1669
  }
1490
1670
  function enableMeasurementMode(mode) {
1671
+ console.log("[CesiumWidget:MeasurementTools] Enabling measurement mode:", mode);
1491
1672
  if (measurementHandler) {
1492
1673
  measurementHandler.destroy();
1493
1674
  measurementHandler = null;
@@ -1676,31 +1857,50 @@ function initializeMeasurementTools(viewer, model, container) {
1676
1857
  });
1677
1858
  }
1678
1859
  model.on("change:measurement_mode", () => {
1860
+ if (isDestroyed) {
1861
+ console.log("[CesiumWidget:MeasurementTools] Skipping measurement_mode change - destroyed");
1862
+ return;
1863
+ }
1679
1864
  const mode = model.get("measurement_mode");
1865
+ console.log("[CesiumWidget:MeasurementTools] Measurement mode changed:", mode);
1680
1866
  enableMeasurementMode(mode);
1681
1867
  });
1682
1868
  model.on("change:measurement_results", () => {
1869
+ if (isDestroyed) {
1870
+ console.log("[CesiumWidget:MeasurementTools] Skipping measurement_results change - destroyed");
1871
+ return;
1872
+ }
1683
1873
  const results = model.get("measurement_results") || [];
1874
+ console.log("[CesiumWidget:MeasurementTools] Measurement results changed, count:", results.length);
1684
1875
  if (results.length === 0) {
1685
1876
  clearAllMeasurements();
1686
1877
  }
1687
1878
  updateMeasurementsList();
1688
1879
  });
1689
1880
  model.on("change:load_measurements_trigger", () => {
1881
+ if (isDestroyed)
1882
+ return;
1690
1883
  const triggerData = model.get("load_measurements_trigger");
1884
+ console.log("[CesiumWidget:MeasurementTools] Load measurements trigger:", triggerData);
1691
1885
  if (triggerData && triggerData.measurements) {
1692
1886
  loadAndDisplayMeasurements(triggerData.measurements);
1693
1887
  updateMeasurementsList();
1694
1888
  }
1695
1889
  });
1696
1890
  model.on("change:focus_measurement_trigger", () => {
1891
+ if (isDestroyed)
1892
+ return;
1697
1893
  const triggerData = model.get("focus_measurement_trigger");
1894
+ console.log("[CesiumWidget:MeasurementTools] Focus measurement trigger:", triggerData);
1698
1895
  if (triggerData && typeof triggerData.index === "number") {
1699
1896
  focusOnMeasurement(triggerData.index);
1700
1897
  }
1701
1898
  });
1702
1899
  model.on("change:show_measurement_tools", () => {
1900
+ if (isDestroyed)
1901
+ return;
1703
1902
  const show = model.get("show_measurement_tools");
1903
+ console.log("[CesiumWidget:MeasurementTools] Show measurement tools:", show);
1704
1904
  toolbarDiv.style.display = show ? "flex" : "none";
1705
1905
  editorPanel.style.display = show ? editorPanel.style.display : "none";
1706
1906
  if (!show && editState.enabled) {
@@ -1709,7 +1909,10 @@ function initializeMeasurementTools(viewer, model, container) {
1709
1909
  }
1710
1910
  });
1711
1911
  model.on("change:show_measurements_list", () => {
1912
+ if (isDestroyed)
1913
+ return;
1712
1914
  const show = model.get("show_measurements_list");
1915
+ console.log("[CesiumWidget:MeasurementTools] Show measurements list:", show);
1713
1916
  measurementsListPanel.style.display = show ? "block" : "none";
1714
1917
  });
1715
1918
  toolbarDiv.style.display = model.get("show_measurement_tools") ? "flex" : "none";
@@ -1719,6 +1922,8 @@ function initializeMeasurementTools(viewer, model, container) {
1719
1922
  enableMeasurementMode,
1720
1923
  clearAllMeasurements,
1721
1924
  destroy: () => {
1925
+ console.log("[CesiumWidget:MeasurementTools] Destroying measurement tools");
1926
+ isDestroyed = true;
1722
1927
  if (measurementHandler) {
1723
1928
  measurementHandler.destroy();
1724
1929
  }
@@ -1726,6 +1931,7 @@ function initializeMeasurementTools(viewer, model, container) {
1726
1931
  if (toolbarDiv.parentNode) {
1727
1932
  toolbarDiv.remove();
1728
1933
  }
1934
+ console.log("[CesiumWidget:MeasurementTools] Measurement tools destroyed");
1729
1935
  }
1730
1936
  };
1731
1937
  }
@@ -1733,15 +1939,22 @@ function initializeMeasurementTools(viewer, model, container) {
1733
1939
  // src/cesiumjs_anywidget/js/index.js
1734
1940
  window.CESIUM_BASE_URL = "https://cesium.com/downloads/cesiumjs/releases/1.135/Build/Cesium/";
1735
1941
  async function render({ model, el }) {
1942
+ console.log("[CesiumWidget] Starting render");
1943
+ console.log("[CesiumWidget] Loading CesiumJS...");
1736
1944
  const Cesium = await loadCesiumJS();
1945
+ console.log("[CesiumWidget] CesiumJS loaded successfully");
1737
1946
  const container = document.createElement("div");
1738
1947
  container.style.width = "100%";
1739
1948
  container.style.height = model.get("height");
1740
1949
  container.style.position = "relative";
1741
1950
  el.appendChild(container);
1951
+ console.log("[CesiumWidget] Container created with height:", model.get("height"));
1742
1952
  const ionToken = model.get("ion_access_token");
1743
1953
  if (ionToken) {
1744
1954
  Cesium.Ion.defaultAccessToken = ionToken;
1955
+ console.log("[CesiumWidget] Ion access token set");
1956
+ } else {
1957
+ console.warn("[CesiumWidget] No Ion access token provided");
1745
1958
  }
1746
1959
  const loadingDiv = createLoadingIndicator(container, !!ionToken);
1747
1960
  let viewer = null;
@@ -1751,37 +1964,57 @@ async function render({ model, el }) {
1751
1964
  let czmlLoader = null;
1752
1965
  (async () => {
1753
1966
  try {
1967
+ console.log("[CesiumWidget] Creating Cesium Viewer...");
1754
1968
  viewer = createViewer(container, model, Cesium);
1969
+ console.log("[CesiumWidget] Cesium Viewer created successfully");
1755
1970
  if (loadingDiv.parentNode) {
1756
1971
  loadingDiv.remove();
1757
1972
  }
1973
+ console.log("[CesiumWidget] Initializing camera synchronization...");
1758
1974
  cameraSync = initializeCameraSync(viewer, model);
1975
+ console.log("[CesiumWidget] Camera synchronization initialized");
1976
+ console.log("[CesiumWidget] Initializing measurement tools...");
1759
1977
  measurementTools = initializeMeasurementTools(viewer, model, container);
1978
+ console.log("[CesiumWidget] Measurement tools initialized");
1979
+ console.log("[CesiumWidget] Setting up viewer listeners...");
1760
1980
  setupViewerListeners(viewer, model, container, Cesium);
1981
+ console.log("[CesiumWidget] Viewer listeners set up");
1982
+ console.log("[CesiumWidget] Setting up GeoJSON loader...");
1761
1983
  geoJsonLoader = setupGeoJSONLoader(viewer, model, Cesium);
1984
+ console.log("[CesiumWidget] GeoJSON loader set up");
1985
+ console.log("[CesiumWidget] Setting up CZML loader...");
1762
1986
  czmlLoader = setupCZMLLoader(viewer, model, Cesium);
1987
+ console.log("[CesiumWidget] CZML loader set up");
1988
+ console.log("[CesiumWidget] Initialization complete");
1763
1989
  } catch (error) {
1764
- console.error("Error initializing CesiumJS viewer:", error);
1990
+ console.error("[CesiumWidget] Error initializing CesiumJS viewer:", error);
1765
1991
  loadingDiv.textContent = `Error: ${error.message}`;
1766
1992
  loadingDiv.style.background = "rgba(255,0,0,0.8)";
1767
1993
  }
1768
1994
  })();
1769
1995
  return () => {
1996
+ console.log("[CesiumWidget] Starting cleanup...");
1770
1997
  if (cameraSync) {
1998
+ console.log("[CesiumWidget] Destroying camera sync...");
1771
1999
  cameraSync.destroy();
1772
2000
  }
1773
2001
  if (measurementTools) {
2002
+ console.log("[CesiumWidget] Destroying measurement tools...");
1774
2003
  measurementTools.destroy();
1775
2004
  }
1776
2005
  if (geoJsonLoader) {
2006
+ console.log("[CesiumWidget] Destroying GeoJSON loader...");
1777
2007
  geoJsonLoader.destroy();
1778
2008
  }
1779
2009
  if (czmlLoader) {
2010
+ console.log("[CesiumWidget] Destroying CZML loader...");
1780
2011
  czmlLoader.destroy();
1781
2012
  }
1782
2013
  if (viewer) {
2014
+ console.log("[CesiumWidget] Destroying viewer...");
1783
2015
  viewer.destroy();
1784
2016
  }
2017
+ console.log("[CesiumWidget] Cleanup complete");
1785
2018
  };
1786
2019
  }
1787
2020
  var js_default = { render };
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cesiumjs-anywidget
3
- Version: 0.4.0
3
+ Version: 0.5.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
7
- Author: Alex PLACET
7
+ Author: Alexis Placet
8
8
  License: Apache License
9
9
  Version 2.0, January 2004
10
10
  http://www.apache.org/licenses/
@@ -0,0 +1,8 @@
1
+ cesiumjs_anywidget/__init__.py,sha256=9WVcAtreHgk6C5clPG6sZy4m7s5AIbGU1DJ4oDpx3Is,165
2
+ cesiumjs_anywidget/styles.css,sha256=kt2i9fJuM6gaR7WkoQ2VGGoHzhqy6RpJVK2xwMKPV70,689
3
+ cesiumjs_anywidget/widget.py,sha256=_7uXX7B3KsOg_3QrMDfV0pZ8BGA-6coFnZ7_gTI3nck,39104
4
+ cesiumjs_anywidget/index.js,sha256=SRVdkrR2QHSnlXBcHvk5jZFOlWVX6GKXaluB5RPl1kA,79662
5
+ cesiumjs_anywidget-0.5.0.dist-info/METADATA,sha256=EIQjpI0HVMin-MZZSOLBbtngZFU4_bis2DQ3S9lNb2I,24780
6
+ cesiumjs_anywidget-0.5.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
7
+ cesiumjs_anywidget-0.5.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
8
+ cesiumjs_anywidget-0.5.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- cesiumjs_anywidget/__init__.py,sha256=9WVcAtreHgk6C5clPG6sZy4m7s5AIbGU1DJ4oDpx3Is,165
2
- cesiumjs_anywidget/styles.css,sha256=kt2i9fJuM6gaR7WkoQ2VGGoHzhqy6RpJVK2xwMKPV70,689
3
- cesiumjs_anywidget/widget.py,sha256=_7uXX7B3KsOg_3QrMDfV0pZ8BGA-6coFnZ7_gTI3nck,39104
4
- cesiumjs_anywidget/index.js,sha256=SrJ9F9xHdfvbz5CkP_ydspiDaPU6vp74vxtUv-RVimE,68405
5
- cesiumjs_anywidget-0.4.0.dist-info/METADATA,sha256=NwADYoiPPp4RLblmHCM5_mhak_cCB7ptC4iN0NXVZTY,24778
6
- cesiumjs_anywidget-0.4.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
7
- cesiumjs_anywidget-0.4.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
8
- cesiumjs_anywidget-0.4.0.dist-info/RECORD,,