Drag n Drop Entities

To the end of being able to move entities via mouse I am interested if anyone has worked towards implementing the following:
1. Implement HotSpot capability such that an entity is only clickable within a certain pixel area around the entities position. Allows picking when entity geometries overlap but have different positions.
2. Implement Billboard spreading when clicking an area where more than one entity has the same position so that you can select the specific billboard of interest.

Both of these capabilities existed in the Google Earth plugin, and given the nature of our data, it is common for our entities to to have overlapping geometries as well as have the same position. In order to fully migrate away from the plugin, I need to be able to edit entities and successfully select the desired entity by clicking on the pin of the desired entity.


Neither of these features are currently implemented in Cesium. I’m a little unclear about the HotSpot capability, but if you have multiple entities overlapping, you can use Scene.drillPick to get an array of all entities that overlap at the mouse click point, then have some method for letting the user choose which one he/she meant to select.

Here’s a demo that shows our picking capabilities: http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Picking.html&label=Showcases



Essentially each of our entities is Billboard containing a map pin, and a geometry typically an ellipse or a rectangle. What I mean by hot spot is essentially to filter picking such that only the billboard can be picked, not the geometry itself. This would reduce the requirement to drill pick and select to only entities whose map pins overlap. I would also want to enable resizing rectangles by providing click and drag capability on corner points. Given what I have seen from your picking api, none of this is entirely trivial given the capability that is presently exposed. How difficult would it be to expose a capability to attach a click handler to say a Billboard or a RectangleGraphics?

Thank you for clarifying. We currently don’t have a method for specifying which entities can be picked. We have an issue written up about that here: https://github.com/AnalyticalGraphicsInc/cesium/issues/1592

It is one of the more frequently requested features so hopefully someone will be able to take a look at that soon.

You would also have to write custom code to resize a rectangle. We don’t have any drawing capabilities built in at this time. A common solution we see is to use a point as a drag handle.

Here’s an example of using a point to drag the west side of a rectangle using entites:

var viewer = new Cesium.Viewer(‘cesiumContainer’);

var west = -110;
var south = 20;
var east = -100;
var north = 25;

var redRectangle = viewer.entities.add({
rectangle : {
coordinates : new Cesium.CallbackProperty(function() {
return Cesium.Rectangle.fromDegrees(west, south, east, north);
}, false),
material : Cesium.Color.RED.withAlpha(0.5),
outline : true,
outlineColor : Cesium.Color.RED

var point = viewer.entities.add({
position : new Cesium.CallbackProperty(function() {
return Cesium.Cartesian3.fromDegrees(west, (north + south) / 2);
}, false),
point : {
pixelSize : 10,
color : Cesium.Color.YELLOW

var dragging;
var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);

handler.setInputAction(function(click) {
var pickedObject = viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject) && pickedObject.id === point) {
dragging = pickedObject;
viewer.scene.screenSpaceCameraController.enableRotate = false;
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

handler.setInputAction(function() {
if (Cesium.defined(dragging)) {
dragging = undefined;
viewer.scene.screenSpaceCameraController.enableRotate = true;
}, Cesium.ScreenSpaceEventType.LEFT_UP);

handler.setInputAction(function(movement) {
var position = viewer.camera.pickEllipsoid(movement.endPosition);
if (!Cesium.defined(position) || !dragging) {

var positionCartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);

west = Cesium.Math.toDegrees(positionCartographic.longitude);

}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);



Using a CallbackProperty for the positions tells Cesium to draw those shapes synchronously, which prevents lag when dragging around the point. You could easily use a billboard to drag instead of using a point.