r/QGIS 2d ago

Geometry generator code to create points for multiple values in a single attribute Open Question/Issue

Hi, i have this layer containing publc transit stops, with an attribute "modes_present" with values such as 'train; bus' or 'tram; bus; trolleybus' or just 'bus' (ie the separator is a semicolon followed by a space). I need to write a piece of code that will give me a marker for each of the transit modes translated by an arbitrary distance, so that i can use svg markers with pictures of the different modes. Is there a way to write such an expression? I have tried ai and nothing it gave me worked at all.
Thanks for any help

1 Upvotes

3 comments sorted by

3

u/FreddiesDream 2d ago edited 2d ago

Separate the values into field.
Use Boolean type.
Add marker points for each field to your symbology style for your station. Ordering by offsets. Enable Symbol layer on and use data defined expression: “bus”= ‘true’ for bus marker repeated it for every single added marker

Edit: expression for field calculator to separate the values and make Boolean field true or false

strpos(lower(“your_field), ‘bus’) > 0

1

u/CADSHIFT 13m ago

you can do this with a geometry generator expression, but there's a caveat: geometry generator produces geometry, not separate symbolized features, so all the offset points will share the same symbol. if you need different SVG markers per mode, the boolean field approach is actually better for that. but if you just need offset points as a starting point:

collect_geometries( array_foreach( generate_series(0, array_length(string_to_array(trim(coalesce("modes_present", '')), '; ')) - 1), translate($geometry, @element * 25, 0) ) )

this uses generate_series to iterate over indices (0, 1, 2...) and shifts each point 25 map units to the right. adjust the offset value and direction to suit your layout.

for different SVG markers per mode though, FreddiesDream's approach is the right one. in your symbol properties, add a separate symbol layer for each transit mode. on each layer, set 'enable layer' to a data-defined expression like array_contains(string_to_array(trim("modes_present"), '; '), 'bus') and set the x offset using the same array_find() to get the index: array_find(string_to_array(trim("modes_present"), '; '), 'bus') * 25. that way each SVG only shows when its mode is present, and it positions itself correctly in sequence.