Using CallbackProperty to Update Wall Positions

I’ve been working on this problem for a few days, but I just can’t seem to figure it out.

I am attempting to use a Wall entity to create a limited length trail with a curtain to the ground that follows behind an aircraft. I have algorithms that use actual data points as well as interpolated points to update the trail positions many times per second. I have the code in place which successfully performs the same thing with just polylines/polylineCollections to create simple “trails”. But I’m having a tough time using Wall entities.

Here’s the code I’m using in a function during animation. Once I determine if the Wall entity already exists I either create it or update it…


if (!blnFound) {
var newCurtainSeg = cesiumViewer.entities.add({
id: this.TrackId,
wall: {
positions: new Cesium.CallbackProperty(updateCurtain(currSegmentInfo.segmentPositions), false),
material: Cesium.Color.fromCssColorString(currSegmentInfo.segmentColor).withAlpha(0.5)
}
});
this.listCurtainSegments.push(newCurtainSeg);
}
else {
this.updateCurtain(currSegmentInfo.segmentPositions);
}

function updateCurtain(positions){
return function() {
return positions;
};
};

``

The problem is that the positions array returned from the callback function doesn’t change even though the array being passed to the function is updated every call. I just get the original array of positions returned over and over again.

Here’s a screen capture showing what I’m getting at this point. The capture was taken after the flights had been animating for some time and I toggled on the Walls (“curtains”). I get an initial curtain for each flight, but the positions of the curtains do not get updated. You can see that the positions of the polyline trailing the aircraft are being updated. But the Walls remain with their original positions…

Based on the following forum topic it seems like this may be related to a Javascript closure issue, but I’m struggling to figure it out…

https://groups.google.com/forum/embed/?place=forum/cesium-dev&showsearch=true&showpopout=true&hideforumtitle=true&fragments=true&parenturl=http%3A%2F%2Fcesiumjs.org%2Fforum.html#!searchin/cesium-dev/callback/cesium-dev/b3rtp5etSOo/Io3xnN2CCAAJ

Any pointers would be greatly appreciated!

I’ve actually set up the updateCurtain function as a prototype on my FlightTrack object as follows…

FlightTrack.prototype.updateCurtain = function(positions){
return function() {
return positions;
};
};

``

I intended to strip it from the code I posted for simplicity sake. But I noticed that I left “this.updateCurtain” in the “else” portion of the code I posted. Just wanted to clarify.

I can’t tell what you’re trying to do with updateCurtain. It doesn’t look like your’e calling the function that function is returning anywhere. Where are the positions actually getting updated?

-Hannah

I’m actually passing the updated positions to the updateCurtain function from the “else” statement in the code above.

I’ve confirmed that the new positions held in the currSegmentInfo.segmentPositions array are correct. But if I put a print statement in the updateCurtain function the positions are only the first ones passed to the function.

I’ve also tried just updating the Wall positions directly (without the callback), but I get the same results. The wall is painted one time, but new positions are not applied.

You alluded to this earlier, but the problem is indeed a JavaScript closure issue not related to Cesium.

this.updateCurtain(currSegmentInfo.segmentPositions);

This actually does nothing. It calls your updateCurtain function, which allocates a new function and returns it, whereupon it is thrown away.

Instead, you need to have some kind of storage object which you can update such that the callback property sees it. Although conceptually you don’t really need a CallbackProperty because your values are not actually a function of time. Presumably the only reason you’re using CallbackProperty is to avoid async primitive creation. Perhaps consider making a copy of ConstantProperty which simply returns false from isConstant instead of true.

https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/DataSources/ConstantProperty.js

Scott,

Thank you for the response. To tell you the truth I’m only using the CallbackProperty because after trying to update the Wall positions directly I found code in the forums that showed using the CallbackProperty.

Considering that we may display thousands of flights… which approach do you think would be most efficient?

Also, I don’t understand how I would use the copy of ConstantProperty. I took a quick look, but I don’t see any examples that would help me understand for my situation.

I appreciate any guidance you could provide!

Rob

Ok. I figured out what you were describing regarding a storage object. I added an array to my FlightTrack object called listCurtainPositions. Every time I calculate the new positions I update this positions array. Then in the CallbackProperty’s function I return the value of this positions array.

...
if (!blnFound) {
    this.listCurtainPositions = currSegmentInfo.segmentPositions;
    var newCurtainSeg = cesiumViewer.entities.add({
        id: this.TrackId,
        wall: {
            positions: new Cesium.CallbackProperty(this.updateCurtain(this), false),
            material: Cesium.Color.fromCssColorString(currSegmentInfo.segmentColor).withAlpha(0.5)
        }
    });
    this.listCurtainSegments.push(newCurtainSeg);
}
else {
    this.listCurtainPositions = currSegmentInfo.segmentPositions;
}
...

FlightTrack.prototype.updateCurtain = function(ft){

return function() { return ft.listCurtainPositions; };

};

``

Thank you for the help with this!

If you have time I still would love to understand what you were describing about the ConstantProperty and how I would use it?

Thanks again,

Rob

I made a sandcastle example.

http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Hello%20World.html&label=Showcases&gist=78486bdaa5076e9b2263c345bb0bc532

CustomProperty is a simple non-constant Property which can have its value set via setValue(). Basically it’s the same as what you have except the value is stored within the property rather than being stored in listCurtainPositions.

A more robust implementation would handle clonable and/or equatable values, using the same code as in ConstantProperty.

Scott,

Thanks for the great example! That really helps me understand what you were describing!

Rob