QGIS API Documentation 4.3.0-Master (d3b565c628d)
Loading...
Searching...
No Matches
qgsalgorithmextractbyexpression.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmextractbyexpression.cpp
3 ---------------------
4 begin : April 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include <QString>
21
22using namespace Qt::StringLiterals;
23
25
26QString QgsExtractByExpressionAlgorithm::name() const
27{
28 return u"extractbyexpression"_s;
29}
30
31QString QgsExtractByExpressionAlgorithm::displayName() const
32{
33 return QObject::tr( "Extract by expression" );
34}
35
36QStringList QgsExtractByExpressionAlgorithm::tags() const
37{
38 return QObject::tr( "extract,filter,expression,field" ).split( ',' );
39}
40
41QString QgsExtractByExpressionAlgorithm::group() const
42{
43 return QObject::tr( "Vector selection" );
44}
45
46QString QgsExtractByExpressionAlgorithm::groupId() const
47{
48 return u"vectorselection"_s;
49}
50
51void QgsExtractByExpressionAlgorithm::initAlgorithm( const QVariantMap & )
52{
53 addParameter( new QgsProcessingParameterFeatureSource( u"INPUT"_s, QObject::tr( "Input layer" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector ) ) );
54 addParameter( new QgsProcessingParameterExpression( u"EXPRESSION"_s, QObject::tr( "Expression" ), QVariant(), u"INPUT"_s ) );
55
56 addParameter( new QgsProcessingParameterFeatureSink( u"OUTPUT"_s, QObject::tr( "Matching features" ) ) );
57 QgsProcessingParameterFeatureSink *failOutput = new QgsProcessingParameterFeatureSink( u"FAIL_OUTPUT"_s, QObject::tr( "Non-matching" ), Qgis::ProcessingSourceType::VectorAnyGeometry, QVariant(), true );
58 failOutput->setCreateByDefault( false );
59 addParameter( failOutput );
60}
61
62QString QgsExtractByExpressionAlgorithm::shortHelpString() const
63{
64 return QObject::tr(
65 "This algorithm creates a new vector layer that only contains matching features from an input layer. "
66 "The criteria for adding features to the resulting layer is based on a QGIS expression.\n\n"
67 "For help with QGIS expression functions, see the inbuilt help for specific functions "
68 "which is available in the expression builder."
69 );
70}
71
72QString QgsExtractByExpressionAlgorithm::shortDescription() const
73{
74 return QObject::tr( "Creates a vector layer that only contains features matching a QGIS expression from an input layer." );
75}
76
77QgsExtractByExpressionAlgorithm *QgsExtractByExpressionAlgorithm::createInstance() const
78{
79 return new QgsExtractByExpressionAlgorithm();
80}
81
82QVariantMap QgsExtractByExpressionAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
83{
84 QGS_MARK_ALGORITHM_SOURCE
85
86 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, u"INPUT"_s, context ) );
87 if ( !source )
88 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
89
90 const QString expressionString = parameterAsExpression( parameters, u"EXPRESSION"_s, context );
91
92 QString matchingSinkId;
93 std::unique_ptr<QgsFeatureSink> matchingSink( parameterAsSink( parameters, u"OUTPUT"_s, context, matchingSinkId, source->fields(), source->wkbType(), source->sourceCrs() ) );
94 if ( !matchingSink )
95 throw QgsProcessingException( invalidSinkError( parameters, u"OUTPUT"_s ) );
96
97 QString nonMatchingSinkId;
98 std::unique_ptr<QgsFeatureSink> nonMatchingSink( parameterAsSink( parameters, u"FAIL_OUTPUT"_s, context, nonMatchingSinkId, source->fields(), source->wkbType(), source->sourceCrs() ) );
99
100 QgsExpression expression( expressionString );
101 if ( expression.hasParserError() )
102 {
103 throw QgsProcessingException( expression.parserErrorString() );
104 }
105
106 QgsExpressionContext expressionContext = createExpressionContext( parameters, context, source.get() );
107
108 const long count = source->featureCount();
109
110 const double step = count > 0 ? 100.0 / count : 1;
111 int current = 0;
112
113 if ( !nonMatchingSink )
114 {
115 // not saving failing features - so only fetch good features
117 req.setFilterExpression( expressionString );
118 req.setExpressionContext( expressionContext );
119
121 QgsFeature f;
122 while ( it.nextFeature( f ) )
123 {
124 if ( feedback->isCanceled() )
125 {
126 break;
127 }
128
129 if ( !matchingSink->addFeature( f, QgsFeatureSink::FastInsert ) )
130 throw QgsProcessingException( writeFeatureError( matchingSink.get(), parameters, u"OUTPUT"_s ) );
131 else
132 feedback->featureAddedToSink( u"OUTPUT"_s );
133
134 feedback->setProgress( current * step );
135 current++;
136 }
137 }
138 else
139 {
140 // saving non-matching features, so we need EVERYTHING
141 expressionContext.setFields( source->fields() );
142 expression.prepare( &expressionContext );
143
144 QgsFeatureIterator it = source->getFeatures();
145 QgsFeature f;
146 while ( it.nextFeature( f ) )
147 {
148 if ( feedback->isCanceled() )
149 {
150 break;
151 }
152
153 expressionContext.setFeature( f );
154 if ( expression.evaluate( &expressionContext ).toBool() )
155 {
156 if ( !matchingSink->addFeature( f, QgsFeatureSink::FastInsert ) )
157 throw QgsProcessingException( writeFeatureError( matchingSink.get(), parameters, u"OUTPUT"_s ) );
158 else
159 feedback->featureAddedToSink( u"OUTPUT"_s );
160 }
161 else
162 {
163 if ( !nonMatchingSink->addFeature( f, QgsFeatureSink::FastInsert ) )
164 throw QgsProcessingException( writeFeatureError( nonMatchingSink.get(), parameters, u"FAIL_OUTPUT"_s ) );
165 else
166 feedback->featureAddedToSink( u"FAIL_OUTPUT"_s );
167 }
168
169 feedback->setProgress( current * step );
170 current++;
171 }
172 }
173
174 if ( matchingSink )
175 {
176 matchingSink->finalize();
177 feedback->featureSinkFinalized( u"OUTPUT"_s );
178 }
179 if ( nonMatchingSink )
180 {
181 nonMatchingSink->finalize();
182 feedback->featureSinkFinalized( u"FAIL_OUTPUT"_s );
183 }
184
185 QVariantMap outputs;
186 outputs.insert( u"OUTPUT"_s, matchingSinkId );
187 if ( nonMatchingSink )
188 outputs.insert( u"FAIL_OUTPUT"_s, nonMatchingSinkId );
189 return outputs;
190}
191
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3755
@ VectorAnyGeometry
Any vector layer with geometry.
Definition qgis.h:3749
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition qgis.h:3930
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
Handles parsing and evaluation of expressions (formerly called "search strings").
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:56
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:65
Contains information about the context in which a processing algorithm is executed.
void setCreateByDefault(bool createByDefault)
Sets whether the destination should be created by default.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
void featureAddedToSink(const QString &output)
Reports that a feature was added to the the sink associated with the specified algorithm output.
void featureSinkFinalized(const QString &output)
Reports that a feature sink has been finalized.
An expression parameter for processing algorithms.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.