Terrain mask

Hi again everybody,

I was wondering if it was possible to create mask between two layers, so that if I only want to see a sub-part of a layer, I can.

For example : I have a layer that has maritime informations, so it will be focus on sea only, but in the meantime this layer also have non interesting images for terrestrial part of the world. How can I mask this terrestrial images for this layer and use another layer to render terrestrial images (bing, etc.) ?



Have you tried creating PNGs with transparent regions? You could treat them as single tile imagery providers.

I don’t really understand how it would work.

Actually, I can’t really put those different layers into a singleTileImageryProvider, because I don’t have control over them.

In my case, one layer use a WebMapServerImageryProvider and another uses a BingMapImageryProvider.

And it’s a worldwide coverage.

What I want to do is to mask the sea part of my BingMap layer and show the sea part of my WMS provider or to mask the terrestrial part of my WMS and show terrestrial part of BingMap. It could be generalized to smaller area but for my case I need a sea mask (or terrestrial mask)

This PNG with transparent region would be usefull if I had the possibility to define it as a mask.

This functionnality is really close to what can exist in other graphic software (photoshop, etc.) : http://www.wikihow.com/Add-a-Layer-Mask-in-Photoshop except that here we speak of tiled layers, and not simple images.

I think, there is already this kind of feature when we use the STK terrain, you apply some kind of filter and add some effects on the sea parts only.

The STK Terrain Server applies the watermask to the terrain data before it is sent to the user’s browser. This works quite differently than imagery layers. Kevin Ring or someone else may have some recommendations.

If you’re using GeoServer for your WMS you might be able to do something like this: http://docs.geoserver.org/2.4.x/en/user/tutorials/imagemosaic_footprint/imagemosaic_footprint.html

Worth a shot at least. If that works to create the masks, than you would then make sure your imager layer is rendered on top of Bing and that should provide you with what you’re looking for.

The only thing I can think of would be to do it reasonably easily would be with a server side proxy of some kind. You can also do some basic masking with SLD in geoserver http://horizon.boundlessgeo.com/opengeo-docs/geoserver/styling/sld-extensions/composite-blend/modes.html

Doing this on the client would be tricky. In theory you could build a custom ImageryProvider that uses a Canvas to mask out (by setting pixels to transparent) another imagery provider. It could also be done on the GPU but that would require changes to shaders and probably other guts of Cesium.

I think doing it ahead of time on a server would likely be easier and more performant, though I can’t make any specific recommendations there.

Thanks for these answers.

Unfortunatly, even if the server-side solution with geoserver looks very good, it is not an option for us, as we don't want to use our server as a proxy for the moment.

The client side solution looks a little bit intimidating, but I note that it should be possible with some effort.

We'll think about that.

So, after all, I tried something to make it work on the client side.

I followed what have suggested Kevin Ring, e.g., create an Imagery provider that contains both providers I'm interested in and try to manipulate each image received via a Canvas.

Indeed, it looks like canvas could really help me here with its globalCompositeOperation : https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation

I had my battle plan, but of course, it didn't work as easily, and now I'm stuck without understanding why it's not working.

Here's my code : https://gist.github.com/theOgrable/f18c06b2f6b233fa6794

I'm aware it is largely incomplete, if I wanted to do things the right way, I should take into account Tile size, or tilingScheme for both source and destination providers. But this is more of a test to see if it's possible right now.

Basically, I'm stuck in requestImage of this provider (line 380):

            //img = image
          context.globalCompositeOperation = this._gco;

Those 'then' never execute their code (nothing in console...) so the canvas returned is not updated accordingly.

And this is what I don't understand.

Ok, so my previous error was simply me forgetting to add '.log' to 'console'. That why there was no logging.

Now, I've changed a little bit this method 'requestImage' of my provider and, well, while it's far from being perfect, I've got my little success : http://hpics.li/ab74619

And here's my code : https://gist.github.com/theOgrable/f18c06b2f6b233fa6794#file-maskedimageryprovider

So, now I have the following problem :
- lot's of undefined images coming from my imagery providers
- Tiles not at its right coordinates on the map, probably due to a difference between tilingScheme (or something related to tile positioning) of the MaskeImageryProvider and the underlying Imagery providers

As for rendering speed, it looks ok, but I'm not really in a real world situation for the moment.

Here's a simple example :

var viewer = new Cesium.Viewer('cesiumContainer');

var layers = viewer.imageryLayers;

var arc = new Cesium.ArcGisMapServerImageryProvider({
        url : '//server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'

var cesiumLogo = new Cesium.SingleTileImageryProvider({
    url : '../images/Cesium_Logo_overlay.png',
    rectangle : Cesium.Rectangle.fromDegrees(-75.0, 28.0, -67.0, 29.75)
layers.addImageryProvider(new Cesium.MaskedImageryProvider({
    sourceProvider : cesiumLogo,
    destinationProvider : arc,
    gco : 'xor'