From 74e64645e410dff89685f029ea0169eb825c7689 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 29 Oct 2016 08:05:26 +1000 Subject: [PATCH] [FEATURE][processing] New extract by expression algorithm Filters an input layer by expression --- python/plugins/processing/algs/help/qgis.yaml | 11 ++- .../algs/qgis/ExtractByExpression.py | 67 +++++++++++++++++++ .../algs/qgis/QGISAlgorithmProvider.py | 3 +- .../testdata/expected/extract_expression.gfs | 32 +++++++++ .../testdata/expected/extract_expression.gml | 29 ++++++++ .../tests/testdata/qgis_algorithm_tests.yaml | 14 +++- 6 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 python/plugins/processing/algs/qgis/ExtractByExpression.py create mode 100644 python/plugins/processing/tests/testdata/expected/extract_expression.gfs create mode 100644 python/plugins/processing/tests/testdata/expected/extract_expression.gml diff --git a/python/plugins/processing/algs/help/qgis.yaml b/python/plugins/processing/algs/help/qgis.yaml index bc1d4b3a2d1..b5c0c20090f 100644 --- a/python/plugins/processing/algs/help/qgis.yaml +++ b/python/plugins/processing/algs/help/qgis.yaml @@ -159,10 +159,15 @@ qgis:exportaddgeometrycolumns: > Depending on the geometry type of the vector layer, the attributes added to the table will be different. qgis:extractbyattribute: > - This algorithms creates new vector layer that only contain certain features from an input layer. The criteria for adding features to the resulting layer is defined based on the values of an attribute from the input layer. + This algorithms creates a new vector layer that only contains matching features from an input layer. The criteria for adding features to the resulting layer is defined based on the values of an attribute from the input layer. + +qgis:extractbyexpression: > + This algorithms creates a new vector layer that only contains matching features from an input layer. The criteria for adding features to the resulting layer is based on a QGIS expression. + + For more information about expressions see the user manual qgis:extractbylocation: > - This algorithms creates new vector layer that only contain certain features from an input layer. The criteria for adding features to the resulting layer is defined based on the spatial relationship between each feature and the features in an additional layer. + This algorithms creates a new vector layer that only contains matching features from an input layer. The criteria for adding features to the resulting layer is defined based on the spatial relationship between each feature and the features in an additional layer. qgis:extractnodes: > This algorithm takes a line or polygon layer and generates a point layer with points representing the nodes in the input lines or polygons. The attributes associated to each point are the same ones associated to the line or polygon that the point belongs to. @@ -419,7 +424,7 @@ qgis:selectbyattributesum: qgis:selectbyexpression: > This algorithms creates a selection in a vector layer. The criteria for selecting features is based on a QGIS expression. - For more information about expressions see theuser manual + For more information about expressions see the user manual qgis:selectbylocation: > diff --git a/python/plugins/processing/algs/qgis/ExtractByExpression.py b/python/plugins/processing/algs/qgis/ExtractByExpression.py new file mode 100644 index 00000000000..4779758a3ae --- /dev/null +++ b/python/plugins/processing/algs/qgis/ExtractByExpression.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + ExtractByExpression.py + --------------------- + Date : October 2016 + Copyright : (C) 2016 by Nyall Dawson +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = 'Nyall Dawson' +__date__ = 'October 2016' +__copyright__ = '(C) 2016, Nyall Dawson' + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import processing +from qgis.core import QgsExpression, QgsVectorLayer, QgsFeatureRequest +from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException +from processing.core.parameters import ParameterVector +from processing.core.outputs import OutputVector +from processing.core.GeoAlgorithm import GeoAlgorithm +from processing.core.parameters import ParameterString +from processing.tools import dataobjects + + +class ExtractByExpression(GeoAlgorithm): + + INPUT = 'INPUT' + EXPRESSION = 'EXPRESSION' + OUTPUT = 'OUTPUT' + + def defineCharacteristics(self): + self.name, self.i18n_name = self.trAlgorithm('Extract by expression') + self.group, self.i18n_group = self.trAlgorithm('Vector selection tools') + + self.addParameter(ParameterVector(self.INPUT, + self.tr('Input Layer'))) + self.addParameter(ParameterString(self.EXPRESSION, + self.tr("Expression"))) + self.addOutput(OutputVector(self.OUTPUT, self.tr('Extracted (expression)'))) + + def processAlgorithm(self, progress): + layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) + expression_string = self.getParameterValue(self.EXPRESSION) + writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(layer.fields(), layer.wkbType(), layer.crs()) + + expression = QgsExpression(expression_string) + if not expression.hasParserError(): + req = QgsFeatureRequest().setFilterExpression(expression_string) + else: + raise GeoAlgorithmExecutionException(expression.parserErrorString()) + + for f in layer.getFeatures(req): + writer.addFeature(f) + + del writer diff --git a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py index 9cb4a1cab64..bf3296b2b92 100644 --- a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py +++ b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py @@ -56,6 +56,7 @@ from .VectorGridPolygons import VectorGridPolygons from .RandomExtract import RandomExtract from .RandomExtractWithinSubsets import RandomExtractWithinSubsets from .ExtractByLocation import ExtractByLocation +from .ExtractByExpression import ExtractByExpression from .PointsInPolygon import PointsInPolygon from .PointsInPolygonUnique import PointsInPolygonUnique from .PointsInPolygonWeighted import PointsInPolygonWeighted @@ -231,7 +232,7 @@ class QGISAlgorithmProvider(AlgorithmProvider): ReliefAuto(), ZonalStatisticsQgis(), IdwInterpolationZValue(), IdwInterpolationAttribute(), TinInterpolationZValue(), TinInterpolationAttribute(), - RemoveNullGeometry() + RemoveNullGeometry(), ExtractByExpression() ] if hasMatplotlib: diff --git a/python/plugins/processing/tests/testdata/expected/extract_expression.gfs b/python/plugins/processing/tests/testdata/expected/extract_expression.gfs new file mode 100644 index 00000000000..a62526d790e --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_expression.gfs @@ -0,0 +1,32 @@ + + + extract_expression + extract_expression + + 3 + EPSG:4326 + + 2 + 4.00000 + 10.00000 + -3.00000 + 5.00000 + + + name + name + String + 5 + + + intval + intval + Integer + + + floatval + floatval + Integer + + + diff --git a/python/plugins/processing/tests/testdata/expected/extract_expression.gml b/python/plugins/processing/tests/testdata/expected/extract_expression.gml new file mode 100644 index 00000000000..a652e20671e --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_expression.gml @@ -0,0 +1,29 @@ + + + + + 4-3 + 105 + + + + + + 5,5 6,4 4,4 5,5 + Aaaaa + -33 + 0 + + + + + 6,1 10,1 10,-3 6,-3 6,17,0 7,-2 9,-2 9,0 7,0 + ASDF + 0 + + + diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml index ea2bc5dd3ca..01a8e8b7757 100644 --- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml +++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml @@ -1212,4 +1212,16 @@ tests: results: OUTPUT_LAYER: name: expected/remove_null_polys.gml - type: vector \ No newline at end of file + type: vector + + - algorithm: qgis:extractbyexpression + name: Extract by Expression + params: + EXPRESSION: left( "Name",1)='A' + INPUT: + name: polys.gml + type: vector + results: + OUTPUT: + name: expected/extract_expression.gml + type: vector