Skip to content

Commit

Permalink
[FEATURE][processing] Add sort order option to Add Incremental Field alg
Browse files Browse the repository at this point in the history
This allows users to optionally set a sort order to use when
assigning values in the Add Incremental Field algorithm.

Previously values were always added using the original feature
order. With this change users can control the order in which
features are assigned values.
  • Loading branch information
nyalldawson committed Apr 18, 2018
1 parent eab76e8 commit 0e0e133
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 2 deletions.
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ autoincrement_sort.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:autoincrement_sort fid="points.8">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>9</ogr:id>
<ogr:id2>0</ogr:id2>
<ogr:AUTO>0</ogr:AUTO>
</ogr:autoincrement_sort>
</gml:featureMember>
<gml:featureMember>
<ogr:autoincrement_sort fid="points.7">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>8</ogr:id>
<ogr:id2>0</ogr:id2>
<ogr:AUTO>1</ogr:AUTO>
</ogr:autoincrement_sort>
</gml:featureMember>
<gml:featureMember>
<ogr:autoincrement_sort fid="points.6">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>7</ogr:id>
<ogr:id2>0</ogr:id2>
<ogr:AUTO>2</ogr:AUTO>
</ogr:autoincrement_sort>
</gml:featureMember>
<gml:featureMember>
<ogr:autoincrement_sort fid="points.5">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-5</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>6</ogr:id>
<ogr:id2>0</ogr:id2>
<ogr:AUTO>3</ogr:AUTO>
</ogr:autoincrement_sort>
</gml:featureMember>
<gml:featureMember>
<ogr:autoincrement_sort fid="points.4">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4,1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>5</ogr:id>
<ogr:id2>1</ogr:id2>
<ogr:AUTO>4</ogr:AUTO>
</ogr:autoincrement_sort>
</gml:featureMember>
<gml:featureMember>
<ogr:autoincrement_sort fid="points.3">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5,2</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>4</ogr:id>
<ogr:id2>2</ogr:id2>
<ogr:AUTO>5</ogr:AUTO>
</ogr:autoincrement_sort>
</gml:featureMember>
<gml:featureMember>
<ogr:autoincrement_sort fid="points.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>3</ogr:id>
<ogr:id2>0</ogr:id2>
<ogr:AUTO>6</ogr:AUTO>
</ogr:autoincrement_sort>
</gml:featureMember>
<gml:featureMember>
<ogr:autoincrement_sort fid="points.1">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>2</ogr:id>
<ogr:id2>1</ogr:id2>
<ogr:AUTO>7</ogr:AUTO>
</ogr:autoincrement_sort>
</gml:featureMember>
<gml:featureMember>
<ogr:autoincrement_sort fid="points.0">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>1</ogr:id>
<ogr:id2>2</ogr:id2>
<ogr:AUTO>8</ogr:AUTO>
</ogr:autoincrement_sort>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,44 @@
<?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="autoincrement_sort" type="ogr:autoincrement_sort_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="autoincrement_sort_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="id" 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="id2" 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="AUTO" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:long">
<xs:totalDigits value="20"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
17 changes: 17 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -501,6 +501,22 @@ tests:
name: expected/autoincrement_grouped.gml
type: vector

- algorithm: native:addautoincrementalfield
name: Add incremental field (with sorting)
params:
FIELD_NAME: AUTO
INPUT:
name: points.gml
type: vector
SORT_ASCENDING: true
SORT_EXPRESSION: 99-id
SORT_NULLS_FIRST: false
START: 0
results:
OUTPUT:
name: expected/autoincrement_sort.gml
type: vector

- algorithm: native:dissolve
name: Dissolve using field
params:
Expand Down Expand Up @@ -5191,4 +5207,5 @@ tests:
name: expected/filter_points_big.gml
type: vector


# See ../README.md for a description of the file format
29 changes: 28 additions & 1 deletion src/analysis/processing/qgsalgorithmaddincrementalfield.cpp
Expand Up @@ -16,6 +16,7 @@
***************************************************************************/

#include "qgsalgorithmaddincrementalfield.h"
#include "qgsfeaturerequest.h"

///@cond PRIVATE

Expand All @@ -36,7 +37,9 @@ QString QgsAddIncrementalFieldAlgorithm::shortHelpString() const
"is not added to the input layer but a new layer is generated instead.\n\n"
"The initial starting value for the incremental series can be specified.\n\n"
"Optionally, grouping fields can be specified. If group fields are present, then the field value will "
"be reset for each combination of these group field values." );
"be reset for each combination of these group field values.\n\n"
"The sort order for features may be specified, if so, then the incremental field will respect "
"this sort order." );
}

