8

I'm trying to obtain the same label style than Perpendicular Placement Orientation from ArcGIS in QGIS. As QGIS doesn't have this feature as default, the option would be using custom placement for this.

An ArcGIS example:

enter image description here

A workaround in QGIS

Settings:

Data defined coordinate X (label in the middle of he line):

$x_at( num_points( $geometry)/2)

Data defined coordinate Y (same as X's location):

$y_at( num_points( $geometry)/2)

Data defined Rotation:

angle_at_vertex( $geometry , num_points( $geometry)/2)

enter image description here

For only for 2/3 labels, the placement is acceptable. For lines with a lot of breaks with different angles, it's more difficult to obtain a nice label.

ArcGIS seems to search the line segment with fewer breaks or a straight segment. Is there a way to obtain coordinates or geometry of the straightest line segment using Expression builder for a better label placement?

  • how about taking an average of the angles at several vertices – csk Jan 22 '18 at 18:06
  • @csk I've tried with line_interpolate_angle($geometry, some lenght) and taking several angle_at_vertex( $geometry , num_points( $geometry)). A loop over this function could be an aproach, but I can't do it directly in Expresion builder – aldo_tapia Jan 22 '18 at 18:11
  • it seems you want to find a section of the line where the angle at each vertex is approximately equal to the line_interpolate_angle – csk Jan 22 '18 at 18:21
  • @csk yes, something like that. A straight line segment to place labels – aldo_tapia Jan 22 '18 at 18:24
1

Actual workaround

Suppose this kind of geometries:

enter image description here

I tried to find a good placement. I'm working with atlas also, so I used a 3% distance of atlas feature from the mid part of the interpolation line per feature's vertices to place labels:

Something like this:

enter image description here

And I create an arrow from the feature's middle vertex to the label:

enter image description here


Settings:

Arrow:

Geometry generator

make_line(make_point($x_at( num_points( $geometry)/2) , $y_at( num_points( $geometry)/2)),
  project( line_interpolate_point(make_line(make_point($x_at(1),$y_at(1)),make_point($x_at(-1),$y_at(-1))),
  length(make_line(make_point($x_at(1),$y_at(1)),make_point($x_at(-1),$y_at(-1))))/2),length(@atlas_geometry)*0.03,
   (radians(line_interpolate_angle(make_line(make_point($x_at(1),$y_at(1)),make_point($x_at(-1),$y_at(-1))),
  0.0001)))+ pi() *0.5))

Label

Data define X

x(project( line_interpolate_point(make_line(make_point($x_at(1),
  $y_at(1)),make_point($x_at(-1),$y_at(-1))),
  length(make_line(make_point($x_at(1),$y_at(1)),
  make_point($x_at(-1),$y_at(-1))))/2),length(@atlas_geometry)*0.03,
   (radians(line_interpolate_angle(make_line(make_point($x_at(1),
  $y_at(1)),make_point($x_at(-1),$y_at(-1))),0.0001)))+ pi() *0.5))

Data define Y

y(project( line_interpolate_point(make_line(make_point($x_at(1),
  $y_at(1)),make_point($x_at(-1),$y_at(-1))),
  length(make_line(make_point($x_at(1),$y_at(1)),
  make_point($x_at(-1),$y_at(-1))))/2),length(@atlas_geometry)*0.03,
   (radians(line_interpolate_angle(make_line(make_point($x_at(1),
  $y_at(1)),make_point($x_at(-1),$y_at(-1))),0.0001)))+ pi() *0.5))

Maybe this could be helpful for someone.

If there is a better approach, glad to receive it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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