Combining two tiled layers issue

Dear all!

I have the following simple member in my JavaScript class describing tiled layers I want to load:

this._params['satellites'] = [{

    'url': "/tiles/landsat-i-cubed"

}, {

    'url': "/tiles/bmng-07-2004",

    'maximumLevel': 2


Layers’ loading is implemented in the following way:

this._cesium = new Cesium.CesiumWidget(this._params[‘id’]);

var layers = this._cesium.centralBody.getImageryLayers();

for (var i = 0; i < this._params['satellites'].length; i++) {

    var satelliteImageryParams = this._params['satellites'][i];

    if (satelliteImageryParams['url'].indexOf("/") === 0)

        satelliteImageryParams['url'] = window.location.protocol + "//" + + satelliteImageryParams['url'];

    satelliteImageryParams = jQuery.extend(satelliteImageryParams, {

        'tilingScheme': new Cesium.GeographicTilingScheme({

            numberOfLevelZeroTilesX: 2,

            numberOfLevelZeroTilesY: 1



    var satelliteImageryProvider = new Cesium.TileMapServiceImageryProvider(satelliteImageryParams);

    var satelliteLayer = new Cesium.ImageryLayer(satelliteImageryProvider);



As one can see both tile caches are organized according to caches provided by MapTiler. The only difference is that Landsat has some more detailed levels. What I want to achive is to display BMNG on high levels and then, say, starting from zoom level 3 overlay transparent Landsat. Setting maximumLevel to 2 in BMNG configuration array restricts tiles’ requesting by level in the range [0; 2] but it doesn’t affect layer’s visibility - Cesium stretches the latest level 2 when I zoom in. As the result, Landsat is never shown.

I also tried to swap these two layers in the array and set minimumLevel of Landsat to 3. But it predictably led me to situation I’ve described in my recent post.

Finally I’ve looked at documentation of ImageryLayer and found nothing that could help to solve the problem. I’d expected to see some zoom level or metric parameters allowing to specify minimum and maximum positions of the camera a layer is visible from. Is it possible to achieve desired behavior using Cesium some way?

Thank you so much for attention!


Cesium does not currently support turning a layer on/off at different zoom levels, though it’s certainly a reasonable thing to want to do.

Are you interested in contributing to Cesium itself? I can guide you in how to implement this feature, and we would welcome a pull request for it. Assuming it is acceptable to switch the layer at particular terrain zoom levels (rather than smoothly blending based on distance) it should be quite easy to implement.

Another possibility is to just build your imagery dataset this way in the first place. Since both of your layers are TMS-style, presumably using the same tiling scheme, it should be pretty easy. Just create a new directory and copy the tilemapresource.xml from the Landsat dataset. Then copy levels 0-3 from BMNG into that directory, and levels greater than 3 from Landsat into that directory. I think that should do the trick. This is assuming you have such control over the imagery datasets, of course.


Dear Kevin!

Thanks a lot for the reply!

I thought about mixing BMNG and Landsat but it’s not preferable way to go due to the following reasons:

  • BMNG is in JPG format while Landsat is in PNG one and has some transparent areas, so it would be ideally to display (even stretched) BMNG under Landsat on each level to cover these areas;

  • my application is supposed to be configurable so BMNG and Landsat can be changed to something else in the future or some additional layers such as transparent hybrid layer can be added.

Of course, I’m interested in having an opportunity to control layers’ visibility depending on the view but don’t know how many time I need to implement it. The main reason is that I know a little bit more than nothing about OpenGL/WebGL though I got some very basic principles from Cesium’s beautiful tutorials, Sandcastle code snippets and reference documentation. Keeping this in mind it’s hard to estimate how much my skills fit the Cesium project. Anyway, if it’s not so difficult for you to guide me through this task I would be happy to try.

I just opened a pull request that adds this feature:

If you get a chance to try it out, let me know how it goes.

Dear Kevin!

Thank you for your efforts.

I tried to test your modifications by copying and pasting them from your commit to recent build 19. I have to note that I couldn’t to get it working at the first time. I was mixing description plain objects of ImagerLayer and ImageryProvider (TileMapServiceImageryProvider in my case) supposing that they are the same thing. But looking at source code I finally saw that I was wrong. At this point I can state that missing ImageryLayer’s description during imagery layer creation based on passed ImageryProvider led me to such confusion. And I think it would be very good to have the following prototype of addImageryProvider method:

function(imageryProvider, description, index)

instead of

function(imageryProvider, index)

I’m not sure whether it’s safe to make description argument the second one considering the backward compatibility with previous releases. But missing this argument forces to create a layer through imagery provider’s constructor manually every time one want its parameters to work with imagery provider.

Going back to minTerrainLevel and maxTerrainLevel. Yes, they work. But it’s very easy to find a position of the camera when some tiles are already shown but others are not (see attachments). I guess the reason is that distances from the camera to these tiles are little bit different. Right now I’m out of ideas how it can be fixed. I faced with the similar problem in WorldWind but it was not such significant, probably due to using tile caches with 5x10 tiles (and even more) on zero level.