Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Merge pull request #5167 from alexbruy/extract-by-expression
[processing] add Extract by expression algorithm to QGIS 2.18
- Loading branch information
Showing
with
167 additions
and 1 deletion.
- +78 −0 python/plugins/processing/algs/qgis/ExtractByExpression.py
- +2 −1 python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
- +30 −0 python/plugins/processing/tests/testdata/expected/extract_expression.gml
- +45 −0 python/plugins/processing/tests/testdata/expected/extract_expression.xsd
- +12 −0 python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
@@ -0,0 +1,78 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
*************************************************************************** | ||
ExtractByExpression.py | ||
--------------------- | ||
Date : September 2017 | ||
Copyright : (C) 2017 by Alexander Bruy | ||
Email : alexander dot bruy at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* 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__ = 'Alexander Bruy' | ||
__date__ = 'September 2017' | ||
__copyright__ = '(C) 2017, Alexander Bruy' | ||
|
||
# This will get replaced with a git SHA1 when you do a git archive | ||
|
||
__revision__ = '$Format:%H$' | ||
|
||
from qgis.core import QgsExpression, QgsExpressionContext, QgsExpressionContextUtils, QgsFeatureRequest | ||
from processing.core.GeoAlgorithm import GeoAlgorithm | ||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException | ||
from processing.core.parameters import ParameterVector | ||
from processing.core.parameters import ParameterString | ||
from processing.core.outputs import OutputVector | ||
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'), [ParameterVector.VECTOR_TYPE_ANY])) | ||
self.addParameter(ParameterString(self.EXPRESSION, | ||
self.tr("Expression"))) | ||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Extracted (expression)'))) | ||
|
||
def processAlgorithm(self, progress): | ||
layer = layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) | ||
|
||
expression = self.getParameterValue(self.EXPRESSION) | ||
qExp = QgsExpression(expression) | ||
if qExp.hasParserError(): | ||
raise GeoAlgorithmExecutionException(qExp.parserErrorString()) | ||
|
||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( | ||
layer.fields(), layer.wkbType(), layer.crs()) | ||
|
||
context = QgsExpressionContext() | ||
context.appendScope(QgsExpressionContextUtils.globalScope()) | ||
context.appendScope(QgsExpressionContextUtils.projectScope()) | ||
context.appendScope(QgsExpressionContextUtils.layerScope(layer)) | ||
|
||
count = layer.featureCount() | ||
step = 100.0 / count if count else 1 | ||
|
||
request = QgsFeatureRequest(qExp, context) | ||
|
||
for current, f in enumerate(layer.getFeatures(request)): | ||
writer.addFeature(f) | ||
progress.setPercentage(int(current * step)) | ||
|
||
del writer |
@@ -0,0 +1,30 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<ogr:FeatureCollection | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://ogr.maptools.org/ extract_expression.xsd" | ||
xmlns:ogr="http://ogr.maptools.org/" | ||
xmlns:gml="http://www.opengis.net/gml"> | ||
<gml:boundedBy> | ||
<gml:Box> | ||
<gml:coord><gml:X>4</gml:X><gml:Y>-3</gml:Y></gml:coord> | ||
<gml:coord><gml:X>10</gml:X><gml:Y>5</gml:Y></gml:coord> | ||
</gml:Box> | ||
</gml:boundedBy> | ||
|
||
<gml:featureMember> | ||
<ogr:extract_expression fid="polys.1"> | ||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5,5 6,4 4,4 5,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty> | ||
<ogr:name>Aaaaa</ogr:name> | ||
<ogr:intval>-33</ogr:intval> | ||
<ogr:floatval>0.00000</ogr:floatval> | ||
</ogr:extract_expression> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:extract_expression fid="polys.3"> | ||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,1 10,1 10,-3 6,-3 6,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>7,0 7,-2 9,-2 9,0 7,0</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs></gml:Polygon></ogr:geometryProperty> | ||
<ogr:name>ASDF</ogr:name> | ||
<ogr:intval>0</ogr:intval> | ||
<ogr:floatval xsi:nil="true"/> | ||
</ogr:extract_expression> | ||
</gml:featureMember> | ||
</ogr:FeatureCollection> |
@@ -0,0 +1,45 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0"> | ||
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/> | ||
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/> | ||
<xs:complexType name="FeatureCollectionType"> | ||
<xs:complexContent> | ||
<xs:extension base="gml:AbstractFeatureCollectionType"> | ||
<xs:attribute name="lockId" type="xs:string" use="optional"/> | ||
<xs:attribute name="scope" type="xs:string" use="optional"/> | ||
</xs:extension> | ||
</xs:complexContent> | ||
</xs:complexType> | ||
<xs:element name="extract_expression" type="ogr:extract_expression_Type" substitutionGroup="gml:_Feature"/> | ||
<xs:complexType name="extract_expression_Type"> | ||
<xs:complexContent> | ||
<xs:extension base="gml:AbstractFeatureType"> | ||
<xs:sequence> | ||
<xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/> | ||
<xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1"> | ||
<xs:simpleType> | ||
<xs:restriction base="xs:string"> | ||
<xs:maxLength value="255"/> | ||
</xs:restriction> | ||
</xs:simpleType> | ||
</xs:element> | ||
<xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1"> | ||
<xs:simpleType> | ||
<xs:restriction base="xs:integer"> | ||
<xs:totalDigits value="10"/> | ||
</xs:restriction> | ||
</xs:simpleType> | ||
</xs:element> | ||
<xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1"> | ||
<xs:simpleType> | ||
<xs:restriction base="xs:decimal"> | ||
<xs:totalDigits value="21"/> | ||
<xs:fractionDigits value="5"/> | ||
</xs:restriction> | ||
</xs:simpleType> | ||
</xs:element> | ||
</xs:sequence> | ||
</xs:extension> | ||
</xs:complexContent> | ||
</xs:complexType> | ||
</xs:schema> |