How to Un-tile for WMS?

I'm using a WMS server, which can take any sized bounding box (bbox), and render the proper image for it. I'm currently adding a layer using WebMapServiceImageryProvider, and this is working.

The owners of the WMS server have asked if I can reduce the calls to the server. For example, with other map engines, I get the extent, and request that as the WMS bbox, and make new requests as the user scrolls around and zooms in, etc. That is, Cesium, because of the tiling, is making one request per visible tile on the screen, resulting in many WMS requests to the server (per view change).

I can't seem to find a way to do this with Cesium. I did consider using a SingleTileImageryProvider, but I believe if I do so, I'll be stuck with JUST one image, and the user won't see better resolution as they zoom in closer.

I've also tried the following (modifying the Cesium source code):

1) Added a (_efficientWms) member to WebMapServiceImageryProvider, indicating I want this new behavior.

2) Added code to ImageryLayer.prototype._createTileImagerySkeletons(), where if the ImageProvider has this member set, will create a single TileImagery, with the following code, rather than produce one per tile:
    // "Magic" to determine visibleRectangle in radians
    var imagery = new Imagery(this, 0, 0, tileLevel, visibleRectangle);
    tile.imagery.splice(insertionPoint, 0, new TileImagery(imagery, new Cartesian4(visibleRectangle.west, visibleRectangle.south, visibleRectangle.east, visibleRectangle.north)));
    return true;

3) Changed ImageryLayer.prototype._requestImagery().doRequest() to pass the imagery.rectangle as an additional parameter to imageryProvider.requestImage().

4) Added the parameter to WebMapServiceImageryProvider.prototype.requestImage(), and code to use this rectangle as the "nativeRectangle" if _efficientWms is set:
    var nativeRectangle = (this._efficientWms && rectangle && this._tilingScheme.rectangleToNativeRectangle(rectangle)) || this._tilingScheme.tileXYToNativeRectangle(x, y, level);

5) Some additional changes to get the magic in step 2 to determine the visible area.

With the above changes, I see the expected WMS requests to the server, which look like they have the correct bbox (and which show data when viewed directly in a browser as an image) - but I don't see the WMS images appear on the map.

Any help (including better ways to do this, or what I've done wrong) would be appreciated. Thank you.

Hi,

Unfortunately this approach won’t work as a general solution for a 3D globe. For top-down views you might get away with it, but imagine what happens when the viewer is looking out toward the horizon. The visible area is wedge-shaped, not rectangular. If you used a rectangular region, you’d either get very poor resolution close to the viewer, or your image would be enormous.

So what can you do to reduce the number of requests to the WMS server? Well, you can try increasing the size of each tile. In WebMapServiceImageryProvider, change this._tileWidth and this._tileHeight, plus the width=256 and height=256 parameters in buildUrl, to a larger value like 512x512. Try to stick to power-of-two dimensions. Going from 256 to 512 will result in 1/4 the requests, and 1024 will be 1/16 the requests.

Another possibility, and maybe a better one, is to configure your WMS server to cache responses or stick a separate caching proxy server in front of it. This will give you much better performance, too.

Kevin

Kevin, thank you for your reply.

First, I'm not worried about the first issue (tilting), as A) My users are only using the top-down view, and B) I believe this would be an issue with the stock WebMapServiceImageryProvider - even without my changes.

At your suggestion, I tried increasing the tile size, but I'm still seeing the same number of WMS requests being issued.

Any other suggestions or ideas on why my changes (listed in my original post) were not showing up (on an non-tilted map)?

Hi,

Stock WebMapServiceImageryProvider doesn’t have this problem because of the tiling. It requests high-resolution tiles near the camera, and low resolution tiles in the distance.

I don’t know why you would see the same number of requests after the changing the tile width and height (in both places!). Can you double-check that the change was made successfully?

Your approach won’t work because createtileImagerySkeletons is only called once per tile, and not called again when the camera moves. Achieving what you’re trying to achieve will be tricky, I don’t know how to do it offhand. But if your users will never tilt the camera, why not just use 2D and make life simpler?

Kevin

I added parameters.height and parameters.width to my call to
Cesium.WebMapServiceImageryProvider(). It looks like this should change both the _tileHeight/_tileWidth and avoid the code in buildImageUrl that adds the height and width. Perhaps we're looking at different versions of the code, or perhaps I'm still not understanding you.

It looks like this._tileWidth and this._tileHeight are hard-coded to 256, so passing parameters.width/height to the constructor won’t change them.

https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Scene/WebMapServiceImageryProvider.js#L92

You’ll have to change the code, sorry.

Kevin

Hello,
I made an issue about tile size in webMapServiceImageryProvider https://github.com/AnalyticalGraphicsInc/cesium/issues/1886
in order to change the tile size, you should create a new WebMapServiceImageryProvider like in the next snippet:
new Cesium.WebMapServiceImageryProvider({
        url: "url to your Web Map Server",
        parameters: {
            format:'image/png',
            transparent:'true',
            heigt:"tile height wished",
            width:"tile width wished"},
        layers : "name(s) of layer(s) wished"
        })

Tile size is defined in parameters: {
            heigt:"tile height wished",
            width:"tile width wished"} !!

Thanks Kevin. As I said, "we may be looking at different versions of code". I'm relatively new to this team, and it seems that someone has modified our version of WebMapServiceImageryProvider to assign _tileHeight and _tileWidth based on the parameters height and width. So, my single change should have accomplished changing both (on our version of the code). And I did watch it in the debugger to confirm my change did take effect.