Bug report #6439

Curve label becomes horizontal when x,y are manually set

Added by Vincent Picavet about 7 years ago. Updated 8 months ago.

Status:Closed
Priority:Low
Assignee:-
Category:Labelling
Affected QGIS version:master Regression?:No
Operating System: Easy fix?:No
Pull Request or Patch supplied:No Resolution:end of life
Crashes QGIS or corrupts data:No Copied to github as #:15680

Description

A label set to be curved for a line becomes horizontal if its anchor point is manually set with x,y values taken from field.

To reproduce :
  • Set labelling on a linear layer
  • Set the labels to be curved : they follow the lines
  • Make sure you have a X and a Y float fields in your layer
  • Set those fields as being the source for label placement
  • Toggle layer to edit mode
  • Use the labelling button to move a specific label
  • The label is moved, but is now horizontal and do not follow the line any longer

one-candidate_a.png (12 KB) Larry Shaffer, 2012-10-10 10:19 AM

one-candidate_b.png (12.7 KB) Larry Shaffer, 2012-10-10 10:19 AM

History

#1 Updated by Giovanni Manghi about 7 years ago

  • Assignee set to Larry Shaffer

#2 Updated by Larry Shaffer about 7 years ago

  • Status changed from Open to Feedback

Hi Vincent,

You are seeing three issues:

Label becomes horizontal happens when you either have data defined x/y but not rotation, or have also defined rotation but have the 'preserve existing rotation values' option checked. Once the x/y are set on label move, with no available rotation column or value defined, the rotation defaults to 0.

The option to preserve existing rotation values is on by default because otherwise data loss could accidentally occur. See issue #4317.

Label no longer follows line happens when you pin the label. An initial move of a label is a pinning operation, where its x/y and optionally rotation values are written to the attribute table. Once a label becomes pinned, it is no longer treated like other labels for the same layer. It is essentially a point feature label plus any rotation. For example, any line vector type 'distance' setting (layer- or data-defined) no longer applies.

If you data define x/y and rotation, and uncheck the 'preserve existing rotation values' option, then move the label a rotation value will be written to the attribute table, BUT only for the first letter of a curved label, which is the third issue. (However, it should work fine with parallel-to-line placement.)

Curved labels are chopped up into their individual characters, each of which is essentially a separate label. The label position class apparently only stores the rotation value that belongs to the first character, which is the only rotation value written to the attribute table when the label is pinned. If the curved label geometry were to be retained, but offset (like in a move operation), a different approach would be to data define x/y offsets (which are already planned). The label and buffer could be drawn, then offset accordingly. This means a different tool (Offset Label?) or add another feature to the current move tool. It might also mean wasted label creation, if the subsequent offset takes the label out of the extent, but the original label was in it (i.e. label is created and offset but not shown).

#3 Updated by Vincent Picavet about 7 years ago

Hi,

Skipping the rotation part, which behaviour is ok as it works now.

Label no longer follows line happens when you pin the label. An initial move of a label is a pinning operation, where its x/y and optionally rotation values are written to the attribute table. Once a label becomes pinned, it is no longer treated like other labels for the same layer. It is essentially a point feature label plus any rotation. For example, any line vector type 'distance' setting (layer- or data-defined) no longer applies.

Why is it working like that ? I would expect the label to keep attached to the original geometry, but with some parameters forced. Distance setting is not a problem, since it is naturally overridden by forced x,y coordinates (manually defined).

If you data define x/y and rotation, and uncheck the 'preserve existing rotation values' option, then move the label a rotation value will be written to the attribute table, BUT only for the first letter of a curved label, which is the third issue. (However, it should work fine with parallel-to-line placement.)

From a user point of view, «rotation» option and «following curve» option are really different thing. They should not interfere, even if behind the scene it's treated with the same mechanism.

Curved labels are chopped up into their individual characters, each of which is essentially a separate label. The label position class apparently only stores the rotation value that belongs to the first character, which is the only rotation value written to the attribute table when the label is pinned. If the curved label geometry were to be retained, but offset (like in a move operation), a different approach would be to data define x/y offsets (which are already planned). The label and buffer could be drawn, then offset accordingly. This means a different tool (Offset Label?) or add another feature to the current move tool. It might also mean wasted label creation, if the subsequent offset takes the label out of the extent, but the original label was in it (i.e. label is created and offset but not shown).

I do not really understand the point here... For curved label to be displayed you need to know :
  • the coordinates of the first character (here manually pinned to a specific x,y)
  • the original geometry to follow

And that's all, if you have that, you can recompute everything and display the label.
If internally each character is a different label, then each time the label is pinned, then all the single character labels positions and rotations should be recomputed to adapt to the curve to follow at that place.
No need for a new tool, just internal modifications.
Or I do not get it ?

#4 Updated by Larry Shaffer about 7 years ago

Vincent Picavet wrote:

Hi,

