Skip to content
Permalink
Browse files

Port geometry by expression to new API

  • Loading branch information
nyalldawson committed Jul 20, 2017
1 parent c0669d4 commit 96cf6612d39077e5e57e5d72fca594ba3b11ccdc
@@ -27,23 +27,17 @@

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,83 +48,75 @@ def group(self):

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'

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:
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)

self.expression = QgsExpression(self.parameterAsString(parameters, self.EXPRESSION, context))
if self.expression.hasParserError():
feedback.reportError(self.expression.parserErrorString())
return False

self.expression_context = self.createExpressionContext(parameters, context)

if not self.expression.prepare(self.expression_context):
feedback.reportErro(
self.tr('Evaluation error: {0}').format(self.expression.evalErrorString()))
return False

return True

def outputWkbType(self, input_wkb_type):
return self.wkb_type

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:
feature.setGeometry(QgsGeometry())
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)

writer = self.getOutputFromName(
self.OUTPUT_LAYER).getVectorWriter(layer.fields(), wkb_type, layer.crs(), context)

expression = QgsExpression(self.getParameterValue(self.EXPRESSION))
if expression.hasParserError():
raise GeoAlgorithmExecutionException(expression.parserErrorString())

exp_context = QgsExpressionContext(QgsExpressionContextUtils.globalProjectLayerScopes(layer))

if not expression.prepare(exp_context):
raise GeoAlgorithmExecutionException(
self.tr('Evaluation error: {0}').format(expression.evalErrorString()))

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

exp_context.setFeature(input_feature)
value = expression.evaluate(exp_context)
if expression.hasEvalError():
raise GeoAlgorithmExecutionException(
self.tr('Evaluation error: {0}').format(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 isinstance(value, QgsGeometry):
raise QgsProcessingException(
self.tr('{} is not a geometry').format(value))
feature.setGeometry(value)
return feature
@@ -61,6 +61,7 @@
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 .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 @@ def getAlgs(self):
# Relief(),
# IdwInterpolation(), TinInterpolation(),
# ExtractSpecificNodes(),
# GeometryByExpression(),
# RasterCalculator(),
# ShortestPathPointToPoint(), ShortestPathPointToLayer(),
# ShortestPathLayerToPoint(), ServiceAreaFromPoint(),
@@ -250,6 +249,7 @@ def getAlgs(self):
ExtentFromLayer(),
ExtractNodes(),
FixGeometry(),
GeometryByExpression(),
GridPolygon(),
Heatmap(),
Hillshade(),
@@ -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

0 comments on commit 96cf661

Please sign in to comment.
You can’t perform that action at this time.