[FEATURE][processing] Add sort order option to Add Incremental Field alg

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.
This commit is contained in:
Nyall Dawson 2018-04-17 13:04:25 +10:00
parent eab76e85c7
commit 0e0e133c7d
6 changed files with 183 additions and 2 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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:
@ -5191,4 +5207,5 @@ tests:
name: expected/filter_points_big.gml
type: vector
# See ../README.md for a description of the file format

View File

@ -16,6 +16,7 @@
***************************************************************************/
#include "qgsalgorithmaddincrementalfield.h"
#include "qgsfeaturerequest.h"
///@cond PRIVATE
@ -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
@ -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
@ -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() )

View File

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

View File

@ -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;