Highlight selected BillboardCollection element?

Thanks to the excellent Picking example from the SandCastle, I’m now able to render a bunch of satellites at various positions and identify them with a mouse hover. The collection is populated like:

billboards.add({imageIndex: 0,

position: new Cesium.Cartesian3(pos[0] * 1000, pos[1] * 1000, pos[2] * 1000)}); // Km to meter

I’m not sure this is the right way to identify the specific billboard in the collection as direct access to the _index attribute makes me feel “dirty”:

var pickedObject = scene.pick(movement.endPosition);

if (pickedObject) { // is the entire Billboard, not just a single satellite in it

name = satnames[pickedObject._index];

But what I’d like to do now is be able to highlight one of the billboards in the collection when a user asks to identify it by selecting from a picklist of names. Basically, I’d get an index from a . But I’m not sure how I’d flash or highlight or otherwise highlight one of the BillboardCollection items. Currently, all the items use the same satellite icon.

Any pointers?

Thanks!

Hi Chris,

As you allude to, I would not access _index directly. Instead, you can add your own properties to the billboard at run-time since this is JavaScript, e.g.,

var b = billboards.add(/* … */);

b.satelliteName = /* … */;

Then access the property when you do a pick, e.g.,

var pickedObject = scene.pick(movement.endPosition);

if ((typeof pickedObject !== ‘undefined’) && (typeof pickedObject.satelliteName !== ‘undefined’)) {

/* process pick */

}

To highlight the billboard, the simplest thing is to change its scale with setScale or change its color with setColor. See the reference doc. If you have a separate image to show when highlighting, add it to the texture atlas (you can add it just once, even when you first create the atlas), and use setImageIndex.

By the way, we’re really interested in your project, and are looking forward to a demo. :slight_smile:

Regards,

Patrick

As you allude to, I would not access _index directly. Instead, you can add your own properties to the billboard at run-time since this is JavaScript, e.g.,

var b = billboards.add(/* … */);

b.satelliteName = /* … */;

OK, that approach works well.

To highlight the billboard, the simplest thing is to change its scale with setScale or change its color with setColor.

Got it.

However, I think I’m setting the scale/color naively, in the tight loop that calculates position based on current time. So it’s looping over all the satellites constantly, and constantly setting the scale/color. It seems that my ‘billboards’ should be defined once for a set of satellites, and the ‘position’ attribute of each should be the only thing updated in the time-based loop. Setting scale/color would be done once upon mouse click to the ‘billboards’ collection element, not in the loop.

But this suggests that the ‘billboards’ collection should be rather global, like ‘scene’. This would also avoid constantly destroying the billboards all recreating them as I do now in my loop:

scene.getPrimitives().removeAll(); // TODO: removes our geo location :frowning:

scene.getPrimitives().add(billboards);

I ran across a discussion yesterday about naive users suffering performance problems with poor billboard practices:

but I don’t know what patterns you typically use in Cesium. Any pointers?

By the way, we’re really interested in your project, and are looking forward to a demo. :slight_smile:

OK, promise not to laugh too much. This is my first JavaScript endeavor and I’ve bitten off a project that’s a rather big for me. All SGP4 calculations from TLEs done in JavaScript using my translation of a MATLAB implementation, and my first attempts at using Cesium. There is no server-side code, by design. My JavaScript fu is weak, and I’d appreciate any feedback you’d care to provide. It’s very much a work in progress.

http://sot.koansys.com/viz/

Code’s on GitHub, with Issues:

https://github.com/koansys/sot

Thanks again!

Hi Chris,

Thanks for sending along the demo. It looks good so far. You might want to upgrade to a more recent version of Cesium (which uses AMD now, but we still have the single Cesium.js file that you are using). This will fix the near/far plane distances from cutting objects out when you zoom in or out, and will hopefully fix the strange behavior with billboards not moving during the morph between views.

I’ve been toying with the idea of adding a BillboardCollection internally to Scene, so that we’d be able to write code like:

scene.addBillboard(/* … */);

For apps like yours, this would be useful, but more complicated apps will still want separate collections in some cases. Anyway, in terms of general billboard guidelines - less collections is better. Generally, the fewer collections we have, the faster things will run. For your app, you could create just one collection, then clear it when the user changes the satellite group, and then add new billboards for the new satellites. Check out all the functions in the reference help for Billboard and BillboardCollection. As you suggest, during animation you should only call set functions for the properties that change. In this case, just setPosition should be fine.

Also, to prevent the context menu after right-clicking for zoom, I think you want:

    canvas.oncontextmenu = function(e) {
        e.preventDefault();
    };

Regards,

Patrick