6

I have a pyqgis stand alone app that display linear features. I put an arrow svg symbol (QgsSvgMarkerSymbolLayerV2) on the line, now I would like to rotate it based on the 'value' field of each line feature in the layer. I tried some variations to the suggested approach below, but they are not working:

sl = QgsSvgMarkerSymbolLayerV2('arrow.svg')
lDD = QgsDataDefined(True, True, 'CASE WHEN "value" < 0 THEN 180.0 ELSE 0.0 END CASE', 'value')
sl.setDataDefinedProperty('angle', lDD)
1
  • 2
    If German's answer satisfies, please accept it so I can give the bounty. Jul 25, 2017 at 9:32

1 Answer 1

6
+50

Regarding this line in your code snippet:

lDD = QgsDataDefined(True, True, 'CASE WHEN "value" < 0 THEN 180.0 ELSE 0.0 END CASE', 'value')

You need to close a CASE expression with END (i.e., END CASE is incorrect). Also, there is no need to pass the last parameter 'value', because you'll be using an expression and not a field.


If you want to rotate an existing SVG marker symbol layer based on a data defined expression, you can do this:

# This assumes your marker line symbol layer is the 2nd layer in the line symbol
ddProperty = QgsDataDefined( True, True, 
    'CASE WHEN "value" < 0 THEN 180.0 ELSE 0.0 END' )
iface.activeLayer().rendererV2().symbols()[0].symbolLayers()[1].subSymbol().setDataDefinedAngle( ddProperty )
iface.activeLayer().triggerRepaint()

If you want to add a new SVG marker layer on your lines, setting the angle of rotation based on data definition expression, use this:

# Create your SVG symbol layer setting the angle to an expression
svgSymLay = QgsSvgMarkerSymbolLayerV2( 'arrows/Arrow_01.svg' )
ddProperty = QgsDataDefined( True, True, 
    'CASE WHEN "value" < 0 THEN 180.0 ELSE 0.0 END' ) 
svgSymLay.setDataDefinedProperty( 'angle', ddProperty )

# Create marker line symbol layer 
# and set a marker symbol (with the SVG layer) as sub-symbol
markerLineSymLay = QgsMarkerLineSymbolLayerV2()
markerSym = QgsMarkerSymbolV2()
markerSym.changeSymbolLayer( 0, svgSymLay )
markerLineSymLay.setSubSymbol( markerSym )

# Append the marker line symbol layer to a line symbol
lineSym = iface.activeLayer().rendererV2().symbols()[0]
lineSym.appendSymbolLayer( markerLineSymLay )

# Refresh layer and its symbology in the layer tree
iface.activeLayer().triggerRepaint()
iface.layerTreeView().refreshLayerSymbology( iface.activeLayer().id() )

Note: As you're working on a standalone application, you wouldn't access layers nor layer tree via iface, but you should have ways to get layers and (optionally) layer tree in your application anyways.

1
  • 1
    Gave you the bounty even before acceptance as OP seems AWOL. Thanks! :) Jul 26, 2017 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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