[FEATURE] New algorithm for 'collecting' geometries

This is basically the equivalent of the dissolve algorithm, but
instead of a dissolving overlapping geometries the geometries
are instead just collected together into a multipart geometry.

It's designed to slot between the 'promote to multipart' algorithm
(which performs no collection of geometries - it just converts
singleparts to multiparts with 1 part) and the more complex
all-encompassing 'aggregate' algorithm.
This commit is contained in:
Nyall Dawson 2017-09-05 11:25:58 +10:00
parent 3484eb019c
commit 16c4f830b3
10 changed files with 353 additions and 7 deletions

View File

@ -231,7 +231,7 @@ def createTest(text):
params[param.name()] = float(token)
elif isinstance(param, QgsProcessingParameterEnum):
params[param.name()] = int(token)
else:
elif token:
if token[0] == '"':
token = token[1:]
if token[-1] == '"':

View File

@ -0,0 +1,32 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>collect_all</Name>
<ElementPath>collect_all</ElementPath>
<!--MULTIPOLYGON-->
<GeometryType>6</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>1</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>9.16296</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
<ExtentYMax>6.08868</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>name</Name>
<ElementPath>name</ElementPath>
<Type>String</Type>
<Width>2</Width>
</PropertyDefn>
<PropertyDefn>
<Name>intval</Name>
<ElementPath>intval</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>floatval</Name>
<ElementPath>floatval</ElementPath>
<Type>Real</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
<gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<ogr:collect_all fid="polys.0">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6.24145873320538,-0.054510556621882 7.24145873320538,-1.05451055662188 5.24145873320538,-1.05451055662188 6.24145873320538,-0.054510556621882</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,5 2,6 3,6 3,5 2,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 2,2 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.44337811900192,4.42360844529751 2.44337811900192,5.42360844529751 3.44337811900192,5.42360844529751 3.44337811900192,4.42360844529751 2.44337811900192,4.42360844529751</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4.17255278310941,4.82264875239923 4.17255278310941,5.82264875239923 5.17255278310941,5.82264875239923 5.17255278310941,4.82264875239923 4.17255278310941,4.82264875239923</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>8.16295585412668,2.73877159309021 8.16295585412668,3.73877159309021 9.16295585412668,3.73877159309021 9.16295585412668,2.73877159309021 8.16295585412668,2.73877159309021</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.62072936660269,5.08867562380038 2.62072936660269,6.08867562380038 3.62072936660269,6.08867562380038 3.62072936660269,5.08867562380038 2.62072936660269,5.08867562380038</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>aa</ogr:name>
<ogr:intval>1</ogr:intval>
<ogr:floatval>44.123456</ogr:floatval>
</ogr:collect_all>
</gml:featureMember>
</ogr:FeatureCollection>

View File

@ -0,0 +1,32 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>collect_one_field</Name>
<ElementPath>collect_one_field</ElementPath>
<!--MULTIPOLYGON-->
<GeometryType>6</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>5</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>9.16296</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
<ExtentYMax>6.08868</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>name</Name>
<ElementPath>name</ElementPath>
<Type>String</Type>
<Width>2</Width>
</PropertyDefn>
<PropertyDefn>
<Name>intval</Name>
<ElementPath>intval</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>floatval</Name>
<ElementPath>floatval</ElementPath>
<Type>Real</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
<gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<ogr:collect_one_field fid="polys.0">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 2,2 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>aa</ogr:name>
<ogr:intval>1</ogr:intval>
<ogr:floatval>44.123456</ogr:floatval>
</ogr:collect_one_field>
</gml:featureMember>
<gml:featureMember>
<ogr:collect_one_field fid="polys.1">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6.24145873320538,-0.054510556621882 7.24145873320538,-1.05451055662188 5.24145873320538,-1.05451055662188 6.24145873320538,-0.054510556621882</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>dd</ogr:name>
<ogr:floatval>0</ogr:floatval>
</ogr:collect_one_field>
</gml:featureMember>
<gml:featureMember>
<ogr:collect_one_field fid="polys.2">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,5 2,6 3,6 3,5 2,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.44337811900192,4.42360844529751 2.44337811900192,5.42360844529751 3.44337811900192,5.42360844529751 3.44337811900192,4.42360844529751 2.44337811900192,4.42360844529751</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4.17255278310941,4.82264875239923 4.17255278310941,5.82264875239923 5.17255278310941,5.82264875239923 5.17255278310941,4.82264875239923 4.17255278310941,4.82264875239923</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.62072936660269,5.08867562380038 2.62072936660269,6.08867562380038 3.62072936660269,6.08867562380038 3.62072936660269,5.08867562380038 2.62072936660269,5.08867562380038</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>bb</ogr:name>
<ogr:intval>1</ogr:intval>
<ogr:floatval>0.123</ogr:floatval>
</ogr:collect_one_field>
</gml:featureMember>
<gml:featureMember>
<ogr:collect_one_field fid="polys.7">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>8.16295585412668,2.73877159309021 8.16295585412668,3.73877159309021 9.16295585412668,3.73877159309021 9.16295585412668,2.73877159309021 8.16295585412668,2.73877159309021</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>cc</ogr:name>
<ogr:floatval>0.123</ogr:floatval>
</ogr:collect_one_field>
</gml:featureMember>
<gml:featureMember>
<ogr:collect_one_field fid="polys.3">
<ogr:intval>120</ogr:intval>
<ogr:floatval>-100291.43213</ogr:floatval>
</ogr:collect_one_field>
</gml:featureMember>
</ogr:FeatureCollection>

