I would like to label groups of points (clusters) with only one label but several call-out lines. I built on top of the very appealing answer from @eurojam here: Giving one label to two points using QGIS
In order to make a distance aware grouping, I used the following code under the geometry-generator
creating a point geometry (in contrast to the polygon geometry in the original post):
centroid(collect($geometry, group_by:="Label", filter:= distance(
$geometry, geometry(@parent)) <= @map_scale/50
))
Now I omit duplicated labels (if two points are clustered, only one label is needed). This allows to make us of the built in label displacement engine (i.e. to avoid labels overlapping each other or certain features). Probably, someone more savvy might include this within the geometry-generator. However, I implemented the following code for a data driven override
for show label
under rendering
, basically adapting the solution here: https://gis.stackexchange.com/a/396489/203521
array_first(array_agg($id, group_by:="Label", filter:= distance(
$geometry, geometry(@parent)) <= @map_scale/50)) = $id
This code displays a single label per group of points within a scale dependent radius. If several points are close, but not very close, it creates multiple centroids, but only one label. Despite that artifact, it seems to be working quite good.
Now, I struggle displaying the call-out lines. They connect to the centroid of the points, the generated geometry.
I tried to tweak the data-defined origin and target-section in the callout section under labeling. So I could provide a couple of x- and y-coordinates, but this does not seem to be working. Only one line is shown. enter image description here
I know can create a line symbology with the geometry generator. The following expression works for labels I moved manually:
make_line($geometry,
make_point(array_first(array_agg(
"auxiliary_storage_labeling_positionx",
group_by:="Label", filter:= distance(
$geometry, geometry(@parent)) <= @map_scale/50)
),
array_first(array_agg(
"auxiliary_storage_labeling_positiony",
group_by:="Label", filter:= distance(
$geometry, geometry(@parent)) <= @map_scale/50)
)))
However I don't have the auxiliary variables by default and I don't know how to populate those fields other than moving the labels with the custom placement tool. So this works for labels I moved, but not for the ones placed by default (the green one I moved, the red and violet one I didn't).
I could create an additional layer with a geometry generator that creates a line between the points and the clusters centroid, as shown below. But that's not exactly what I intended.
Another Idea is to create a virtual layer. Something along the following code could be used, but scale dependent clustering would be another issue then.
select "Label",st_collect(geometry) as geometry
from Singlepart
Group by "Label"
But the result is not exactly what I expected. One label per point (not per multipoint) and callout lines scale dependent to some selection features (as visible in the labels of group 1) enter image description here enter image description here
Any other ideas?
Similar questions I found:
2 Answers 2
Create a multi-point layer:
Then, in this order:
- define your label style,
- move the labels
- select
Draw lines to all feature parts
:
Result:
This is somewhat trick, as it seems not all multi-parts are handled correctly. In my example, initially the multi-points labeled "P" showed the correct multi-callout, the ones labeled "E" did not... A refresh helped.
-
1Many thanks! I thought this might be a solution by creating a virtual layer and apply the labeling there. But I didn't succeed. I applied
select "Label",st_collect(geometry) as geometry from Singlepart Group by "Label"
but it creates a label per feature and not one per entry. The callout lines then are to some elements. "Label all elements of a multipart feature" is unchecked. I might add some edit.Beni– Beni2023年11月21日 08:51:20 +00:00Commented Nov 21, 2023 at 8:51
I would like to add / "bump" this question. Originally I wanted to just add a comment under Beni's comment to the answer by RafDouglas C. Tommasi, but I don't have enough reputation. I would like to add this reply because there doesn't seem to be so many posts about this on GIS Stack Exchange, and not many concrete solutions for the ones that do, and so I think that maybe others in my position have been searching for a solution to this. I have also included things that I've tried not mentioned here. I thought it best to answer this question instead of making my own post. Please feel free to let me know if this is ok or not :)
I am also trying to solve the same problem, and I have looked at every question regarding it on this website, including the ones Beni links at the bottom of his question. I too cannot for the life of me, for the case of multiple sepearate objects / features (points or polygons) with the same attribute value**, achieve a single label which has multiple callout lines anchored to each of the objects / features. I feel very stupid!
Other things that I have tried not mentioned here:
Setting the value of fields
auxiliary_storage_callouts_destinationx
andauxiliary_storage_callouts_destinationy
to be the same as thex
andy
coordinate of the feature itself by setting the expression$x
and$y
as the field values, andSetting the value of the fields
auxiliary_storage_callouts_originx
andauxiliary_storage_callouts_originy
to be the same as
auxiliary_storage_labeling_positionx
and
auxiliary_storage_labeling_positiony
respectively by setting the
reference to those fields as the value of the fields.
In the hope that I could "force" QGIS to hold the same callout origin coords but use different callout destination coords, however this appears to have had no effect.
When I implement the code to hide duplicate labels (by adding a data override to the show label
property in the rendering
section of the layer label options:
array_first(array_agg($id, group_by:="Label", filter:= distance( $geometry, geometry(@parent)) <= @map_scale/50)) = $id
This works, but also suppresses the callout lines.
To make matters worse, even when I add a geometry generator
line component to the marker symbology of the point layer:
make_line($geometry, make_point(array_first(array_agg( "auxiliary_storage_labeling_positionx", group_by:="Label", filter:= distance( $geometry, geometry(@parent)) <= @map_scale/50) ), array_first(array_agg( "auxiliary_storage_labeling_positiony", group_by:="Label", filter:= distance( $geometry, geometry(@parent)) <= @map_scale/50) )))
I can only get multiples lines to display if I use the simpler expression for the symbology geometry generator
make_line( make_point($x, $y), make_point( "auxiliary_storage_labeling_positionx" , "auxiliary_storage_labeling_positiony" ) )
But it is only with respect to the origin positions of their original (hidden) labels, not the visible label. Modifying the attribute table by altering the values of the fields mentioned above has no effect.
I am a civil engineer with around 8 years of experience with Autodesk software, mainly Civil 3D, so I've produced many a drawing / layout... hence why I feel very stupid right now for not being able to make this work!
Hope this is appropriate to post.
-
1As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.2024年11月01日 13:53:12 +00:00Commented Nov 1, 2024 at 13:53
Explore related questions
See similar questions with these tags.