10

I'm drawing a track where I want to place icons (point symbols), but with an offset so that the line is fully visible. Here is an example: track with offset icons

The origin is exactly on the track, therefore when zooming in and out the icons stay in a reasonable position. So far,so good.

What I need, though, is to connect the edge of the icon to the original point on the track using a line or arrow. I need this to indicate where exactly is the danger point (that is what the exclamation mark icon stands for)

4 Answers 4

11

Use Geometry Generator

Use the Geometry Generator tool with the following expression:

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

Then you can freely move your labels around.

Geometry Generator

Explanation

One end of the line will stick to the coordinates of the original point (the make_point($x,$y) part of the generator), while the other end will be drawn at the coordinates of the moved label (i.e. at the ( "auxiliary_storage_labeling_positionx" , "auxiliary_storage_labeling_positiony") coordinates).

enter image description here

1
  • Following this howto I was able to create labels with lines pointing from the original position to the offset position. Problem is that I need this for an SVG marker. The first part make_point($x,$y) works, but I need to replace the "auxiliary_storage_labeling_positionx" and "auxiliary_storage_labeling_positiony" with the marker offset. How do I access the offset values (x,y) for a SVG marker? Commented Feb 15, 2020 at 18:50
5

Answering your follow-up request:

Probably better to use Labels with Callouts instead.

A generic How-To:

  • Switch to No Symbols in the Symbology tab
  • Switch to Single Labels in the Label tab
    • Set Opacity to 0 in the Text tab
    • Activate Draw Background in the Background tab
      • Switch to SVG in the Shape selector
      • Link to your SVG
      • Adjust further settings as needed
      • Click Load symbol parameters
    • Activate Draw Callouts in the Callout tab
      • choose a Label anchor point
      • Adjust further settings as needed

Similar to the Geometry Generator solution, you can freely move the Labels around after creating the Auxiliary Storage:

  • Activate the Label toolbar in the QGIS GUI
  • Choose the Move a Label, Diagram or Callout tool
    • Click a Label to move (make sure you select the actual Label, not the Callout line!)
      • If asked, choose a unique key field to link the Auxiliary storage to the Layer
      • choose a new position
2

Using labels

The easy way will be to transform your icon as label. It would be easy and stronger because it let you define blocking rules for your "icon as label" not overlap the road.

The second proposal in this question might help you to do so. The draw back is that there will be less styling option and no possibility to have start flag or play icon, but many other options exist including using emoji or wingdings font.

Using styling

If you have to use an SVG icon, it will be through the styling option and need many fittings. It will not detect overlapping with other layer so manual work have to be done.

In my opinion, your icon must not be placed on a geographical location (as label positioning does) but on a location dependent on the zoom level to get always the same distance on the map between icon and point at any zooms.

For every point we will have the icon and a "callout" line. The icon will be distant from the point location. The position of the icon will be based on an distance in milimeter (the offset) and an angle defined by you.

  1. In the layer containing the point, use the field calculator to create angle wich will store the angle in degree, set it to 90 for the test.
  2. Go to symbology and then on your first icon. In symbol selector click on SVG marker and then go in the offset section data-driven (2), and edit(3).

enter image description here

An expression string builder will pop up, replace OFFSET_CHANGEME in the formula below by the number of millimetre you want and paste it :

array_foreach( array(sin(radians("angle")), cos(radians("angle"))), @element* OFFSET_CHANGEME )

Your icon should have a data defined offset position in your map

  1. Back in the symbol selector, add a simple marker (1), choose the line (2) or any other symbol. Set the size to be the same value as you choose for offset, set the rotation to be data driven by the field "angle" (3) and set the offset to be in y - OFFSET_CHANGEME(4). Then set it to be under your SVG icon (5).

enter image description here

Your icon should have a line connected to the geographical point location

Do it for as many icons as you have defined before in your style.

Then edit the angle value in the attribute table of your point layer to not hide the line.

PS : If you have many layers and may want to adjust the offset on all layer in one action, then you can add a project variable called offset.

1
+150

You can edit two point layer one containing SVG maker positions and the other containing points on the line (danger points). enter image description here

Points that you want connect each other must have an attribute with the same name, in the example both the feature have an attribute named 'desc'

enter image description here

after you have to duplicate marker point layer and set the simbol as Geometry generation instead SVG. Then apply this formula:

make_line(
  make_point($x,$y), 
  make_point(
    x(geometry(get_feature( 'point_online', 'desc' , "desc" ))),
    y(geometry(get_feature( 'point_online', 'desc' , "desc" )))
  )
)

formula connect marker geometry to the point_online geometry join feature by same desc attribute

enter image description here

OTHER SOLUTION WITH ONE LAYER

You can use the same logic with one layer that have both marker SVG point and both online danger points.

Table must have an attribute that you can use for join the two point, in my example is the attribute 'desc'. Marker point have value 'A', danger point related to it, have value '2A'. enter image description here enter image description here

As Stile you can use a rule based stile and using attribute 'connected point' to decide if use SVG or hide the on line symbol. enter image description here

Now you can duplicate the layer and apply Geomtry generation as stile:

make_line(
 make_point($x,$y), 
 make_point(
   x(geometry(get_feature( 'marker point', 'desc' , 2||"desc" ))),
   y(geometry(get_feature( 'marker point', 'desc' , 2||"desc" )))
)
)

enter image description here

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