8

I have two features. One line feature and another polygon feature. I want the line feature label not to appear when it is within a polygon similar to the one in the figure. That is, I want the label to only appear when the line is outside the polygon. Is it possible to do this in QGIS 3?

I tried the field calculator with the within function but it didn't work very well.

example

Below is the code I tried to do in the QGIS field calculator:

CASE
   WHEN within('Lines_4e1a1089_ba02_495e_8c79_d32b79cf3b54','polygon_406a7fae_06b4_45a1_a20e_d64b8682e501') THEN " "
   ELSE "Label"
END
1
  • 1
    Welcome to GIS.SE! I guess you mean the "Expression Dialog" that opens when you click the "ε" button right to the "Label with" combo box, not the field calculator? Oct 10, 2019 at 5:53

4 Answers 4

12

You trying to call within on a string representing a layer, not its geometry. But it won't work that way anyway. This way it would label/not label whole feature, not segments. With within it would label feature with " " in case that whole line is in polygon. In case of intersects it will label feature that somehow interact with any polygon.

Maybe there is option how to solve this with expression of Label with, but I thing this is primary for formatting label text for feature, not for label placement. I didn't figure out how to split the line geometry in this expression for the desired result.

In QGIS 3.8, there is Geometry generator in Placement tab in labels properties. With this you can generate new source geometry only for labels, in your case lines that are not intersecting polygons. Labels are than rendered only over this geometry (i.e. rendering labels over polygon i suppressed):

example1

if(
    intersects(
        $geometry,
        aggregate('poly','collect',$geometry,intersects($geometry, geometry(@parent)))
    ),
    difference(
        $geometry,
        aggregate('poly','collect',buffer($geometry,0.1),intersects($geometry, geometry(@parent)))
    ),
    $geometry
)

Notice the buffer function, this gives space around polygon to suppress label rendering. This avoids long labels overlap polygons.

Than in Rendering tab check the Label every part of multi-part features. This keeps rendering labels on all part of a line (lines that overlap the polygon and continues).

example2

example3

1
  • Awesome solution!
    – Ben W
    Oct 10, 2019 at 12:09
11

Or in a very simple way, you can use the polygon to block the labels of the polyline.

Label polyline normally:

enter image description here

After using the polygon as a blocking feature, the label will be shifted automatically outside the polygon:

enter image description here

3
  • 2
    Oh, that is simple! I knew that there was something like this :D. However my solution could help in specific cases (repeating lables).
    – Oto Kaláb
    Oct 10, 2019 at 11:49
  • 2
    @OtoKaláb I like your solution. It is really great and will help in complicated cases. :)
    – ahmadhanb
    Oct 10, 2019 at 11:57
  • 2
    That's a very nifty trick!
    – Ben W
    Oct 10, 2019 at 12:08
4

Your approach does not work because

  • spatial joins over layers (not tests for the relations of single geometries) cannot be performed in expression dialog
  • within is only true when a whole geometry falls entirely into another geometry, wich is not the fact in your case
  • double quotes are for attribute names, for strings use single quotes

All in all, I doubt that this can be achieved using expressions in symbology or labelling, I recommend using the Difference tool to compute the sections of your linestring layer that lie outside the polygon (Processing Toolbox > Vector Overlay > Difference):

enter image description here

Labelling for the original linestring layer:

enter image description here

Labelling for the Difference Layer:

enter image description here

If you want to display your original linestring layer (without labels) and use the labels from the Difference layer I suggest setting up a "No Symbol" style for the Difference layer, label it and display both of them.

2

You could also use a data defined override for label rendering, but it requires splitting your line layer.

  1. From the processing toolbox, run the Clip tool to clip the line layer with the polygon layer.

  2. Run the Difference tool to extract the parts of the line feature which fall outside the polygon.

  3. Run the Merge vector layers tool on the clipped and difference results.

  4. Add a new integer field to the merged layer and call it e.g. 'Label'.

  5. Select the feature inside the polygon. Open the attribute table and, with the layer in edit mode, give it a value of 0 in the 'Label' field. Give the feature/ features outside the polygon values of 1.

  6. In layer properties, label the line layer with the desired field, in the rendering tab check 'Label every part of multi-part features', then click 'data defined' for show label, and select the 'Label' field.

Label settings:

enter image description here

Result:

enter image description here

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