5

I have a point feature layer with some attributes. The numeric value of each attribute stands for the number of items of that attribute related to each point. Is it possible in QGIS to display a symbology according to these values, where the number of symbols depends on the numeric value itself?

For example, with an attribute table like this:

pt_number apples bananas
1 1 2
2 3 1

the symbology for point 1 would be this:

enter image description here

I would like to avoid to create as many rules as the possible combinations, just to set the main icons and then display them automatically.

4
  • How many different attributes are there to display (2 like in your example, or many more ?)
    – Kasper
    Jan 8 at 14:00
  • @Kasper, Yes, attributes are more than two. Does this affect the possible solution?
    – HyPhens
    Jan 8 at 14:12
  • Yes,I have a solution for let's say a reasonable amount of attributes from a practical perspective (like one rule defined once per item)
    – Kasper
    Jan 8 at 14:16
  • @Kasper, any help would be appreciated.
    – HyPhens
    Jan 8 at 14:21

1 Answer 1

8

You can use the Geometry Generator in the Layer Style definition.

With one Geometry Generator entry for each relevant category.

These will be used to generate:

  • "Bananas" points, starting from $geometry, spaced by a given amount;
  • "Apples" points, starting from where Bananas left us with;
  • "Oranges" points, starting from where Apples + Bananas left us with;

The generic code will be: collect_geometries(array_foreach(generate_series(0,number_items-1,1),translate($geometry,@element*0.005,0)))

generate_series(0,number_items-1,1) to get the number of items;

translate($geometry,@element*0.005,0) to generate points right from the initial $geometry. 0.005 is the horizontal spacing, 0 the vertical spacing. Alternatives can be used to pile symbols instead of aligning them.

collect_geometries(array_foreach(...)) to generate multipart geometry for the array of translated points


Results with the following sample data:

pt_number bananas apples oranges
1 1 2 2
2 3 1 0
3 4 0 4
4 0 1 0

enter image description here


Settings the Style for 3 item categories:

In the Layer Style, use the 3 separate levels of Geometry Generator:

The first one: enter image description here

The code for each of the 3 levels:

case when "Bananas" >0 then 
collect_geometries(array_foreach(
generate_series(0,"Bananas"-1,1),
translate($geometry,@element*0.005,0)))
end

then:

collect_geometries(array_foreach(
generate_series(0,"Apples"-1,1),
translate($geometry,@element*0.005+"Bananas"*0.005,0))) 

(note the offset by number of Bananas)

and then:

collect_geometries(array_foreach(
generate_series(0,"Oranges"-1,1),
translate($geometry,@element*0.005+("Bananas"+"Apples")*0.005,0)))

(note the offset by number of Bananas + number of Apples)

enter image description here


Alternate styling :

That's the baseline that should allow you to customize your Symbols. For something that matches your initial representation even more closely, you can do the following (keep the Simple Marker for the Point geometry + add one offset in X and Y direction in the translate

enter image description here

4
  • I updated the Answer with as many details as possible
    – Kasper
    Jan 8 at 16:40
  • 1
    A very thorough and well written answer! The only thing I would add if anyone wanted to customise further is to configure symbol levels if you want the symbols to overlap in a particular way (i.e. apples above bananas or whatever).
    – she_weeds
    Jan 9 at 4:58
  • @Kasper, Ok I tried with your dataset and it works. Just one final request. I can't move the symbols like in your alternate styling. I can only display the first attribute ("Bananas") in the right position, above the feature point. What should be the offset values for the other attributes?
    – HyPhens
    Jan 11 at 11:51
  • The function is translate($geometry, xoffset,yoffset) so you need each of the attribute formulas to have an actual yoffset (replacing the relevant 0 by 0.005 in all the formulas) to raise the symbols. And in the alternate example, I changed the generate_series to start from 1 instead of 0, and end on the attribute value (remove the -1 after the attribute names). This offsets everything by one increment to the right, otherwise the first symbol is above the point
    – Kasper
    Jan 11 at 12:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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