Intercepting Cesium's selectedEntity


I’m aiming to do my own custom handling on left click and left double click on entities to determine the selected entity. For example, I’d like to filter some entities out (not select them) or select the entity’s parent instead.
Currently I can do this by checking the selected entity AFTER its already been assigned, which isn’t all nice.

handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);

handler.setInputAction(function(movement) {
if (viewer.selectedEntity && viewer.selectedEntity.symbolType === “prop”) {
// do processing here
viewer.selectedEntity = undefined;
// etc.
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);


I was wondering if there is a way to trap the event BEFORE Cesium assigns the selected entity and override it with my own handling?


You can disable the Viewer’s built-in click handling abilities - did that in my own application. If you look inside Cesium’s Viewer.js file, you’ll see:

        cesiumWidget.screenSpaceEventHandler.setInputAction(pickAndSelectObject, ScreenSpaceEventType.LEFT_CLICK);
        cesiumWidget.screenSpaceEventHandler.setInputAction(pickAndTrackObject, ScreenSpaceEventType.LEFT_DOUBLE_CLICK);


In other words, it’s using the CesiumWidget’s default ScreenSpaceEventHandler instance to listen to clicks, and attach its own behavior. All you have to do is grab that same SSEH instance and remove those event listeners, then set up your own.

My current application started with Cesium b17, way before this Viewer thing showed up, so we’d always created a Scene and such for ourselves. That meant we always had our own click handling set up. A couple months back we wanted to leverage the selection/tracking abilities, so I upgraded us to use a Viewer instance, turned off all its default behavior, then wrote some adapter code to take our own data models (Backbone/Ampersand models, in this case), wrap them up a bit, present them to Cesium as Entities that could be tracked, and used a CallbackProperty to fetch their positions from the data fields we already had for our own use. Worked beautifully. I could probably share some relevant pseudocode tomorrow if it would help.

Ahh yes. That helps a lot thanks Mark.

I have now implemented removing those inputActions when initialising the widget. I also took the pickEntity, pickAndSelectObject & pickAndTrackObject methods defined in the Cesium js file, and have basically replicate their functionality to my needs.

This approach seems to be working fine and is much better, so thanks for that! I’ll still need to figure out how to alter Cesium’s defaults for its trackedEntity and the camera, as I want to disable the way it zooms into the minimumZoomDistance.

Sounds like you got to do some interesting stuff with your application. In this project of mine, we are reflecting entities from a simulation across network, which involves updating a data model based on a simulation tick from the network. I have set it to update the Cesium entity counterparts position, etc from the simulations tick rather than Cesium’s.

I believe the zoom aspect is related to how it calculates bounding spheres for each Entity. Let me actually give a bit more description of what our app does, and how I handled things, as it relates.

We’ve got a system that displays icons on the globe for various aircraft and other platforms, and has a bunch of other desktop-like UI. Our app is built on Backbone and Ampersand, and we update our in-memory data models via ongoing polling to the backend. When we started writing this, Cesium only had the Primitive API layer, so we’ve always managed all our display handling ourselves. We’ve actually created a bunch of Backbone/Marionette View classes that render Cesium primitives instead of HTML and then update those primitives as the models’ attributes change, which has worked out great. Sounds somewhat similar to what you’re doing

The net result is that while Cesium has really focused on the Entity API in the last year, we’ve been doing our own thing with the Primitive API. But, when we decided we wanted to add camera tracking ability, I noted that the Viewer had that already, and didn’t want to reinvent that wheel. The Entity adapter I threw together winds up creating an Entity instance that has a “position” property, but no visuals, since we’re doing all the primitive handling ourselves. If you follow Cesium’s tracking/selection logic down inside, it winds up asking the various Graphics types for a bounding sphere, and uses that to determine how far it should zoom in when something is selected. Because our generated Entities had no visuals attached, they also did not hand back a bounding sphere, and Cesium would zoom in WAY too far. I wound up copying Cesium’s functions for generating bounding spheres for billboards and 3D models and modified them to suit my needs. From there I created a custom Visualizer class to pass to the CustomDataSource instance that would use those to query my Cesium Views for the actual bounding sphere, and pass that back to Cesium. Increasing the radius of the bounding sphere causes Cesium to not zoom in as close.

It’s all proprietary, of course, so I can’t just paste all my code in here. But, hopefully that gives you some ideas, and if you need more detail, I’ll see what I can do.

I have to say that, having worked with both Google Earth and Cesium, the fact that Cesium is open source is just fantastic. I can at any moment dig down inside and see exactly what’s going on, as opposed to the big binary black box that was GE.

Mark Erikson

Very similar! Though I’m not sure the use of changing boundingSpheres could help in my position. Since I want maintain the zoom prior to tracking.

Currently I’m trying to track an entity using the viewFrom property, yet it’s not working as planned. I am trying to set the camera offset to directly above the entity, without modifying the zoom. As in, after beginning to track the entity, the camera offset uses the range before it was tracking.
However, it seems to reposition to track from the side, at an offset I’m not even sure how it arrived at.

I take it that without specifying a custom boundingSphere for that entity, it uses a default one, then uses the provided offset fromthat sphere to give the end camera range?