QGIS – Applying Labeling with Obstacles for Better Map Readability

expressionlabelingpoint-in-polygonqgisqgis-3

I'm working with QGIS 3.16 Hannover and I'm quite confused with the option Features act as obstacles.

According to QGIS documentation (13. The Style Library » 13.3. Setting a label » 13.3.2.3.4.4. Obstacles)

an obstacle is a feature over which QGIS avoids placing other
features’ labels or diagrams.

However, this option can only be activated if the labels for that layer are already active.

I've got a polygon layer (in blue in the example below) which I want to label (Sevilla); and a point layer (in red in the example) which I'm not labelling. What I want is that the red dots act as obstacles, so the label of the blue polygon was automatically displaced to where it doesn't interfere with them.

enter image description here

How should it be done?

Best Answer

Why obstacles do not work

The setting Features act as obstacles only works for features of the same layer.

Use Geometry generator to define label placement

Go to Label / Placement tab and use Geometry generator to define the area inside the polygon where the label is allowed to be placed. Use an expression that excludes the area around the points: create a buffer around the points and subtract that area from the polygon you want to label.

Screenshot:

Area hached in dark blue is the area created by the geometry generator: the area where label placement is allowed: enter image description here

How to create the area where the label is allowed

To get the point geometries from the layer point on your polygon layer, use aggregate('point', 'collect', $geometry), create a buffer around $geometry and merge (dissolve) the single buffers creating again a buffer around the result with distance of 0. Then use difference to subtract this from your polygon geometries ($geometry). The whole expression looks like (replace 5000 on line 7 with a buffer size that fits your needs):

difference (
    $geometry,
    buffer (
        aggregate( 
            'point', 
            'collect', 
            buffer ($geometry,5000)
        ),
        0
))

For better results, you can try setting placement mode to Horizontal (instead of Around Centroid) - this is especially useful with many "forbidden" areas where only small areas left for the label to be placed:

enter image description here