2

I have a spatial data set of a country (England), I am trying to use this dataset to shade out all parts of a background map apart from the country shape.

Using wms I can set the bgcolor to black, if I also set the style of the polygon to be transparent it simply means all I see is the black background colour, therefore as some kind of hack, I have set the polygon colour to a solid white. Then when making the wms request I set the bgcolor to black and set the opacity to 0.5 which almost achieves what I need with the rest of the world being shaded and my country being visible, although washed out as it has a 0.5 opacity white style over it so this is not quite ideal:

enter image description here

Are there any ideas on how this can be better achieved, simply using the England shape data set that I already have.

For reference:

SLD:

<FeatureTypeStyle>
<Rule>
<Name>Rule 1</Name>
<Title>Invisible polygon</Title>
<Abstract></Abstract>
<PolygonSymbolizer>
  <Fill>
    <CssParameter name="fill">#FFFFFF</CssParameter>
    <CssParameter name="fill-opacity">1.0</CssParameter>
  </Fill>
</PolygonSymbolizer>
</Rule>
</FeatureTypeStyle>

WMS:

new ol.layer.Image({
ref: 'england',
source: new ol.source.ImageWMS({
  url: '/ows?service=wms',
  serverType: 'geoserver',
  params: {
    'LAYERS': 'england_010k',
    'BGCOLOR': '0x000000',
    'TRANSPARENT': 'false'
  }
}),
visible: true,
opacity: '0.5'
})

Edit:

Trying Andrea's hint I got as far as (using destination-in):

enter image description here

With the layer code:

new ol.layer.Image({
ref: 'england',
source: new ol.source.ImageWMS({
  url: '/ows?service=wms',
  serverType: 'geoserver',
  params: {
    'LAYERS': 'england_010k'
  }
}),
visible: true,
opacity: '1'
})

...

var setBlendMode = function (evt) {
  evt.context.globalCompositeOperation = 'destination-in'
}
var resetBlendMode = function (evt) {
  evt.context.globalCompositeOperation = 'source-over'
}

options.layers[4].on('precompose', setBlendMode)
options.layers[4].on('postcompose', resetBlendMode)

But now the rest of the world is hidden, and I need it to be shaded.

  • please add the relevant part of your SLD file – Ian Turton Feb 13 '17 at 14:54
3

Seems a use case for "destination-out" alpha compositing:

http://docs.geoserver.org/stable/en/user/styling/sld/extensions/composite-blend/modes.html#destination-out

  • Thank you for your hint, I just tried this, using ol3 I set the England dataset to use destination-in. This shows the England section of the world map, but everything else is hidden. When I need it to be visible but shaded, any further tips or ideas? Seems so close now. thanks – Tedd Feb 13 '17 at 16:01
  • ps code and screenshots have been added to my question, showing what I tried. – Tedd Feb 13 '17 at 16:07
  • Sorry, if you are playing on the client side I'm the wrong person to help. – Andrea Aime Feb 14 '17 at 20:40
2

Traditionally, the way I have handled this in the past is creating a derived feature by doing a union between a giant rectangle covering the visible area of the map and the feature I am trying to emphasize. This would produce two features an outline feature that you can set opacity on, and an inner feature.

in the past I have either deleted the inner feature or made it so it was completely transparent.

(If it's a web map where the user can zoom in and out, might I suggest doing the entire earth).

Note: I recognize this doesn't meet the criteria of only using the input feature, but it is a workaround if you can't get it to work another way.

  • Thanks, I'd considered this as an alternative if I couldn't achieve it with only my current shape. Frustrating that I can get it so close, but not quite – Tedd Feb 14 '17 at 9:32
0

Taking on board the answers from Andrea and bwp8nt I achieved this through geoserver.

First creating the world layer with sql (postgis) of:

select ST_MakeEnvelope(-180, -90, 180, 90, 4326)

Thus creating a feature of the entire coorrdinates system.

I then create a layer group with the world layer first, styled with a solid fill, and the england layer 2nd with the following styling:

<FeatureTypeStyle>
    <Rule>
      <Name>England</Name>
      <Title></Title>
      <PolygonSymbolizer>
        <Fill>
          <CssParameter name="fill">#FFFFFF</CssParameter>
          <CssParameter name="fill-opacity">1</CssParameter>
        </Fill>
        <VendorOption name="composite">destination-out</VendorOption>
      </PolygonSymbolizer>
     </Rule>
</FeatureTypeStyle>

<VendorOption name="composite">destination-out</VendorOption> means where there is content from this layer over the source it will remove the source and this layer, thus displaying a cutout of the england shape:

enter image description here

Then when pulling through the file using openlayers setting the opacity to 0.5 results in:

enter image description here

Just a warning note, when I pushed this to our servers the styling failed, this was down to the version of geoserver which was 2.6.x. This version failed to perform the composite destination-out, and resulted in the england shape just being solid white. My local version of geoserver was 2.7.2 where it worked fine, so updating our server version to this version fixed this, so I updated both to the latest (2.9.3) where it works fine.

Thanks to all that helped.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.