Port geometry by expression to new API

This commit is contained in:
Nyall Dawson 2017-07-20 15:25:55 +10:00
parent c0669d4fd2
commit 96cf6612d3
3 changed files with 106 additions and 120 deletions

View File

@ -27,23 +27,17 @@ __revision__ = '$Format:%H$'
from qgis.core import (QgsWkbTypes,
QgsExpression,
QgsFeatureSink,
QgsExpressionContext,
QgsExpressionContextUtils,
QgsGeometry,
QgsApplication,
QgsProcessingUtils)
QgsProcessingException,
QgsProcessingParameterBoolean,
QgsProcessingParameterEnum,
QgsProcessingParameterExpression)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector, ParameterSelection, ParameterBoolean, ParameterExpression
from processing.core.outputs import OutputVector
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
class GeometryByExpression(QgisAlgorithm):
class GeometryByExpression(QgisFeatureBasedAlgorithm):
INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'
OUTPUT_GEOMETRY = 'OUTPUT_GEOMETRY'
WITH_Z = 'WITH_Z'
WITH_M = 'WITH_M'
@ -54,27 +48,22 @@ class GeometryByExpression(QgisAlgorithm):
def __init__(self):
super().__init__()
def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer')))
self.geometry_types = [self.tr('Polygon'),
'Line',
'Point']
self.addParameter(ParameterSelection(
def initParameters(self, config=None):
self.addParameter(QgsProcessingParameterEnum(
self.OUTPUT_GEOMETRY,
self.tr('Output geometry type'),
self.geometry_types, default=0))
self.addParameter(ParameterBoolean(self.WITH_Z,
self.tr('Output geometry has z dimension'), False))
self.addParameter(ParameterBoolean(self.WITH_M,
self.tr('Output geometry has m values'), False))
options=self.geometry_types, defaultValue=0))
self.addParameter(QgsProcessingParameterBoolean(self.WITH_Z,
self.tr('Output geometry has z dimension'), defaultValue=False))
self.addParameter(QgsProcessingParameterBoolean(self.WITH_M,
self.tr('Output geometry has m values'), defaultValue=False))
self.addParameter(ParameterExpression(self.EXPRESSION,
self.tr("Geometry expression"), '$geometry', parent_layer=self.INPUT_LAYER))
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Modified geometry')))
self.addParameter(QgsProcessingParameterExpression(self.EXPRESSION,
self.tr("Geometry expression"), defaultValue='$geometry', parentLayerParameterName='INPUT'))
def name(self):
return 'geometrybyexpression'
@ -82,55 +71,52 @@ class GeometryByExpression(QgisAlgorithm):
def displayName(self):
return self.tr('Geometry by expression')
def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
def outputName(self):
return self.tr('Modified geometry')
geometry_type = self.getParameterValue(self.OUTPUT_GEOMETRY)
wkb_type = None
if geometry_type == 0:
wkb_type = QgsWkbTypes.Polygon
elif geometry_type == 1:
wkb_type = QgsWkbTypes.LineString
def prepareAlgorithm(self, parameters, context, feedback):
self.geometry_type = self.parameterAsEnum(parameters, self.OUTPUT_GEOMETRY, context)
self.wkb_type = None
if self.geometry_type == 0:
self.wkb_type = QgsWkbTypes.Polygon
elif self.geometry_type == 1:
self.wkb_type = QgsWkbTypes.LineString
else:
wkb_type = QgsWkbTypes.Point
if self.getParameterValue(self.WITH_Z):
wkb_type = QgsWkbTypes.addZ(wkb_type)
if self.getParameterValue(self.WITH_M):
wkb_type = QgsWkbTypes.addM(wkb_type)
self.wkb_type = QgsWkbTypes.Point
if self.parameterAsBool(parameters, self.WITH_Z, context):
self.wkb_type = QgsWkbTypes.addZ(self.wkb_type)
if self.parameterAsBool(parameters, self.WITH_M, context):
self.wkb_type = QgsWkbTypes.addM(self.wkb_type)
writer = self.getOutputFromName(
self.OUTPUT_LAYER).getVectorWriter(layer.fields(), wkb_type, layer.crs(), context)
self.expression = QgsExpression(self.parameterAsString(parameters, self.EXPRESSION, context))
if self.expression.hasParserError():
feedback.reportError(self.expression.parserErrorString())
return False
expression = QgsExpression(self.getParameterValue(self.EXPRESSION))
if expression.hasParserError():
raise GeoAlgorithmExecutionException(expression.parserErrorString())
self.expression_context = self.createExpressionContext(parameters, context)
exp_context = QgsExpressionContext(QgsExpressionContextUtils.globalProjectLayerScopes(layer))
if not self.expression.prepare(self.expression_context):
feedback.reportErro(
self.tr('Evaluation error: {0}').format(self.expression.evalErrorString()))
return False
if not expression.prepare(exp_context):
raise GeoAlgorithmExecutionException(
self.tr('Evaluation error: {0}').format(expression.evalErrorString()))
return True
features = QgsProcessingUtils.getFeatures(layer, context)
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
for current, input_feature in enumerate(features):
output_feature = input_feature
def outputWkbType(self, input_wkb_type):
return self.wkb_type
exp_context.setFeature(input_feature)
value = expression.evaluate(exp_context)
if expression.hasEvalError():
raise GeoAlgorithmExecutionException(
self.tr('Evaluation error: {0}').format(expression.evalErrorString()))
def processFeature(self, feature, feedback):
self.expression_context.setFeature(feature)
value = self.expression.evaluate(self.expression_context)
if self.expression.hasEvalError():
raise QgsProcessingException(
self.tr('Evaluation error: {0}').format(self.expression.evalErrorString()))
if not value:
output_feature.setGeometry(QgsGeometry())
else:
if not isinstance(value, QgsGeometry):
raise GeoAlgorithmExecutionException(
self.tr('{} is not a geometry').format(value))
output_feature.setGeometry(value)
writer.addFeature(output_feature, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total))
del writer
if not value:
feature.setGeometry(QgsGeometry())
else:
if not isinstance(value, QgsGeometry):
raise QgsProcessingException(
self.tr('{} is not a geometry').format(value))
feature.setGeometry(value)
return feature

