Search code examples
datasourcecesiumjsczml

How to customize czml datasource?


I have a CZML data that I extracted via python. I have buildings, with their geometry, height, building ID, and intervals. each interval has a value. After loading the czml data to Cesium, I'd like to access the attributes and then customize the color of the buildings according to the value given. Here is a sample of my CZML:

[{ "id": "document", "version": "1.0" }, { "id": 32, "availability": "2014-01-01T00:00:00Z/2014-12-31T00:00:00Z", "polygon": { "positions": { "cartographicDegrees": [54.7162360431897, 24.4519912715277, 0, 54.716219612921, 24.4519754832587, 0, 54.7162501395131, 24.4519488635358, 0, 54.7162465684811, 24.4519454316688, 0, 54.7162670831639, 24.4519275432238, 0, 54.7162707308589, 24.4519310439514, 0, 54.7163022563025, 24.4519035537608, 0, 54.7161962974502, 24.4518018819532, 0, 54.7161647729823, 24.4518293730395, 0, 54.7162035538772, 24.4520196028966, 0, 54.7162360431897, 24.4519912715277, 0] }, "someProperty": [{ "interval": "2014-00-01T00:00:00Z/2014-01-01T00:00:00Z", "En_C_need": 0.7 }, { "interval": "2014-01-01T00:00:00Z/2014-02-01T00:00:00Z", "En_C_need": 1.0 }, { "interval": "2014-02-01T00:00:00Z/2014-03-01T00:00:00Z", "En_C_need": 2.6 }, { "interval": "2014-03-01T00:00:00Z/2014-04-01T00:00:00Z", "En_C_need": 12.1 }, { "interval": "2014-04-01T00:00:00Z/2014-05-01T00:00:00Z", "En_C_need": 30.2 }, { "interval": "2014-05-01T00:00:00Z/2014-06-01T00:00:00Z", "En_C_need": 37.8 }], "extrudedHeight": 6.0 } }]

I have other GeoJSON data that I customized, I tried the same method but it didn't work.

Here is what I'm trying to do (this does not work):

var test2 = Cesium.CzmlDataSource.load ('Data/czml/TESTING/example_8.czml');
test2.then(function (dataSource) {
    viewer.dataSources.add(test2);
    viewer.zoomTo (test2);
var entities = dataSource.entities.values; 

    var colorHash = {};
    var Energy = [];
    for (var i = 0; i < entities.length; i++) {
        var entity = entities[i];
        Energy = entity.someProperty.En_C_need;
        var color = colorHash [Energy];
        if(!color ) {
            if (Energy < 5 ) {
            color = Cesium.Color.DARKSALMON.withAlpha (0.95);
        } else if (Energy < 10) {
                color = Cesium.Color.BURLYWOOD.withAlpha (0.95);
        } else if (Energy < 20) {
                color = Cesium.Color.RED.withAlpha (0.95);
        } else {
                color = Cesium.Color.PINK.withAlpha (0.95); 
        };
        colorHash[Energy] = color;
        };
        entity.polygon.fill = true;
        entity.polygon.material = color;
        entity.polygon.outline = false;     
    };

});


Solution

  • To start with the solution - here's the working plnkr: https://plnkr.co/edit/P1Cg4DNJYtK9r9XrLzxK?p=preview

    I've changed several things in your code: 1) viewer.dataSources.add(test2); should be outside your promise (it doesn't really matter, but it's cleaner code - using the promise inside the promise feels strange). 2) According to the CZML properties spec, you need to place the properties in the right location in the CZML. It should not be inside the polygon, but in the "root":

    var czml = [{"id": "document", "version": "1.0"},
    {
        "id": 32, "availability": "2014-01-01T00:00:00Z/2014-12-31T00:00:00Z", "properties": {
        "someProperty": [
            {"interval": "2014-00-01T00:00:00Z/2014-01-01T00:00:00Z", "En_C_need": 0.7}, 
            {"interval": "2014-01-01T00:00:00Z/2014-02-01T00:00:00Z", "En_C_need": 1.0},
            {"interval": "2014-02-01T00:00:00Z/2014-03-01T00:00:00Z", "En_C_need": 2.6},
            {"interval": "2014-03-01T00:00:00Z/2014-04-01T00:00:00Z", "En_C_need": 12.1},
            {"interval": "2014-04-01T00:00:00Z/2014-05-01T00:00:00Z", "En_C_need": 30.2},
            {"interval": "2014-05-01T00:00:00Z/2014-06-01T00:00:00Z", "En_C_need": 37.8}
            ],
    },
        "polygon": {
            "positions": {
                "cartographicDegrees":
                    [54.7162360431897, 24.4519912715277, 0, 54.716219612921, 24.4519754832587, 0, 54.7162501395131, 24.4519488635358, 0, 54.7162465684811, 24.4519454316688, 0, 54.7162670831639, 24.4519275432238, 0, 54.7162707308589, 24.4519310439514, 0, 54.7163022563025, 24.4519035537608, 0, 54.7161962974502, 24.4518018819532, 0, 54.7161647729823, 24.4518293730395, 0, 54.7162035538772, 24.4520196028966, 0, 54.7162360431897, 24.4519912715277, 0]
            },
            "extrudedHeight": 6.0
        }
    }];
    

    Then you can ask for the properties according to the interval (Energy = entity.properties.getValue(viewer.clock.currentTime).someProperty.En_C_need;) and get the Energy at viewer's current time.

    Update after commentchatting: Your code was not meant to change dynamically. You need to set the value either by callbackProperty as in this example: plnkr.co/edit/lm290uaQewEvfIOgXbDP?p=preview or by using timeIntervalCollection