Skip to content

Commit

Permalink
Fix Cesium datasource issues & minor draw tool bug
Browse files Browse the repository at this point in the history
- Properly switch the maps "click action" back to original setting after draw tool turned off
- Fixed delayed rendering of datasources after update (esp. Geohashes)
- Fix zooming to features on click (issue with getting bounding sphere of a feature)

Issues #2180 and #2189
  • Loading branch information
robyngit committed Oct 18, 2023
1 parent b245cca commit f7d6ddf
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 41 deletions.
18 changes: 6 additions & 12 deletions src/js/models/maps/assets/CesiumVectorData.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,16 +405,14 @@ define([
return;
}
const time = Cesium.JulianDate.now();
let displayReadyNow = dataSource.update(time);
let displayReadyNow = true
for (let x = 0; x < visualizers.length; x++) {
displayReadyNow = visualizers[x].update(time) && displayReadyNow;
}
this.set("displayReady", displayReadyNow);
if (!displayReadyNow) {
// If the display is not ready, try again. It means the visualizers
// are waiting for an asynchronous process to complete.
setTimeout(this.runVisualizers.bind(this), 10);
return
setTimeout(this.runVisualizers.bind(this), 300);
} else {
this.set("displayReady", true);
}
this.trigger("appearanceChanged");
},
Expand Down Expand Up @@ -783,12 +781,8 @@ define([
}
return false;
})
.catch(function (error) {
console.log(
"Failed to get the bounding sphere for a CesiumVectorData model" +
". Error details: " +
error
);
.catch(function (e) {
console.log("Error getting bounding sphere.", e);
});
},
}
Expand Down
121 changes: 93 additions & 28 deletions src/js/views/maps/CesiumWidgetView.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,16 +280,15 @@ define([
if (view.zoomTarget) {
view.completeFlight(view.zoomTarget, view.zoomOptions);
}
// The dataSourceDisplay must be set to 'ready' to get bounding
// spheres for dataSources
view.dataSourceDisplay._ready = true;
} catch (e) {
console.log("Error calling post render functions:", e);
}
},

