OpenLayers – FullTileRanges of TileGrid No Longer Easily Available in Version 6.13

javascriptopenlayers

Getting the details of a tileGrid was working fine in OpenLayers 6.5, but I've just upgraded to OpenLayers 6.13 and now the tileGrid keys are no longer available in plain English. Eg, keys such as "resolutions_" and "fullTileRanges_" are not available directly in the tileGrid object. Instead there are only the coded keys (which presumably change with each build of OpenLayers.

I'm running the following: layer.getSource().getTileGrid() in order to get various details of the tileGrid in order to download tiles for a particular extent and particular zoom levels. In 6.5 a tileGrid (logged to the console) looks like this (in part):

    "resolutions_" =     (
        "156543.0339279804",
        "78271.51696399009",
        "39135.75848199517",

whereas in 6.13, the same part looks like this:

    Ti =     (
        "156543.0339279804",
        "78271.51696399009",
        "39135.75848199517",

…and similarly for the other elements.

You may wonder why I'm accessing these properties by these keys instead of by getResolutions(), etc. This is because there are some elements that don't seem to be available this way, in particular fullTileRanges.

I need to be able to reconstruct a tileGrid from a JSON string to use for an offline (downloaded) version of the layer like this:

tileGrid = new ol.tilegrid.TileGrid( JSON.parse(tileGridJSON) );

…which works fine if the fullTileRanges element is present, but if fullTileRanges is missing, then the layer that uses the tileGrid doesn't display (I think it tries to load the wrong tiles?). So if I can't get this element from the original online tileGrid to include when saving the JSON string, then the whole thing falls over.

The following "solution" (really a work-around) works perfectly for now. However, I consider it to be a kludge, as it uses the OpenLayers 6.13 encoded key for fullTileRanges ("Oo") and I expect it will break next time I upgrade my version of OpenLayers:

function getRasterServiceTileGrid(layerIndex) {
    var olTileGrid = rasterServiceLayers[layerIndex].getSource().getTileGrid();
    var origins = [];
    var tileSizes = [];
    var matrixIds = null;
    var fullTileRanges = null;
    if ( olTileGrid.getMatrixIds() ) {
        matrixIds = olTileGrid.getMatrixIds();
    }
    if ( olTileGrid["Oo"] ) {
        fullTileRanges = olTileGrid["Oo"];
    }
    for (var z = olTileGrid.getMinZoom(); z <= olTileGrid.getMaxZoom(); z++) {
        origins.push(olTileGrid.getOrigin(z));
        tileSizes.push(olTileGrid.getTileSize(z));
    }
    var keyedTileGrid = {
        extent: olTileGrid.getExtent(),
        maxZoom: olTileGrid.getMaxZoom(),
        minZoom: olTileGrid.getMinZoom(),
        resolutions: olTileGrid.getResolutions(),
        origins: origins,
        tileSizes: tileSizes,
        matrixIds: matrixIds,
        fullTileRanges: fullTileRanges,
    };
    
    return keyedTileGrid;
}

There doesn't appear to be a tileGrid.getProperties() function, nor a tileGrid.get() function, like there is for many other OL classes.

Is there a 'correct' way for me to get access to the fullTileRanges property in 6.13 instead of using this kludge, since I can no longer query for the "fullTileRanges_" key like I used to do with OL 6.5?

Best Answer

As @Mike commented, there is an undocumented getFullTileRange() function that can be used to build up the array of all tile ranges.

I've now successfully implemented the solution as:

function getRasterServiceTileGrid(layerIndex) {
    var olTileGrid = rasterServiceLayers[layerIndex].getSource().getTileGrid();
    var origins = [];
    var tileSizes = [];
    var fullTileRanges = [];
    var matrixIds = null;
    if ( olTileGrid.getMatrixIds() ) {
        matrixIds = olTileGrid.getMatrixIds();
    }
    for (var z = olTileGrid.getMinZoom(); z <= olTileGrid.getMaxZoom(); z++) {
        origins.push(olTileGrid.getOrigin(z));
        tileSizes.push(olTileGrid.getTileSize(z));
        fullTileRanges.push(olTileGrid.getFullTileRange(z));
    }
    var keyedTileGrid = {
        extent: olTileGrid.getExtent(),
        maxZoom: olTileGrid.getMaxZoom(),
        minZoom: olTileGrid.getMinZoom(),
        resolutions: olTileGrid.getResolutions(),
        origins: origins,
        tileSizes: tileSizes,
        matrixIds: matrixIds,
        fullTileRanges: fullTileRanges,
    };
    
    return keyedTileGrid;
}

Alternatively, as @Mike commented, instead of the for loop, it could also be done as:

tilegrid.getResolutions().map((r, z) => tilegrid.getFullTileRange(z))

(...and similarly for the other items in the for loop.)