I have a code that works well in the GUI for the field calculator but I am trying to make it work in the python console of QGIS. Firstly I start off with a roads then calculate the azimuth of the road with this PyQGIS code:
fp = "C:/Users/my/file/path/roads.geojson"
layer = QgsVectorLayer(fp, "roads", "ogr")
QgsProject.instance().addMapLayer(layer)
pv = layer.dataProvider()
pv.addAttributes([QgsField('azimuth', QVariant.Double)])
layer.updateFields()
print (layer.fields().names())
The field "azimuth" is successfully created. Next is to calculate the azimuth using the method answered in the question below. Adding Direction and Distance into Attribute table
expression1 = QgsExpression('CASE WHEN ((yat(-1)-yat(0)) = 0 and (xat(-1) - xat(0)) >0) THEN 90 WHEN ((yat(-1)-yat(0)) = 0 and (xat(-1) - xat(0)) <0) THEN 270 ELSE (atan((xat(-1)-xat(0))/(yat(-1)-yat(0)))) * 180/pi() + (180 * (((yat(-1)-yat(0)) < 0) + (((xat(-1)-xat(0)) < 0 AND (yat(-1) - yat(0)) > 0)*2))) END')
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(layer))
with edit(layer):
for f in layer.getFeatures():
context.setFeature(f)
f['azimuth'] = expression1.evaluate(context)
layer.updateFeature(f)
My goal is to categorize the roads by quadrant. In the field calculator GUI of QGIS the following code works perfectly.
CASE
WHEN (0.000 <= "azimuth" AND "azimuth" <= 90.000 )THEN 'quad-1'
WHEN (90.000 < "azimuth" AND "azimuth" <= 180.000 )THEN 'quad-2'
WHEN (180.000 < "azimuth" AND "azimuth" <= 270.000 )THEN 'quad-3'
WHEN (270.000 < "azimuth" AND "azimuth" <= 360.000 )THEN 'quad-4'
END
I have not been able to find documentation for PyQGIS where the expression references values from an existing column to add a text string to a new column. The expression from the documentation is very simple. 11. Expressions, Filtering and Calculating Values I know that the field (column) name must be in a double quote "azimuth" was the previously created column where I calculated the az as a decimal. My attempt looks like:
pv = layer.dataProvider()
pv.addAttributes([QgsField('az_quad', QVariant.String)])
layer.updateFields()
print (layer.fields().names())
## or
for field in layer.fields():
print(field.name(), field.typeName())
e = QgsExpression('CASE WHEN (0.000 <= "azimuth" AND "azimuth" <= 90.000 )THEN "quad-1" WHEN (90.000 < "azimuth" AND "azimuth" <= 180.000 )THEN "quad-2" WHEN (180.000 < "azimuth" AND "azimuth" <= 270.000 )THEN "quad-3" WHEN (270.000 < "azimuth" AND "azimuth" <= 360.000 )THEN "quad-4" END')
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(layer))
with edit(layer):
for f in layer.getFeatures():
context.setFeature(f)
f['az_quad'] = e.evaluate(context)
layer.updateFeature(f)
The only difference between the python equation and the GUI field calculator was that I changed the single quote to double quote to get rid of the syntax error. It does not add any values to the az_cat column.