To make it look good, keep data consistent etc. the best answer was already given by Jochen.
With that said there a possible solution might be to rotate the labels according to the current rotation of the line close to your point label. The result will however depend on:
- how many shifts in directions /curves are in you lines
- the scale: due to cartographic generalization (smoothing) of the line at smaller scales some curves may no be visible any more, but you labels are still rotated according to that curve...
How to do it:
- Determine where you point labels are relative to the length of the line, e.g. at the start of the line, right in the middle of the line etc...
- You can calculate the line angle at that point with the field calculator formula 'line_interpolate_angle'
- For this you need to get the geometry of the line features and you need the position (length in line - see 1.) of the point labels
- The result of the formula 'line_interpolate_angle' are the angles from 0-360° (North-East-South-West). You need to transform these angles to the label rotation system which works from -180° to 0° to +180° (0° is horizontal)
Example:
With the given layers:
AND:
- connecting ID field with the same unique value for each feature in each layer, here: 'road_lines_ID' and 'road_point_ID'
- assuming all the point labels are at 50% length of your lines.
Set the rotation of the labels of the "point_labels" layer in: Properties>Labels>Placement>Data defined>Rotation>'Edit'
Enter the following formula:
((((((line_interpolate_angle(geometry( get_feature( 'road_lines','road_lines_ID', "road_point_ID" )), distance:= ( length(geometry( get_feature( 'road_lines','road_lines_ID', "road_point_ID" )))/2)))+270)%360)+180)%360)-180)*-1
To speed things up you can also calculate a field in the point_labels layer with the given formula and rotate the labels according to the calculated field value.
Result: (Depending on the zoom level the result can be like this:
Formula in detail:
- line_interpolate_angle(geometry, distance) : gets the angel/direction of the line at a certain length
- geometry( get_feature( 'road_lines','road_lines_ID', "road_point_ID" )): gets the corresponding 'ID' feature from road_lines
- distance:= ( length(geometry( get_feature( 'road_lines','road_lines_ID', "road_point_ID" )))/2): get the distance along the line, where the label is place --> here /2 --> at 50% of the lines length.
- )+270)%360)+180)%360)-180)*-1: transfer from 0-360° (0 = north) system to -180 to +180° (0 = horizontal) system