5

I have labelled a points layer by defining a line between points and labels, so as I could remove the label to outside the map area (Figure 1). Using additional columns in the points layer attributes table ("x" and "y"), I can move the labels manually.

To make a line from the point to the label, I have added a 'Geometry Generator' in the Style section of the layer's Properties dialog. To define the geometry generator, I have used the following expression where $x and $y are the features' coordinates and "x" and "y" are the labels' coordinates:

make_line(make_point($x,$y), make_point("x","y"))

My issue is that labels do not align with the line connecting them to features. The labels are basically where I want them, but the line heads elsewhere (see Figure 1). How do I get these lines to basically be positioned from the first letter of the town name to the point?

figure_1

Image shows map with points being towns and the labels their town name. The lines are supposed to connect the town name label (e.g. Warrnambool) to the point (the town location), but the lines are fixed in odd directions

3 Answers 3

6

Proposed expression for the Geometry Generator:

-- algorithm inspired by https://github.com/haubourg/EasyCustomLabeling/blob/master/EasyCustomLabeling/EasyCustomLabeling.py line 260 and next

case
 when "auxiliary_storage_labeling_positionx" < $x and "auxiliary_storage_labeling_positiony" > $y and abs("auxiliary_storage_labeling_positiony"-$y) < abs("auxiliary_storage_labeling_positionx"-$x)
  then make_line($geometry, make_point($x-abs("auxiliary_storage_labeling_positiony"-$y),"auxiliary_storage_labeling_positiony"),make_point("auxiliary_storage_labeling_positionx", "auxiliary_storage_labeling_positiony"))
 when "auxiliary_storage_labeling_positionx" < $x and "auxiliary_storage_labeling_positiony" > $y and abs("auxiliary_storage_labeling_positiony"-$y) >= abs("auxiliary_storage_labeling_positionx"-$x)
  then make_line($geometry, make_point($x,abs("auxiliary_storage_labeling_positionx"-$x)+$y),make_point("auxiliary_storage_labeling_positionx", "auxiliary_storage_labeling_positiony"))
 when "auxiliary_storage_labeling_positionx" < $x and "auxiliary_storage_labeling_positiony" < $y and abs("auxiliary_storage_labeling_positiony"-$y) < abs("auxiliary_storage_labeling_positionx"-$x)
  then make_line($geometry, make_point($x-abs("auxiliary_storage_labeling_positiony"-$y),"auxiliary_storage_labeling_positiony"),make_point("auxiliary_storage_labeling_positionx", "auxiliary_storage_labeling_positiony"))  
 when "auxiliary_storage_labeling_positionx" < $x and "auxiliary_storage_labeling_positiony" < $y and abs("auxiliary_storage_labeling_positiony"-$y) >= abs("auxiliary_storage_labeling_positionx"-$x)
  then make_line($geometry, make_point($x,$y-abs("auxiliary_storage_labeling_positionx"-$x)),make_point("auxiliary_storage_labeling_positionx", "auxiliary_storage_labeling_positiony"))
 when "auxiliary_storage_labeling_positionx" >= $x and "auxiliary_storage_labeling_positiony" > $y and abs("auxiliary_storage_labeling_positiony"-$y) > abs("auxiliary_storage_labeling_positionx"-$x) --quadrant ur alternatif
  then make_line($geometry, make_point($x,"auxiliary_storage_labeling_positiony"-abs("auxiliary_storage_labeling_positionx"-$x)),make_point("auxiliary_storage_labeling_positionx", "auxiliary_storage_labeling_positiony")) 
 when "auxiliary_storage_labeling_positionx" >= $x and "auxiliary_storage_labeling_positiony" > $y and abs("auxiliary_storage_labeling_positiony"-$y) < abs("auxiliary_storage_labeling_positionx"-$x)
  then make_line($geometry, make_point($x+abs("auxiliary_storage_labeling_positiony"-$y),"auxiliary_storage_labeling_positiony"),make_point("auxiliary_storage_labeling_positionx", "auxiliary_storage_labeling_positiony"))  
 when "auxiliary_storage_labeling_positionx" >= $x and "auxiliary_storage_labeling_positiony" <= $y and abs("auxiliary_storage_labeling_positiony"-$y) > abs("auxiliary_storage_labeling_positionx"-$x)
  then make_line($geometry, make_point($x,$y-abs("auxiliary_storage_labeling_positionx"-$x)),make_point("auxiliary_storage_labeling_positionx", "auxiliary_storage_labeling_positiony"))  
 when "auxiliary_storage_labeling_positionx" >= $x and "auxiliary_storage_labeling_positiony" <= $y and abs("auxiliary_storage_labeling_positiony"-$y) < abs("auxiliary_storage_labeling_positionx"-$x)
  then make_line($geometry, make_point($x+abs("auxiliary_storage_labeling_positiony"-$y),"auxiliary_storage_labeling_positiony"),make_point("auxiliary_storage_labeling_positionx", "auxiliary_storage_labeling_positiony"))  
end 

and for label position (horizontal alignment) :

CASE 
   WHEN "auxiliary_storage_labeling_positionx" < $x THEN 'right'
   ELSE 'left'  
END

see sample.

0
5

Short answer: use the expression below.

make_line($geometry, 
          make_point("auxiliary_storage_labeling_positionx",
                     "auxiliary_storage_labeling_positiony"))

[Background]

It is not stated in your question, but the captured image suggests that these labels were moved using Easy Custom Labeling function. Because QGIS 3 does not show the leader lines (connectors) automatically, Geometry generator approach seems to be the good workaround.

[Steps]

(1) On your point layer, move your labels to desired locations.

(2) Duplicate your point layer and open Layer properties

(3) Switch it to Geometry generator and select LineString/MultiLineString

(4) The expression is the one on top of this answer.

enter image description here

Then you will get lines, as expected:

enter image description here

NB. If you move your labels afterwords, you need to redo these steps again.

2
  • This worked! Thanks for the advice it was completely accurate. But now I have a new related issue. How can I change the position that the leader lines meet the label? At the moment they meet the label at a point at the lower left hand side of the label text ''box''. I want them to meet the label at either the top left side or the top centre of the label. Any advice?
    – eclectus
    Jun 5, 2018 at 11:02
  • Hi @eclectus What I know is doing it manually and it is tedious... I will update the answer to include that. Hope you do not get astounded.
    – Kazuhito
    Jun 5, 2018 at 11:41
2

It could be caused by your labeling option, try to change the label alignement and/or placement (offset from point should give you best result)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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