Os trechos de código desta página precisam das seguintes importações se você estiver fora do console do pyqgis:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from qgis.core import (
edit,
QgsExpression,
QgsExpressionContext,
QgsFeature,
QgsFeatureRequest,
QgsField,
QgsFields,
QgsVectorLayer,
QgsPointXY,
QgsGeometry,
QgsProject,
QgsExpressionContextUtils
)
|
11. Expressões, filtragem e cálculo dos valores¶
O QGIS possui alguns recursos para análise de expressões semelhantes à SQL. Apenas um pequeno subconjunto da sintaxe SQL é suportado. As expressões podem ser avaliadas tanto como predicados booleanos (retornando Verdadeiro ou Falso) ou como funções (retornando um valor escalar) . Veja Expressões no Manual do Usuário para uma lista completa das funções disponíveis.
Três tipos básicos são suportados:
número — ambos os números inteiros e números decimais, por exemplo,
123
,3.14
texto — eles devem estar entre aspas simples: ‘Olá world’`
coluna referência — ao avaliar, a referência é substituída com o valor real do campo. Os nomes não alteram.
As seguintes operações estão disponíveis:
operadores aritméticos:
+
,-
,*
,/
,^
parênteses: para fazer cumprir a precedência do operador:
(1 + 1) * 3
Sinal mais e menos:
-12
,+5
funções matemáticas:
sqrt
,sen
,cos
,tan
,asen
,acos
,atan
Funções de conversão: “to_int”, “to_real”, “to_string”, “to_date”
funções geométricas:
$area
,$length
funções de manipulação de geometria: “$x”, “$y”, “$geometry”, “num_geometries”, “centroid”
E os seguintes predicados são suportados:
comparação:
=
,!=
,>
,>=
,<
,<=
correspondência padrão:
LIKE
(usando % e _),~
(expressões regulares)predicados lógicos:
AND
,OR
,NOT
verificação de valor nulo:
IS NULL
,IS NOT NULL
Exemplos de predicados:
1 + 2 = 3
sen(ângulo) > 0
'Hello' LIKE 'He%'
(x > 10 AND y > 10) OR z = 0
Exemplos de expressões escalares:
2 ^ 10
sqrt(val)
$length + 1
11.1. Expressões de Análise¶
O exemplo a seguir mostra como verificar se uma determinada expressão pode ser analisada corretamente:
1 2 3 4 5 6 7 | exp = QgsExpression('1 + 1 = 2')
assert(not exp.hasParserError())
exp = QgsExpression('1 + 1 = ')
assert(exp.hasParserError())
assert(exp.parserErrorString() == '\nsyntax error, unexpected $end')
|
11.2. Expressões de Avaliação¶
Expressões podem ser usadas em diferentes contextos, por exemplo, para filtrar recursos ou calcular novos valores de campo. De qualquer forma, a expressão deve ser avaliada. Isso significa que seu valor é calculado executando as etapas computacionais especificadas, que podem variar de aritmética simples a expressões agregadas.
11.2.1. Expressões Básicas¶
Essa expressão básica é avaliada como 1, o que significa que é verdadeiro:
exp = QgsExpression('1 + 1 = 2')
assert(exp.evaluate()) # exp.evaluate() returns 1 and assert() recognizes this as True
11.2.2. Expressões com características¶
Para avaliar uma expressão em relação a um recurso, um objeto QgsExpressionContext
deve ser criado e passado à função de avaliação para permitir que a expressão acesse os valores de campo do recurso.
O exemplo a seguir mostra como criar um recurso com um campo chamado “Coluna” e como adicionar esse recurso ao contexto da expressão.
1 2 3 4 5 6 7 8 9 10 11 | fields = QgsFields()
field = QgsField('Column')
fields.append(field)
feature = QgsFeature()
feature.setFields(fields)
feature.setAttribute(0, 99)
exp = QgsExpression('"Column"')
context = QgsExpressionContext()
context.setFeature(feature)
assert(exp.evaluate(context) == 99)
|
A seguir, é apresentado um exemplo mais completo de como usar expressões no contexto de uma camada vetorial, para calcular novos valores de campo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | from qgis.PyQt.QtCore import QVariant
# create a vector layer
vl = QgsVectorLayer("Point", "Companies", "memory")
pr = vl.dataProvider()
pr.addAttributes([QgsField("Name", QVariant.String),
QgsField("Employees", QVariant.Int),
QgsField("Revenue", QVariant.Double),
QgsField("Rev. per employee", QVariant.Double),
QgsField("Sum", QVariant.Double),
QgsField("Fun", QVariant.Double)])
vl.updateFields()
# add data to the first three fields
my_data = [
{'x': 0, 'y': 0, 'name': 'ABC', 'emp': 10, 'rev': 100.1},
{'x': 1, 'y': 1, 'name': 'DEF', 'emp': 2, 'rev': 50.5},
{'x': 5, 'y': 5, 'name': 'GHI', 'emp': 100, 'rev': 725.9}]
for rec in my_data:
f = QgsFeature()
pt = QgsPointXY(rec['x'], rec['y'])
f.setGeometry(QgsGeometry.fromPointXY(pt))
f.setAttributes([rec['name'], rec['emp'], rec['rev']])
pr.addFeature(f)
vl.updateExtents()
QgsProject.instance().addMapLayer(vl)
# The first expression computes the revenue per employee.
# The second one computes the sum of all revenue values in the layer.
# The final third expression doesn’t really make sense but illustrates
# the fact that we can use a wide range of expression functions, such
# as area and buffer in our expressions:
expression1 = QgsExpression('"Revenue"/"Employees"')
expression2 = QgsExpression('sum("Revenue")')
expression3 = QgsExpression('area(buffer($geometry,"Employees"))')
# QgsExpressionContextUtils.globalProjectLayerScopes() is a convenience
# function that adds the global, project, and layer scopes all at once.
# Alternatively, those scopes can also be added manually. In any case,
# it is important to always go from “most generic” to “most specific”
# scope, i.e. from global to project to layer
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(vl))
with edit(vl):
for f in vl.getFeatures():
context.setFeature(f)
f['Rev. per employee'] = expression1.evaluate(context)
f['Sum'] = expression2.evaluate(context)
f['Fun'] = expression3.evaluate(context)
vl.updateFeature(f)
print( f['Sum'])
|
876.5
11.2.3. Filtrando uma camada com expressões¶
O exemplo seguinte pode ser usado para filtrar uma camada e devolver qualquer característica que corresponda a um predicado.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | layer = QgsVectorLayer("Point?field=Test:integer",
"addfeat", "memory")
layer.startEditing()
for i in range(10):
feature = QgsFeature()
feature.setAttributes([i])
assert(layer.addFeature(feature))
layer.commitChanges()
expression = 'Test >= 3'
request = QgsFeatureRequest().setFilterExpression(expression)
matches = 0
for f in layer.getFeatures(request):
matches += 1
assert(matches == 7)
|
11.3. Manipulando erros de expressão¶
Erros relacionados à expressão podem ocorrer durante a análise ou análise de expressão:
1 2 3 4 5 6 7 | exp = QgsExpression("1 + 1 = 2")
if exp.hasParserError():
raise Exception(exp.parserErrorString())
value = exp.evaluate()
if exp.hasEvalError():
raise ValueError(exp.evalErrorString())
|