QStringList QgsAddIncrementalFieldAlgorithm::tags() const
Expand Down Expand Up @@ -81,6 +84,17 @@ void QgsAddIncrementalFieldAlgorithm::initParameters( const QVariantMap & )
QgsProcessingParameterNumber::Integer, 0, true ) );
addParameter( new QgsProcessingParameterField( QStringLiteral( "GROUP_FIELDS" ), QObject::tr( "Group values by" ), QVariant(),
QStringLiteral( "INPUT" ), QgsProcessingParameterField::Any, true, true ) );

// sort params
std::unique_ptr< QgsProcessingParameterExpression > sortExp = qgis::make_unique< QgsProcessingParameterExpression >( QStringLiteral( "SORT_EXPRESSION" ), QObject::tr( "Sort expression" ), QVariant(), QStringLiteral( "INPUT" ), true );
sortExp->setFlags( sortExp->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
addParameter( sortExp.release() );
std::unique_ptr< QgsProcessingParameterBoolean > sortAscending = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "SORT_ASCENDING" ), QObject::tr( "Sort ascending" ), true, true );
sortAscending->setFlags( sortAscending->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
addParameter( sortAscending.release() );
std::unique_ptr< QgsProcessingParameterBoolean > sortNullsFirst = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "SORT_NULLS_FIRST" ), QObject::tr( "Sort nulls first" ), false, true );
sortNullsFirst->setFlags( sortNullsFirst->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
addParameter( sortNullsFirst.release() );
}

QgsFields QgsAddIncrementalFieldAlgorithm::outputFields( const QgsFields &inputFields ) const
Expand All @@ -97,9 +111,22 @@ bool QgsAddIncrementalFieldAlgorithm::prepareAlgorithm( const QVariantMap &param
mValue = mStartValue;
mFieldName = parameterAsString( parameters, QStringLiteral( "FIELD_NAME" ), context );
mGroupedFieldNames = parameterAsFields( parameters, QStringLiteral( "GROUP_FIELDS" ), context );

mSortExpressionString = parameterAsExpression( parameters, QStringLiteral( "SORT_EXPRESSION" ), context );
mSortAscending = parameterAsBool( parameters, QStringLiteral( "SORT_ASCENDING" ), context );
mSortNullsFirst = parameterAsBool( parameters, QStringLiteral( "SORT_NULLS_FIRST" ), context );

return true;
}

QgsFeatureRequest QgsAddIncrementalFieldAlgorithm::request() const
{
if ( mSortExpressionString.isEmpty() )
return QgsFeatureRequest();

return QgsFeatureRequest().setOrderBy( QgsFeatureRequest::OrderBy() << QgsFeatureRequest::OrderByClause( mSortExpressionString, mSortAscending, mSortNullsFirst ) );
}

QgsFeatureList QgsAddIncrementalFieldAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
{
if ( !mGroupedFieldNames.empty() && mGroupedFields.empty() )
Expand Down
7 changes: 7 additions & 0 deletions src/analysis/processing/qgsalgorithmaddincrementalfield.h
Expand Up @@ -51,6 +51,7 @@ class QgsAddIncrementalFieldAlgorithm : public QgsProcessingFeatureBasedAlgorith
QgsProcessingFeatureSource::Flag sourceFlags() const override;

bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
QgsFeatureRequest request() const override;
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;

private:
Expand All @@ -62,6 +63,12 @@ class QgsAddIncrementalFieldAlgorithm : public QgsProcessingFeatureBasedAlgorith
mutable QgsFields mFields;
QStringList mGroupedFieldNames;
QgsAttributeList mGroupedFields;

QString mSortExpressionString;
bool mSortAscending = true;
bool mSortNullsFirst = false;


};

///@endcond PRIVATE
Expand Down
2 changes: 1 addition & 1 deletion src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -732,7 +732,7 @@ QVariantMap QgsProcessingFeatureBasedAlgorithm::processAlgorithm( const QVariant
long count = mSource->featureCount();

QgsFeature f;
QgsFeatureIterator it = mSource->getFeatures( QgsFeatureRequest(), sourceFlags() );
QgsFeatureIterator it = mSource->getFeatures( request(), sourceFlags() );

double step = count > 0 ? 100.0 / count : 1;
int current = 0;
Expand Down

0 comments on commit 0e0e133

Please sign in to comment.