Have you ever wondered how to mask features on a map, so that only a particular zone is highlighted ?
There have been a simple plugin to do that for a while. Called 'Mask', it allowed to turn a vector selection into a new memory layer with only one geometry made by the geometric inversion of the selection: the polygons that were selected get transformed into holes of a squared polygon bigger than the current extent.
One could then use this new layer, like any other one and apply a vector symbology on it. An opaque color to mask everything but the selection, or some semi-transparent color in order to only highlight the selection.
It was very useful but came with some limitations, and especially the fact that no update of the 'mask' layer was done during an atlas printing.
Thanks to the support of Agence de l'Eau Adour Garonne, Oslandia has been developing some evolutions to the core of QGIS, as well as to the mask plugin.
The core part consists of a new feature renderer that can be used on any polygon vector layer, as a symbology element. It is called inverted polygon renderer and allows to apply any other renderer to polygons that have been inverted. It was designed originally to allow only simple filling mode to be applied to the exterior ring of polygons, but it now allows to use more complex renderers like graduated, categorized or even rule-based renderers.
Inverted polygons: Simple usage
The simplest usage is to select the default sub renderer that is set to "single symbol" in order to have a uniform exterior fill of a layer.
When the sub-renderer used by the inverted polygon renderer has different symbol categories, features are grouped by symbol category before being inverted and rendered. It then only makes sense when the symbology used is partly transparent, so that the different inverted polygons can be distinguished from each other. This can be used for example to render a semi-transparent shapeburst fill around the current atlas feature.
In this example, we have an inverted polygon renderer with a rule-based sub renderer. The rule will only select the current atlas geometry, thanks to the expression $id=$atlasfeatureid. The symbol used is made of two symbol layers: a semi-transparent blue simple fill and a shapeburst fill on top of it. The polygon layer is then duplicated to also have a green "interior fill" for each polygon. The output can be seen hereafter:
When the map has labels enabled, this inverted polygon renderer is not sufficient to mask labels as well. When a user wants to highlight a particular zone on a map, she usually also wants to mask labels that are around, or at least make them less visible.
The way QGIS handles labels out of the box is not directly compatible with this need. QGIS always displays labels on top of every other layers.
To circumvent this, the original 'mask' plugin has been enhanced in order to be aware of layers with labels. A new 'mask' layer can be computed and its geometry can be used to test whether a feature has to be labeled or not. The plugin exposes two special variables that are available for any expressions :
- in_mask(srid) will return a boolean that tests if the current feature is in the mask. The parameter srid is the SRID projection code of the layer where this function is used.
- $mask_geometry will return the current mask geometry
Different spatial predicates can be used to test if the current feature lies inside the highlighted zone. A different type of predicate will be used for polygon layers, line layers and point layers.
Suppose we have a map of some french départements with a background raster map, and some linear layer displaying rivers.
If we want to highlight only one département, we can use the mask plugin for that. We will first select it and call the plugin.
A fancy inverted polygon symbology, based on a shapeburst fill is created. We see here that we can choose the function that will be used for filtering the labeling. By default these functions are "pointOnSurface" for polygon layers and "intersects" for line layers.
Here, we want both the départements layer and the rivers layers to see their labeling rules modified in order to hide the labels outside of the defined mask polygon.
By modifying the mask symbology, adding a little bit of transparency, we obtain the following result :
The plugin is able to interact with the atlas printing and will update its mask geometry as well as the labels that are allowed to be displayed.
The mask layer can also be saved with the project, using a memory layer if you use the Memory Layer Saver plugin, or using an OGR vector file format.
Here is a short video that shows how the plugin can be setup for a simple mask with an atlas print.
How to get the plugin ?
The new mask plugin is available in its 1.0 version on the QGIS official repository of plugins. It requires QGIS 2.4.
We are currently investigating the addition of this label masking feature to the QGIS core. The idea would be to have a concept of "label layer" that could then be hidden by others, or even made partly transparent.
It is not an easy task, though, since it would require to rework parts of the labeling and rendering engine. If you are interested by such a feature, please let us know !