View File

@ -0,0 +1,32 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>collect_two_fields</Name>
<ElementPath>collect_two_fields</ElementPath>
<!--MULTIPOLYGON-->
<GeometryType>6</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>6</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>9.16296</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
<ExtentYMax>6.08868</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>name</Name>
<ElementPath>name</ElementPath>
<Type>String</Type>
<Width>2</Width>
</PropertyDefn>
<PropertyDefn>
<Name>intval</Name>
<ElementPath>intval</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>floatval</Name>
<ElementPath>floatval</ElementPath>
<Type>Real</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
<gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<ogr:collect_two_fields fid="polys.8">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.62072936660269,5.08867562380038 2.62072936660269,6.08867562380038 3.62072936660269,6.08867562380038 3.62072936660269,5.08867562380038 2.62072936660269,5.08867562380038</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>bb</ogr:name>
<ogr:intval>2</ogr:intval>
<ogr:floatval>0.123</ogr:floatval>
</ogr:collect_two_fields>
</gml:featureMember>
<gml:featureMember>
<ogr:collect_two_fields fid="polys.0">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 2,2 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>aa</ogr:name>
<ogr:intval>1</ogr:intval>
<ogr:floatval>44.123456</ogr:floatval>
</ogr:collect_two_fields>
</gml:featureMember>
<gml:featureMember>
<ogr:collect_two_fields fid="polys.7">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>8.16295585412668,2.73877159309021 8.16295585412668,3.73877159309021 9.16295585412668,3.73877159309021 9.16295585412668,2.73877159309021 8.16295585412668,2.73877159309021</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>cc</ogr:name>
<ogr:floatval>0.123</ogr:floatval>
</ogr:collect_two_fields>
</gml:featureMember>
<gml:featureMember>
<ogr:collect_two_fields fid="polys.1">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6.24145873320538,-0.054510556621882 7.24145873320538,-1.05451055662188 5.24145873320538,-1.05451055662188 6.24145873320538,-0.054510556621882</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>dd</ogr:name>
<ogr:floatval>0</ogr:floatval>
</ogr:collect_two_fields>
</gml:featureMember>
<gml:featureMember>
<ogr:collect_two_fields fid="polys.3">
<ogr:intval>120</ogr:intval>
<ogr:floatval>-100291.43213</ogr:floatval>
</ogr:collect_two_fields>
</gml:featureMember>
<gml:featureMember>
<ogr:collect_two_fields fid="polys.2">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,5 2,6 3,6 3,5 2,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.44337811900192,4.42360844529751 2.44337811900192,5.42360844529751 3.44337811900192,5.42360844529751 3.44337811900192,4.42360844529751 2.44337811900192,4.42360844529751</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4.17255278310941,4.82264875239923 4.17255278310941,5.82264875239923 5.17255278310941,5.82264875239923 5.17255278310941,4.82264875239923 4.17255278310941,4.82264875239923</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>bb</ogr:name>
<ogr:intval>1</ogr:intval>
<ogr:floatval>0.123</ogr:floatval>
</ogr:collect_two_fields>
</gml:featureMember>
</ogr:FeatureCollection>

View File

@ -3437,3 +3437,42 @@ tests:
OUTPUT:
name: expected/promote_multipart_already_multi.gml
type: vector
- algorithm: native:collect
name: Test (native:collect)
params:
INPUT:
name: dissolve_polys.gml
type: vector
results:
OUTPUT:
name: expected/collect_all.gml
type: vector
- algorithm: native:collect
name: Test (native:collect)
params:
FIELD:
- name
INPUT:
name: dissolve_polys.gml
type: vector
results:
OUTPUT:
name: expected/collect_one_field.gml
type: vector
- algorithm: native:collect
name: Test (native:collect)
params:
FIELD:
- intval
- name
INPUT:
name: dissolve_polys.gml
type: vector
results:
OUTPUT:
name: expected/collect_two_fields.gml
type: vector

View File

