Preventing use of higher level tiles when lower level ones are unavailable (WMTS)

Hello,

I have a WMTS server
having only data from zoom levels 6 to 16 and want to display its tiles in
Cesium. According to the API reference of the WebMapTileServiceImageryProvider
(https://cesiumjs.org/Cesium/Build/Documentation/WebMapTileServiceImageryProvider.html#WebMapTileServiceImageryProvider),
I should be able to use the ‘minimumLevel’ and ‘maximumLevel’ properties to
indicate the available tile range.

I used the following
code (the URL is not the one I used, as my server is not accessible from
Internet):

var viewer = new
Cesium.Viewer(‘cesiumContainer’);

var wmts = new
Cesium.WebMapTileServiceImageryProvider({

url : "https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryTopo/MapServer/WMTS/tile/1.0.0/USGSImageryTopo/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}",

layer : 'USGSImageryTopo',

style : 'default',

format : 'image/png',

tileMatrixSetID : 'default028mm',

minimumLevel: 6,

maximumLevel: 16

});

viewer.imageryLayers.addImageryProvider(wmts);

I get the following
error: “Uncaught DeveloperError: The imagery provider’s rectangle and
minimumLevel indicate that there are 4096 tiles at the minimum level. Imagery
providers with more than four tiles at the minimum level are not
supported.”

I guess the reason
why Cesium tries to download data from zoom level 6 when the view is currently
at zoom level 0 is to “compute” the missing tiles from higher level
ones.

I
tried creating an ImageryLayer and specifying the minimumTerrainLevel, but
that’s not valid workaround, because the check is done in the
WebMapTileServiceImageryProvider constructor (https://github.com/AnalyticalGraphicsInc/cesium/blob/3ef9dad02f4be88894e58501a602118008c5b5c6/Source/Scene/WebMapTileServiceImageryProvider.js#L214).

The only workaround I could find was that, if you work on a
relatively small area, you can specify your extent
of interest with the ‘rectangle’ property of the options.

I see there was an
issue created to raise the allowed number of tiles at minimum level (https://github.com/AnalyticalGraphicsInc/cesium/issues/4372).

But would not it be
better to totally disable this “extrapolation” mechanism" when
it is not wanted?

It could be done
like that:

  1. Remove the check of the
    number of tiles at minimum level (https://github.com/AnalyticalGraphicsInc/cesium/blob/3ef9dad02f4be88894e58501a602118008c5b5c6/Source/Scene/WebMapTileServiceImageryProvider.js#L214)
  2. Add a new optional property
    to the ImageryLayer options named for instance
    ‘extrapolateLowerLevelTiles’. True would mean the current behavior (use
    higher level tiles to compute missing lower level ones), and false would
    mean that the layer should not try to display anything. Defaut value could
    be true to keep current behavior.
  3. Change the following block (https://github.com/AnalyticalGraphicsInc/cesium/blob/3ef9dad02f4be88894e58501a602118008c5b5c6/Source/Scene/ImageryLayer.js#L545)

if
(defined(imageryProvider.minimumLevel)) {

var minimumLevel =

imageryProvider.minimumLevel;

if (imageryLevel < minimumLevel) {

    imageryLevel = minimumLevel;

}

}

by
something like:

if
(defined(imageryProvider.minimumLevel)) {

var minimumLevel =

imageryProvider.minimumLevel;

if (imageryLevel < minimumLevel) {

    if (this.extrapolateLowerLevelTiles) {

        imageryLevel = minimumLevel;

    } else {

        // Do not create missing tiles from

higher level ones.

        return false;

    }

}

}

Would it be of any
interest for the product?

Best regards

Hi Thomas,

As mentioned in the other thread, step #1 may not be the best approach in all cases, as it’s trying to avoid loading too many tiles in at once when viewing the entire globe. I think you can circumvent that check if that optional “extrapolate” is set to false.

I think your approach makes sense, we’d be happy to review a pull request with this proposed change! See CONTRIBUTING.md to get started.

Thanks!

Gabby

Hi Gabby,

Thanks for your answer. I will gladly propose a pull request as soon as possible.

Thomas

Thomas,

This is a really poorly documented feature in Cesium and something we can do a lot better with. Just to jump right into it, I think this example code will provide exactly what you need, no changes to Cesium necessary:

var viewer = new Cesium.Viewer(‘cesiumContainer’, {

imageryProvider : false,

baseLayerPicker: false

});

var wmts = new Cesium.WebMapTileServiceImageryProvider({

url : “https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryTopo/MapServer/WMTS/tile/1.0.0/USGSImageryTopo/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}”,

layer : ‘USGSImageryTopo’,

style : ‘default’,

format : ‘image/png’,

tileMatrixSetID : ‘default028mm’,

maximumLevel: 16

});

var layers = viewer.imageryLayers;

layers.add(new Cesium.ImageryLayer(wmts, { minimumTerrainLevel: 6 }));

Here’s a Runnable demo version: https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/#c=ZVJNa+MwEP0rwpe4EKRkD2XJuqGQwhJI2LLOthdfJvbEFasPI8lO05D/XslWwGnti2bevHkjvenAkI7jEQ15IAqPZIWWt5K+9Ll0UvbhSisHXKGZTMm5UMR/XEKN5vRsdMcrz16QAwiL0wHdg8UNnNA88/I/mggW6nL3q1Dh77zuUTp7q/qK+y00Oy4wR9PxEte3KmkUb43wgkXy5lxjF4wFOQkNVeC4ViDCudYdA1PW3DKD1jE7dLTsX/47j313utHMKwY1NOx1u8uZ8+psTmd09q3ynLuTwAs7hwm34Ax/z9HdxDH4q4/xtNLiUiTxWUR4Ej/55EvnScRt6B/wCg/QCnfNH7SR4ALQPztrVH2F3HiU9dOIPPvxU8prmYR3Llu5wQ7FgszvgwfRjGBFP1gwY9gFGt3tLbS+asApVFU6sms9qkqDm347iOQqKO3QGL8yUfCeXO6CWjJNsv6Sy2GsRy4bbVwwNKWUOZSNAOdN2rd+bxwtrQ20jF1JWcU7wquHIvmymUVCSgHWeuTQCpHzDyySZcZ8/Q1NaKi4qv94v/2lQsnbfLkZkpTSjPnwO8tpLfZgRh0/AQ

Basically, I defined a single layer and have it disabled completely until you hit zoom level 6, so the globe is the default blue when the demo starts but as you zoom in it will appear when you hit level 6. You could also use a different base imagery layer as the base and turn it off at layer 6 at the same time yours turns on.

The poorly named minimumTerrainLevel/maximumTerrainLevel options to the ImageryLayer constructor turn on/off visualization of that layer at the specified zoom levels.

I’m going to write up an issue to better improve the API here and make it much more obvious how to implement this (often requested) functionality.

Let me know if you still have questions. Thanks!

Thanks Matt! Can you link to the issue you open here?

Thanks for the reminder. Submitted https://github.com/AnalyticalGraphicsInc/cesium/issues/6564