View File

@ -61,6 +61,7 @@ from .ExtendLines import ExtendLines
from .ExtentFromLayer import ExtentFromLayer
from .ExtractNodes import ExtractNodes
from .FixGeometry import FixGeometry
from .GeometryByExpression import GeometryByExpression
from .GridPolygon import GridPolygon
from .Heatmap import Heatmap
from .Hillshade import Hillshade
@ -164,7 +165,6 @@ from .ZonalStatistics import ZonalStatistics
# from .IdwInterpolation import IdwInterpolation
# from .TinInterpolation import TinInterpolation
# from .ExtractSpecificNodes import ExtractSpecificNodes
# from .GeometryByExpression import GeometryByExpression
# from .RasterCalculator import RasterCalculator
# from .TruncateTable import TruncateTable
# from .Polygonize import Polygonize
@ -221,7 +221,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
# Relief(),
# IdwInterpolation(), TinInterpolation(),
# ExtractSpecificNodes(),
# GeometryByExpression(),
# RasterCalculator(),
# ShortestPathPointToPoint(), ShortestPathPointToLayer(),
# ShortestPathLayerToPoint(), ServiceAreaFromPoint(),
@ -250,6 +249,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
ExtentFromLayer(),
ExtractNodes(),
FixGeometry(),
GeometryByExpression(),
GridPolygon(),
Heatmap(),
Hillshade(),

View File

@ -1416,54 +1416,54 @@ tests:
# compare:
# fields:
# fid: skip
#
# - algorithm: qgis:geometrybyexpression
# name: Geometry by expression (point)
# params:
# EXPRESSION: 'translate( $geometry,1,1)'
# INPUT_LAYER:
# name: points.gml
# type: vector
# OUTPUT_GEOMETRY: '0'
# WITH_M: false
# WITH_Z: false
# results:
# OUTPUT_LAYER:
# name: expected/geometry_by_expression_point.gml
# type: vector
#
# - algorithm: qgis:geometrybyexpression
# name: Geometry by expression (polygon)
# params:
# EXPRESSION: ' translate( centroid($geometry),1,1)'
# INPUT_LAYER:
# name: polys.gml
# type: vector
# OUTPUT_GEOMETRY: '2'
# WITH_M: false
# WITH_Z: false
# results:
# OUTPUT_LAYER:
# name: expected/geometry_by_expression_poly.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: qgis:geometrybyexpression
# name: Geometry by expression (line)
# params:
# EXPRESSION: ' translate( $geometry,1,1)'
# INPUT_LAYER:
# name: lines.gml
# type: vector
# OUTPUT_GEOMETRY: '1'
# WITH_M: false
# WITH_Z: false
# results:
# OUTPUT_LAYER:
# name: expected/geometry_by_expression_line.gml
# type: vector
- algorithm: qgis:geometrybyexpression
name: Geometry by expression (point)
params:
EXPRESSION: 'translate( $geometry,1,1)'
INPUT:
name: points.gml
type: vector
OUTPUT_GEOMETRY: '0'
WITH_M: false
WITH_Z: false
results:
OUTPUT:
name: expected/geometry_by_expression_point.gml
type: vector
- algorithm: qgis:geometrybyexpression
name: Geometry by expression (polygon)
params:
EXPRESSION: ' translate( centroid($geometry),1,1)'
INPUT:
name: polys.gml
type: vector
OUTPUT_GEOMETRY: '2'
WITH_M: false
WITH_Z: false
results:
OUTPUT:
name: expected/geometry_by_expression_poly.gml
type: vector
compare:
geometry:
precision: 7
- algorithm: qgis:geometrybyexpression
name: Geometry by expression (line)
params:
EXPRESSION: ' translate( $geometry,1,1)'
INPUT:
name: lines.gml
type: vector
OUTPUT_GEOMETRY: '1'
WITH_M: false
WITH_Z: false
results:
OUTPUT:
name: expected/geometry_by_expression_line.gml
type: vector
- algorithm: qgis:snapgeometries
name: Snap lines to lines