@ -25,6 +25,8 @@
#include "qgsgeometryengine.h"
#include "qgswkbtypes.h"
#include <functional>
///@cond PRIVATE
QgsNativeAlgorithms::QgsNativeAlgorithms( QObject *parent )
@ -62,6 +64,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsCentroidAlgorithm() );
addAlgorithm( new QgsClipAlgorithm() );
addAlgorithm( new QgsDissolveAlgorithm() );
addAlgorithm( new QgsCollectAlgorithm() );
addAlgorithm( new QgsExtractByAttributeAlgorithm() );
addAlgorithm( new QgsExtractByExpressionAlgorithm() );
addAlgorithm( new QgsMultipartToSinglepartAlgorithm() );
@ -243,7 +246,8 @@ QgsDissolveAlgorithm *QgsDissolveAlgorithm::createInstance() const
return new QgsDissolveAlgorithm();
}
QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
QVariantMap QgsCollectorAlgorithm::processCollection( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback,
std::function<QgsGeometry( const QList< QgsGeometry >& )> collector, int maxQueueLength )
{
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
if ( !source )
@ -289,10 +293,10 @@ QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameter
if ( f.hasGeometry() && f.geometry() )
{
geomQueue.append( f.geometry() );
if ( geomQueue.length() > 10000 )
if ( maxQueueLength > 0 && geomQueue.length() > maxQueueLength )
{
// queue too long, combine it
QgsGeometry tempOutputGeometry = QgsGeometry::unaryUnion( geomQueue );
QgsGeometry tempOutputGeometry = collector( geomQueue );
geomQueue.clear();
geomQueue << tempOutputGeometry;
}
@ -302,7 +306,7 @@ QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameter
current++;
}
outputFeature.setGeometry( QgsGeometry::unaryUnion( geomQueue ) );
outputFeature.setGeometry( collector( geomQueue ) );
sink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
}
else
@ -355,7 +359,7 @@ QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameter
QgsFeature outputFeature;
if ( geometryHash.contains( attrIt.key() ) )
{
QgsGeometry geom = QgsGeometry::unaryUnion( geometryHash.value( attrIt.key() ) );
QgsGeometry geom = collector( geometryHash.value( attrIt.key() ) );
if ( !geom.isMultipart() )
{
geom.convertToMultiType();
@ -375,6 +379,23 @@ QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameter
return outputs;
}
QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
return processCollection( parameters, context, feedback, []( const QList< QgsGeometry > &parts )->QgsGeometry
{
return QgsGeometry::unaryUnion( parts );
}, 10000 );
}
QVariantMap QgsCollectAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
return processCollection( parameters, context, feedback, []( const QList< QgsGeometry > &parts )->QgsGeometry
{
return QgsGeometry::collectGeometry( parts );
} );
}
void QgsClipAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
@ -1289,6 +1310,31 @@ QgsFeature QgsPromoteToMultipartAlgorithm::processFeature( const QgsFeature &fea
}
return f;
}
void QgsCollectAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
addParameter( new QgsProcessingParameterField( QStringLiteral( "FIELD" ), QObject::tr( "Unique ID fields" ), QVariant(),
QStringLiteral( "INPUT" ), QgsProcessingParameterField::Any, true, true ) );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Collected" ) ) );
}
QString QgsCollectAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm takes a vector layer and collects its geometries into new multipart geometries. One or more attributes can "
"be specified to collect only geometries belonging to the same class (having the same value for the specified attributes), alternatively "
"all geometries can be collected.\n\n"
"All output geometries will be converted to multi geometries, even those with just a single part. "
"This algorithm does not dissolve overlapping geometries - they will be collected together without modifying the shape of each geometry part." );
}
QgsCollectAlgorithm *QgsCollectAlgorithm::createInstance() const
{
return new QgsCollectAlgorithm();
}
///@endcond

View File

@ -131,10 +131,21 @@ class QgsBufferAlgorithm : public QgsProcessingAlgorithm
};
/**
* Base class for dissolve/collect type algorithms.
*/
class QgsCollectorAlgorithm : public QgsProcessingAlgorithm
{
protected:
QVariantMap processCollection( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback,
std::function<QgsGeometry( const QList< QgsGeometry >& )> collector, int maxQueueLength = 0 );
};
/**
* Native dissolve algorithm.
*/
class QgsDissolveAlgorithm : public QgsProcessingAlgorithm
class QgsDissolveAlgorithm : public QgsCollectorAlgorithm
{
public:
@ -155,6 +166,30 @@ class QgsDissolveAlgorithm : public QgsProcessingAlgorithm
};
/**
* Native collect geometries algorithm.
*/
class QgsCollectAlgorithm : public QgsCollectorAlgorithm
{
public:
QgsCollectAlgorithm() = default;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
QString name() const override { return QStringLiteral( "collect" ); }
QString displayName() const override { return QObject::tr( "Collect geometries" ); }
virtual QStringList tags() const override { return QObject::tr( "union,combine,collect,multipart,parts,single" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector geometry" ); }
QString shortHelpString() const override;
QgsCollectAlgorithm *createInstance() const override SIP_FACTORY;
protected:
virtual QVariantMap processAlgorithm( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
};
/**
* Native extract by attribute algorithm.
*/