/**
* Run the update method and all visualizers for each data source.
* @return {boolean} Returns true if all data sources are ready to be
* displayed.
* @since x.x.x
*/
updateAllDataSources: function () {
Expand All @@ -299,13 +298,17 @@ define([
return;
}
const time = view.clock.currentTime;
dataSources.forEach(function (dataSource) {
let displayReady = true;
for (let i = 0; i < dataSources.length; i++) {
const dataSource = dataSources.get(i);
dataSource.update(view.clock.currentTime);
// for each visualizer, update it
dataSource._visualizers.forEach(function (visualizer) {
visualizer.update(time);
displayReady = displayReady && visualizer.update(time);
});
});
}
view.dataSourceDisplay._ready = displayReady;
return displayReady;
},

/**
Expand Down Expand Up @@ -370,11 +373,11 @@ define([

// Listen for addition or removal of layers TODO: Add similar listeners
// for terrain
if(layers){
if (layers) {
view.stopListening(layers);
view.listenTo(layers, "add", view.addAsset);
view.listenTo(layers, "remove", view.removeAsset);

// Each layer fires 'appearanceChanged' whenever the color, opacity,
// etc. has been updated. Re-render the scene when this happens.
view.listenTo(layers, "appearanceChanged", view.requestRender);
Expand Down Expand Up @@ -595,7 +598,7 @@ define([
const layersReverse = layers.last(layers.length).reverse();
layersReverse.forEach(function (layer) {
view.addAsset(layer);
})
});
}

// The Cesium Widget will support just one terrain option to start.
Expand Down Expand Up @@ -662,19 +665,18 @@ define([
*/
completeFlight: function (target, options) {
try {
const view = this;
if (typeof options !== "object") options = {};

// A target is required
if (!target) {
return;
}
if (!target) return;

const view = this;
if (typeof options !== "object") options = {};
view.resetZoomTarget();

// If the target is a Bounding Sphere, use the camera's built-in
// function
if (target instanceof Cesium.BoundingSphere) {
view.camera.flyToBoundingSphere(target, options);
view.resetZoomTarget();
return;
}

Expand Down Expand Up @@ -713,27 +715,31 @@ define([
// If the object saved in the Feature is an Entity, then this
// function will get the bounding sphere for the entity on the next
// run.
setTimeout(() => {
// TODO check if needed
view.flyTo(target.get("featureObject"), options);
}, 0);
// check if the layer is displayReady
const layer = target.get("mapAsset");
const displayReady = layer.get("displayReady");
if (!displayReady) {
// Must wait for layer to be rendered in via the dataSourceDisplay
// before we can get the bounding sphere for the feature.
view.listenToOnce(layer, "change:displayReady", function () {
view.flyTo(target, options);
});
return
}
view.flyTo(target.get("featureObject"), options);
return;
}

// If the target is a Cesium Entity, then get the bounding sphere for
// the entity and call this function again.
const entity = target instanceof Cesium.Entity ? target : target.id;

if (entity instanceof Cesium.Entity) {
let entityBoundingSphere = new Cesium.BoundingSphere();
view.dataSourceDisplay.getBoundingSphere(
entity,
false,
entityBoundingSphere
);
setTimeout(() => {
// TODO check if needed

view.dataSourceDisplay._ready = true
view.getBoundingSphereFromEntity(entity).then(function (entityBoundingSphere) {
view.flyTo(entityBoundingSphere, options);
}, 0);
});
return;
}

Expand Down Expand Up @@ -770,6 +776,65 @@ define([
}
},

getBoundingSphereFromEntity: function (entity) {
const view = this
const entityBoundingSphere = new Cesium.BoundingSphere();
const readyState = Cesium.BoundingSphereState.DONE;
function getBS() {
return view.dataSourceDisplay.getBoundingSphere(
entity,
false,
entityBoundingSphere
);
}
// Return a promise that resolves to bounding box when it's ready.
// Keep running getBS at intervals until it's ready.
return new Promise(function (resolve, reject) {
let attempts = 0;
const maxAttempts = 100;
const interval = setInterval(function () {
attempts++;
const state = getBS();
if (state !== readyState) {
// Search for the entity again in case it was removed and
// re-added to the data source display.
entity = view.getEntityById(entity.id, entity.entityCollection);
if(!entity) {
clearInterval(interval);
reject("Failed to get bounding sphere for entity, entity not found.");
}

} else {
clearInterval(interval);
resolve(entityBoundingSphere);
}
if (attempts >= maxAttempts) {
clearInterval(interval);
reject("Failed to get bounding sphere for entity.");
}
}, 100);
})
},

/**
* Search an entity collection for an entity with a given id.
* @param {string} id - The id of the entity to find.
* @param {Cesium.EntityCollection} collection - The collection to search.
* @returns {Cesium.Entity} The entity with the given id, or null if no
* entity with that id exists in the collection.
* @since x.x.x
*/
getEntityById: function (id, collection) {
const entities = collection.values;
for (let i = 0; i < entities.length; i++) {
const entity = entities[i];
if (entity.id === id) {
return entity;
}
}
return null;
},

resetZoomTarget: function () {
const view = this;
view.zoomTarget = null;
Expand Down
3 changes: 2 additions & 1 deletion src/js/views/maps/DrawToolView.js
Original file line number Diff line number Diff line change
Expand Up @@ -386,12 +386,13 @@ define(["backbone", "models/connectors/GeoPoints-CesiumPolygon", "models/connect
*/
removeClickListeners: function () {
const handler = this.clickHandler;
const originalAction = this.originalAction;
if (handler) {
handler.stopListening();
handler.clear();
this.clickHandler = null;
}
this.mapModel.set("clickFeatureAction", this.originalClickAction);
this.mapModel.set("clickFeatureAction", originalAction);
this.listeningForClicks = false;
},

Expand Down

0 comments on commit f7d6ddf

Please sign in to comment.