Avoiding labeling features if overlapped by another layer in QGIS?

In QGIS >= 2.12 you can set the "lake" polygon layer as a label obstacle. This is done through the layer properties of the "lake" layer, under the 'Labels' section. Change the combo box at the top from "No labels" to "Discourage other labels from covering features in this layer".


Automated labelling is a really hard problem, but feature geometry is not so bad.

Even if you can get placement to work adequately most of the time, there are likely to be exceptions. Some of these you will notice and may be able to address. Others you won't notice when making a large map or tileset because you can't pour over every inch of your map at a variety of scales. Almost always you will have the urge to move some automatically-placed labels manually, from a cartographic perspective.

As I suggested in my comment, I'd make the problem easier for the labelling engine. In this case, I would do this by defining my rivers as a table view*, with river geometries clipped to respect lake boundaries. That way, there are no river features inside lakes to be labelled, and no label collisions.

* I assume the use of a RDBMS here, like PostgreSQL/PostGIS, for convenience and the ability to only update your authoritative source of data and have the view work itself out without your intervention. But you can also do some work upfront with static files to clip and delete features, but I don't recommend this if you ever plan to revisit a map.

Example:

Starting with two shapefiles (could be database tables) of rivers and lakes, with rivers intersecting lakes and causing labelling issues that are hard to resolve completely and confidently:

enter image description here

Bring these into Postgres if you need to with shp2pgsql:

shp2pgsql -s 4326 /data/lake public.lakes | psql -d mydb

shp2pgsql -s 4326 /data/river public.rivers | psql -d mydb

Then define a view with ST_Difference:

CREATE OR REPLACE VIEW rivers_clipped AS
SELECT r.id, ST_Difference(r.geom, l.geom) AS geom, r.name
FROM public.rivers AS r, public.lakes AS l;

Add the view to your layout:

enter image description here

Although the problem in my example is deliberately fabricated, the styles in the two river layers (original and view) are the same, and they are placed on top of the lake in the drawing order. When you update the lakes or rivers geometries, you won't need to do much more than refresh the rendering.

enter image description here


I find labeling in general quite hard, at least to generate labels that please my cartographer's senses. While the automatic labelling feature works fine 80% of the time, there are cases like your river/lake labeling problem where it doesn't generate nice labeling. The automatic labeling is often tied to the geometry of the feature, e.g. how many parts are in a line so that at first all parts are being labeled. Of course QGIS has means to prevent repeated labeling, which also depends on the scale of the current map view.

Well anyway, my tip isn't a quick solution. I often create a specialised layer just for labelling, so that my labels are more easily controlled. And often the features geometry for cartographic representation can collide with a good geometry for labeling. So I would propose to create a new layer where the streams do not cross the lakes, so that you can circumvent the problem altogether. Having an extra labeling-layer can also help to prevent problems where the labeling direction is not in the intended one because it is tied to how the geometry was created.

Well, I fear that my tip is not what you expected, but I hope that my alternative approach my help you somehow.

Tags:

Labeling

Qgis