The CZML entities position CallbackProperty bug?

52 views
Skip to first unread message

findl...@gmail.com

unread,
Apr 1, 2019, 10:38:29 AM4/1/19
to cesium-dev
1. A concise explanation of the problem you're experiencing.

I add satellite orbit from a czml file, and add cylinder under each satellite using the entity's position CallbackProperty. But when I add more than one satellite, the program only render the last satellite's cylinder in czml file, please help...

2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.

var dataSource = new Cesium.CzmlDataSource();
        viewer.dataSources.add(dataSource);
        dataSource.process('./SampleData/satellite1.czml').then(function() {

            console.log(dataSource.entities.values.length);

            var saEntity;
            var nowPos = [];

            for(var i=0;i<dataSource.entities.values.length;i++){
                saEntity = dataSource.entities.values[i];
                var isConstant = false;
                var tmp = i;

                viewer.entities.add({
                    id: tmp,
                    name: tmp,
                    position : new Cesium.CallbackProperty(function(time) {
                        nowPos[i] = Cesium.Ellipsoid.WGS84.cartesianToCartographic(saEntity.position.getValue(time));
                        console.log(tmp + ":" + time);
                        //if(i==0){  console.log(tmp + ":"+ time + "pos:" + nowPos[i]); }
                        return Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees(nowPos[i].longitude),Cesium.Math.toDegrees(nowPos[i].latitude),0,Cesium.Ellipsoid.WGS84);
                    }, isConstant),
                    cylinder: {
                        length: new Cesium.CallbackProperty(function(time) {
                            nowPos[i] = Cesium.Ellipsoid.WGS84.cartesianToCartographic(saEntity.position.getValue(time));
                            //if(i==0){  console.log(tmp + ":"+ time + "pos:" + nowPos[i]); }
                            return nowPos[i].height;
                            }, isConstant),
                        topRadius: 0.0,
                        bottomRadius: 300000.0,
                        material: Cesium.Color.RED.withAlpha(0.2),
                    }
                });
            }
        });

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.
add cylinder under each satellite using the entity's position CallbackPropert


4. The Cesium version you're using, your operating system and browser.
cesium 1.51 ,chrome 70

1.png


Omar Shehata

unread,
Apr 3, 2019, 11:05:23 AM4/3/19
to cesium-dev
This is actually a problem with scoping in JavaScript, not with CZML or Cesium. The problem is that you're creating functions in the loop that all reference the saEntity variable. There is only one variable, which get overwritten each iteration of the loop, so all the functions end up referencing the same satellite, which is the last one in the loop.

You can test this out with just a simple function that prints out the id:

var saEntity;
var callbackFunctions = [];
for(var i=0;i<dataSource.entities.values.length;i++){
   saEntity = dataSource.entities.values[i];
    callbackFunctions.push(function(){
        console.log(entity.id);
    });
}

for (var i = 0;i < callbackFunctions.length; i++){
    callbackFunctions[i]();
}

Here you'll get all the printouts of the same id, the last satellite. One way to get around this is to using a closure to capture the scope of each variable:


var saEntity;
var callbackFunctions = [];
for(var i=0;i<dataSource.entities.values.length;i++){
   saEntity = dataSource.entities.values[i];
    callbackFunctions.push(function(entity){
        return function(){
            console.log(entity.id);
        };
    }(saEntity));
}

for (var i = 0;i < callbackFunctions.length; i++){
    callbackFunctions[i]();
}

 This will correctly print each one.
Reply all
Reply to author
Forward
0 new messages