1
votes

I am trying to display the daily MODIS satellite images from the GIBS image server http://wiki.earthdata.nasa.gov/display/GIBS/Map+Library+Usage. The tiles are provided in the WMTS protocol. Here is an example of my code using Google maps API:

var getTileUrl = function(tile, zoom) {
        return "http://map1.vis.earthdata.nasa.gov/wmts-webmerc/" +
               "MODIS_Terra_CorrectedReflectance_TrueColor/default/" + 
               get_date() + "/" +
               "GoogleMapsCompatible_Level9/" +
                zoom + "/" + tile.y + "/" +
                tile.x + ".jpeg";
    };

    var layerOptions = {
        alt: "MODIS_Terra_TrueColor",
        getTileUrl: getTileUrl,
        maxZoom: 9,
        minZoom: 1,
        name: "MODIS_Terra_TrueColor",
        tileSize: new google.maps.Size(256, 256),
        opacity: 0.8
    };
    var modisOverlay = new google.maps.ImageMapType(layerOptions);
    map.overlayMapTypes.insertAt(0, modisOverlay);

When I zoom the map to more detail than zoom level 9, the tiles disappear. So I increased maxZoom to a 10, and now I'm getting messages like:

Failed to load resource: the server responded with a status of 400 (Bad Request) http://map1.vis.earthdata.nasa.gov/wmts-webmerc/MODIS_Terra_CorrectedReflectance_TrueColor/default/2013-03-07/GoogleMapsCompatible_Level9/10/291/587.jpeg

From my understanding the server doesn't have tiles at zoom levels higher than 9.

Is there a way to show the WMTS tiles when I zoom to a higher zoom level? What I need is to "stretch" the tile images when the user zooms in to a zoom level bigger than 9. I'm currently using the Google maps API V3, but I can change to Leaflet or OpenLayers if it's easier to use them for solving my problem.

2

2 Answers

3
votes

I'm not sure about Google Maps, but for OpenLayers the short answer is that there is no built in way. There is a one to one mapping between a WMTS resource and its URL. So, there are a known number of zoom levels with fixed resolutions and from the view port extents and the zoom level the correct tiles will be returned based on /zoom/y/x.jpeg. So, once you have got to the maximum zoom, you would have to have to extend the WMTS code to rescale the existing backbuffer images rather than requesting a new layer from the server. So, it is doable, if a bit messy.

If you look at the source for OpenLayers.Layer.Tile you will see a method applyBackBuffer which does tile rescaling and is called by a zoom event, assuming transitionEffect:resize is set on the WMS/WMTS source (which is the default). You would need to use this logic and prevent calls to getURL in [OpenLayers.Layer.WMTS] once you have got to the maximum zoom for your WMTS. The getURL function is actually called by OpenLayer.Tile.Image, which is the class that represents individual tiles WMS or WMTS.

So, that is the longer answer, doable, but messy, as you are mixing two different approaches to tiles.

It is also worth mentioning that even if you did this, it would look awful very quickly. When you zoom from a resolution of 4 to 2, you are resampling in both x and y dimensions, so effectively only have 25% of the original pixels, going from 4 to 1, you are looking at 1/16th of the original tiles pixels, as each new pixel will be a resampling of 4 pixels in both x and y direction.

2
votes

I found a simple solution using Leaflet. In the Leaflet tileLayer, I can set maxNativeZoom and maxZoom.

maxNativeZoom is the maximum zoom level supported by the tile data provider.

maxZoom is the maximum zoom level to display the stretched tiles in my map.

The answer is here: Leaflet zoom in further and stretch tiles

It works and looks quite OK when I zoom-in a few levels beyond the maxNativeZoom. The disadvantage is that the image is re-sampled.