[GIS] How to organise complex styling rules in QGIS

qgisstylevector-layer

For example, my "roads" vector layer has the following attributes:

  • road type: primary, secondary, local, track, or path
  • surface: sealed, or unsealed
  • segment type: road, bridge, tunnel, floodway, culvert, and few more types
  • relevancy: 1..9 (related to scale / zoom level)

Which yields almost 1000 unique styles but only 10% is present in data (for example, there are no unsealed primary roads)

In general styling rules are simple:

  • any path should be dashed black line (0.25mm pen width)
  • any unsealed road should be dashed
  • primary and secondary roads should be red (0.6mm pen width)
  • local roads and tracks should be orange (0.4mm pen width)
  • tracks should be dashed
  • each segment type has specific rendering:
    • road: no change
    • tunnel: keep colour and pen width but change line to dotted and draw portals
    • and so on ..

So far, I've tried to use "Single Symbol" based on segment type and then use "Expression" for colour, pen width & style. I couldn't figure out how deal with relevancy so I switched to "Rule-based".

"Rule-based" can deal with relevancy, but number of rules is high. I can't figure out how use "Refine selected rule" > "Add categories to rule" to change pen style only and keep the colour.

In both cases I have to copy attribute expressions across the rules (not sure if there is a concept of "global" expression) and it's tedious to keep then in sync.

Best Answer

The following approach is simple to use and avoids duplication of styling rules:

QGIS allows to define custom fields: "Layer Properties" -> "Fields". The best result is achieved by defining a new field for each style using expression. For example style_colour is defined as

case
  when  "roadtype" = "path" then 'black'
  when "surface" in (0,1) then 'red'
  else '#FF7518'
end

Expression should produce a valid value for given style.

(Tip: previously defined fields can be used in expressions)

Then use rule based filtering using (segment segment_type in my case) to define individual symbols (road on bridge, in tunnel, floodway, ...).

Then set "Color" to "Attribute Field" (using drop down next to colour picker") and assign style_colour field. Repeat this for the remaining styles.