Skipping the rotation part, which behaviour is ok as it works now.

Label no longer follows line happens when you pin the label. An initial move of a label is a pinning operation, where its x/y and optionally rotation values are written to the attribute table. Once a label becomes pinned, it is no longer treated like other labels for the same layer. It is essentially a point feature label plus any rotation. For example, any line vector type 'distance' setting (layer- or data-defined) no longer applies.

Why is it working like that ? I would expect the label to keep attached to the original geometry, but with some parameters forced. Distance setting is not a problem, since it is naturally overridden by forced x,y coordinates (manually defined).

See below about how varied candidates make this difficult to make it work as expected. Basically, once the x/y is data defined, the feature's geometry is ignored by PAL and just the mapped attributes are used. Although, some data defined attributes augment an existing label's calculation (e.g. distance). Newer additions (x/y-independent data defined rotation) to make pinned labels work as expected are patches to PAL and its wrapper class, rather than turning on/off any functionality in the PAL library itself. In other words, it's how PAL works, for now.

If you data define x/y and rotation, and uncheck the 'preserve existing rotation values' option, then move the label a rotation value will be written to the attribute table, BUT only for the first letter of a curved label, which is the third issue. (However, it should work fine with parallel-to-line placement.)

From a user point of view, «rotation» option and «following curve» option are really different thing. They should not interfere, even if behind the scene it's treated with the same mechanism.

I agree this is not the expected behavior one would expect when pinning a curved label. It is definitely a bug. Since PAL currently only has data defined x/y and rotation as its core data defined placement, it basically turns it into what appears to be a parallel-to-line label with a rotation that almost never makes any sense.

Curved labels are chopped up into their individual characters, each of which is essentially a separate label. The label position class apparently only stores the rotation value that belongs to the first character, which is the only rotation value written to the attribute table when the label is pinned. If the curved label geometry were to be retained, but offset (like in a move operation), a different approach would be to data define x/y offsets (which are already planned). The label and buffer could be drawn, then offset accordingly. This means a different tool (Offset Label?) or add another feature to the current move tool. It might also mean wasted label creation, if the subsequent offset takes the label out of the extent, but the original label was in it (i.e. label is created and offset but not shown).

I do not really understand the point here... For curved label to be displayed you need to know :
  • the coordinates of the first character (here manually pinned to a specific x,y)
  • the original geometry to follow

And that's all, if you have that, you can recompute everything and display the label.
If internally each character is a different label, then each time the label is pinned, then all the single character labels positions and rotations should be recomputed to adapt to the curve to follow at that place.
No need for a new tool, just internal modifications.
Or I do not get it ?

I wish that were all that's needed. :^) PAL doesn't receive the entire feature for its label candidates calculation (noted exception is when calculating the centroid for the whole feature). The QgsPalLabeling class clips a duplicate of the feature to the canvas extent prior to sending it into PAL, to speed-up overall label production. This means that for different panned extents or zoom levels the same feature is sent into PAL differently, thereby creating very different candidate solutions.

Since the candidates vary greatly, it would be would be difficult for PAL to 'know' which candidate your data defined x/y refers to. If it referred to any, the label would drastically change appearance as the user panned/zoomed. For example, as a test I set candidates for line layers to '1', turned on showing candidates and created a comparison of what a very small pan of the map produces (see attachments). You can see how different a solution PAL produces even for one candidate. My suggestion for label offsets would also fall prey to such a problem.

Ultimately, a solution that would solve this issue (and others) would be if a simplified polyline or bezier curve geometry were generated and storable for a given curved label. See old issue #1780 for a similar suggestion. This could be added as an extension of the current PAL solution, where instead of a number of candidates for each character being returned, their base resultant polyline is returned and Qt is used to place the text on that path. In such a scenario, letter-/word-spacing, multi-line options (and others) would then be readily possible. In addition, when pinning the label (and there is a data defined geometry storage location) the simplified path and x/y coords could be saved. Once saved, general geometry manipulation tools could be used to change it, independent of its related feature geometry.

Such a solution would greatly enhance curved labels and fix most of the issues (including this one) with its PAL-based implementation.

#5 Updated by Giovanni Manghi over 5 years ago

  • Status changed from Feedback to Open

#6 Updated by Jürgen Fischer over 5 years ago

  • Target version changed from Version 2.0.0 to Future Release - Lower Priority

#7 Updated by Giovanni Manghi over 2 years ago

  • Easy fix? set to No
  • Regression? set to No

#8 Updated by Regis Haubourg over 1 year ago

  • Description updated (diff)
  • Priority changed from Normal to Low

#9 Updated by Giovanni Manghi over 1 year ago

  • Assignee deleted (Larry Shaffer)

Hi Regis, why lowering the priority for this? isn't this a quite important labeling issue?

#10 Updated by Giovanni Manghi 8 months ago

  • Status changed from Open to Closed
  • Resolution set to end of life

Also available in: Atom PDF