Skip to content

Instantly share code, notes, and snippets.

@datadavev
Created November 29, 2021 13:03
Show Gist options
  • Save datadavev/9af52380c13cb5a0c1031b2611b1f4de to your computer and use it in GitHub Desktop.
Save datadavev/9af52380c13cb5a0c1031b2611b1f4de to your computer and use it in GitHub Desktop.
Cesium - Draw BB with mouse by holding down Alt.
/*
Draw a bounding box.
Hold down ALT and drag to draw a bounding box rectangle.
Multiple BBs may be shown.
Select a BB and Delete to remove.
*/
class BBSelector {
constructor() {
// holds the selection rectangle when drawing
this.r = new Cesium.Rectangle();
// starting point
this.p0 = null;
// current point
this.p1 = null;
// callback that updates the entity coordinates
this.cb = null;
// entity, a RectangleGeometry
this.entity = null;
}
get rect() {
return Cesium.Rectangle.clone(this.r);
}
/**
* Start drawing the bounding rectangle
*
* Returns an entity that should be added to the viewer entity collection
*/
startDrawing(cartesian, name=null) {
this.entity = new Cesium.Entity({
show: true,
rectangle: {
coordinates: new Cesium.Rectangle(),
material: Cesium.Color.YELLOW.withAlpha(0.5),
},
name: name,
});
this.p0 = Cesium.Cartographic.fromCartesian(cartesian);
this.p1 = Cesium.Cartographic.clone(this.p0);
this.r.west = this.p0.longitude;
this.r.east = this.p1.longitude;
this.r.south = this.p0.latitude;
this.r.north = this.p1.latitude;
this.cb = new Cesium.CallbackProperty((time, result) => {
return Cesium.Rectangle.clone(this.r);
}, false);
this.entity.rectangle.coordinates = this.cb;
return this.entity;
}
/**
* Update the rectangle with the provided cartesian
*/
draw(cartesian) {
this.p1 = Cesium.Cartographic.fromCartesian(cartesian);
this.r.east = Math.max(this.p0.longitude, this.p1.longitude);
this.r.west = Math.min(this.p0.longitude, this.p1.longitude);
this.r.north = Math.max(this.p0.latitude, this.p1.latitude);
this.r.south = Math.min(this.p0.latitude, this.p1.latitude);
}
/**
* Stop drawing.
*
* The callback is removed, and the entity coordinates become static
*/
stopDrawing() {
this.entity.rectangle.coordinates = this.rect;
this.entity = null;
this.p0 = null;
this.p1 = null;
this.cb = null;
}
toString() {
return `${this.r.west}, ${this.r.south}, ${this.r.east}, ${this.r.north},`;
}
}
/*****************************************/
// Create the viewer with terrain
var viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain(),
});
// Get a ScreenSpaceEventHandler
// https://cesium.com/learn/cesiumjs/ref-doc/ScreenSpaceEventHandler.html
let screenEventHandler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
// set to an instance of BBSelector when drawing
let _selector = null;
let bbIDs = [];
let selectedID = null;
// Handle Alt + left_down
// Start drawing the selector
screenEventHandler.setInputAction((event) => {
// Determine the Cesium cartesian coordinates from the mouse position
const cartesian = viewer.scene.pickPosition(event.position);
if (cartesian !== undefined) {
// Start drawing if we have a valid starting point.
_selector = new BBSelector();
// get the entity to display
const bb = _selector.startDrawing(cartesian, "Bounding Box");
// display the entity by adding it to the viewer entity collection
bbIDs.push(bb.id);
viewer.entities.add(bb);
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN, Cesium.KeyboardEventModifier.ALT);
// Handle Alt+move
// Draw the selector between the first and current points.
screenEventHandler.setInputAction((event) => {
if (_selector === null) {
return;
}
const cartesian = viewer.scene.pickPosition(event.endPosition);
if (cartesian !== undefined) {
_selector.draw(cartesian);
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE, Cesium.KeyboardEventModifier.ALT);
// Handle Alt + left up
// Drawing is finished, create the rectangle and add to entities
screenEventHandler.setInputAction((event) => {
if (_selector !== null) {
_selector.stopDrawing();
}
_selector = null;
}, Cesium.ScreenSpaceEventType.LEFT_UP, Cesium.KeyboardEventModifier.ALT);
// Info, log the screen coords and corresponding longitude, latitude
screenEventHandler.setInputAction((event) => {
console.log(event.position);
const pc = viewer.scene.pickPosition(event.position);
if (pc !== undefined) {
const P = Cesium.Cartographic.fromCartesian(pc);
console.log(`${Cesium.Math.toDegrees(P.longitude)}, ${Cesium.Math.toDegrees(P.latitude)}`);
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
viewer.selectedEntityChanged.addEventListener(function(entity) {
if (Cesium.defined(entity)) {
if (bbIDs.includes(entity.id)) {
console.log(entity.id);
if (selectedID !== null) {
const csel = viewer.entities.getById(selectedID);
if (csel !== undefined) {
csel.rectangle.material = Cesium.Color.YELLOW.withAlpha(0.5);
}
}
selectedID = entity.id;
entity.rectangle.material = Cesium.Color.RED.withAlpha(0.3);
}
} else {
if (selectedID !== null) {
const csel = viewer.entities.getById(selectedID);
if (csel !== undefined) {
csel.rectangle.material = Cesium.Color.YELLOW.withAlpha(0.5);
}
selectedID = null;
console.log("unselected");
}
}
});
viewer.canvas.setAttribute('tabindex', '0');
viewer.canvas.onclick = function () {
viewer.canvas.focus();
};
document.getElementById("cesiumContainer").addEventListener('keydown', function(e){
if (e.key === "Delete") {
if (selectedID !== null) {
viewer.entities.removeById(selectedID);
let newbbs = [];
bbIDs.forEach(bb => {
if (bb !== selectedID) {
newbbs.push(bb);
}
});
bbIDs = newbbs;
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment