Skip to content

Commit 16c4f83

Browse files
committedSep 5, 2017
[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.
1 parent 3484eb0 commit 16c4f83

File tree

10 files changed

+353
-7
lines changed

10 files changed

+353
-7
lines changed
 

‎python/plugins/processing/gui/TestTools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ def createTest(text):
231231
params[param.name()] = float(token)
232232
elif isinstance(param, QgsProcessingParameterEnum):
233233
params[param.name()] = int(token)
234-
else:
234+
elif token:
235235
if token[0] == '"':
236236
token = token[1:]
237237
if token[-1] == '"':
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>collect_all</Name>
4+
<ElementPath>collect_all</ElementPath>
5+
<!--MULTIPOLYGON-->
6+
<GeometryType>6</GeometryType>
7+
<SRSName>EPSG:4326</SRSName>
8+
<DatasetSpecificInfo>
9+
<FeatureCount>1</FeatureCount>
10+
<ExtentXMin>-1.00000</ExtentXMin>
11+
<ExtentXMax>9.16296</ExtentXMax>
12+
<ExtentYMin>-3.00000</ExtentYMin>
13+
<ExtentYMax>6.08868</ExtentYMax>
14+
</DatasetSpecificInfo>
15+
<PropertyDefn>
16+
<Name>name</Name>
17+
<ElementPath>name</ElementPath>
18+
<Type>String</Type>
19+
<Width>2</Width>
20+
</PropertyDefn>
21+
<PropertyDefn>
22+
<Name>intval</Name>
23+
<ElementPath>intval</ElementPath>
24+
<Type>Integer</Type>
25+
</PropertyDefn>
26+
<PropertyDefn>
27+
<Name>floatval</Name>
28+
<ElementPath>floatval</ElementPath>
29+
<Type>Real</Type>
30+
</PropertyDefn>
31+
</GMLFeatureClass>
32+
</GMLFeatureClassList>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
10+
<gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:collect_all fid="polys.0">
16+
<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>
17+
<ogr:name>aa</ogr:name>
18+
<ogr:intval>1</ogr:intval>
19+
<ogr:floatval>44.123456</ogr:floatval>
20+
</ogr:collect_all>
21+
</gml:featureMember>
22+
</ogr:FeatureCollection>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>collect_one_field</Name>
4+
<ElementPath>collect_one_field</ElementPath>
5+
<!--MULTIPOLYGON-->
6+
<GeometryType>6</GeometryType>
7+
<SRSName>EPSG:4326</SRSName>
8+
<DatasetSpecificInfo>
9+
<FeatureCount>5</FeatureCount>
10+
<ExtentXMin>-1.00000</ExtentXMin>
11+
<ExtentXMax>9.16296</ExtentXMax>
12+
<ExtentYMin>-3.00000</ExtentYMin>
13+
<ExtentYMax>6.08868</ExtentYMax>
14+
</DatasetSpecificInfo>
15+
<PropertyDefn>
16+
<Name>name</Name>
17+
<ElementPath>name</ElementPath>
18+
<Type>String</Type>
19+
<Width>2</Width>
20+
</PropertyDefn>
21+
<PropertyDefn>
22+
<Name>intval</Name>
23+
<ElementPath>intval</ElementPath>
24+
<Type>Integer</Type>
25+
</PropertyDefn>
26+
<PropertyDefn>
27+
<Name>floatval</Name>
28+
<ElementPath>floatval</ElementPath>
29+
<Type>Real</Type>
30+
</PropertyDefn>
31+
</GMLFeatureClass>
32+
</GMLFeatureClassList>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
10+
<gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:collect_one_field fid="polys.0">
16+
<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>
17+
<ogr:name>aa</ogr:name>
18+
<ogr:intval>1</ogr:intval>
19+
<ogr:floatval>44.123456</ogr:floatval>
20+
</ogr:collect_one_field>
21+
</gml:featureMember>
22+
<gml:featureMember>
23+
<ogr:collect_one_field fid="polys.1">
24+
<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>
25+
<ogr:name>dd</ogr:name>
26+
<ogr:floatval>0</ogr:floatval>
27+
</ogr:collect_one_field>
28+
</gml:featureMember>
29+
<gml:featureMember>
30+
<ogr:collect_one_field fid="polys.2">
31+
<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>
32+
<ogr:name>bb</ogr:name>
33+
<ogr:intval>1</ogr:intval>
34+
<ogr:floatval>0.123</ogr:floatval>
35+
</ogr:collect_one_field>
36+
</gml:featureMember>
37+
<gml:featureMember>
38+
<ogr:collect_one_field fid="polys.7">
39+
<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>
40+
<ogr:name>cc</ogr:name>
41+
<ogr:floatval>0.123</ogr:floatval>
42+
</ogr:collect_one_field>
43+
</gml:featureMember>
44+
<gml:featureMember>
45+
<ogr:collect_one_field fid="polys.3">
46+
<ogr:intval>120</ogr:intval>
47+
<ogr:floatval>-100291.43213</ogr:floatval>
48+
</ogr:collect_one_field>
49+
</gml:featureMember>
50+
</ogr:FeatureCollection>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>collect_two_fields</Name>
4+
<ElementPath>collect_two_fields</ElementPath>
5+
<!--MULTIPOLYGON-->
6+
<GeometryType>6</GeometryType>
7+
<SRSName>EPSG:4326</SRSName>
8+
<DatasetSpecificInfo>
9+
<FeatureCount>6</FeatureCount>
10+
<ExtentXMin>-1.00000</ExtentXMin>
11+
<ExtentXMax>9.16296</ExtentXMax>
12+
<ExtentYMin>-3.00000</ExtentYMin>
13+
<ExtentYMax>6.08868</ExtentYMax>
14+
</DatasetSpecificInfo>
15+
<PropertyDefn>
16+
<Name>name</Name>
17+
<ElementPath>name</ElementPath>
18+
<Type>String</Type>
19+
<Width>2</Width>
20+
</PropertyDefn>
21+
<PropertyDefn>
22+
<Name>intval</Name>
23+
<ElementPath>intval</ElementPath>
24+
<Type>Integer</Type>
25+
</PropertyDefn>
26+
<PropertyDefn>
27+
<Name>floatval</Name>
28+
<ElementPath>floatval</ElementPath>
29+
<Type>Real</Type>
30+
</PropertyDefn>
31+
</GMLFeatureClass>
32+
</GMLFeatureClassList>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
10+
<gml:coord><gml:X>9.162955854126682</gml:X><gml:Y>6.088675623800385</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:collect_two_fields fid="polys.8">
16+
<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>
17+
<ogr:name>bb</ogr:name>
18+
<ogr:intval>2</ogr:intval>
19+
<ogr:floatval>0.123</ogr:floatval>
20+
</ogr:collect_two_fields>
21+
</gml:featureMember>
22+
<gml:featureMember>
23+
<ogr:collect_two_fields fid="polys.0">
24+
<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>
25+
<ogr:name>aa</ogr:name>
26+
<ogr:intval>1</ogr:intval>
27+
<ogr:floatval>44.123456</ogr:floatval>
28+
</ogr:collect_two_fields>
29+
</gml:featureMember>
30+
<gml:featureMember>
31+
<ogr:collect_two_fields fid="polys.7">
32+
<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>
33+
<ogr:name>cc</ogr:name>
34+
<ogr:floatval>0.123</ogr:floatval>
35+
</ogr:collect_two_fields>
36+
</gml:featureMember>
37+
<gml:featureMember>
38+
<ogr:collect_two_fields fid="polys.1">
39+
<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>
40+
<ogr:name>dd</ogr:name>
41+
<ogr:floatval>0</ogr:floatval>
42+
</ogr:collect_two_fields>
43+
</gml:featureMember>
44+
<gml:featureMember>
45+
<ogr:collect_two_fields fid="polys.3">
46+
<ogr:intval>120</ogr:intval>
47+
<ogr:floatval>-100291.43213</ogr:floatval>
48+
</ogr:collect_two_fields>
49+
</gml:featureMember>
50+
<gml:featureMember>
51+
<ogr:collect_two_fields fid="polys.2">
52+
<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>
53+
<ogr:name>bb</ogr:name>
54+
<ogr:intval>1</ogr:intval>
55+
<ogr:floatval>0.123</ogr:floatval>
56+
</ogr:collect_two_fields>
57+
</gml:featureMember>
58+
</ogr:FeatureCollection>

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3437,3 +3437,42 @@ tests:
34373437
OUTPUT:
34383438
name: expected/promote_multipart_already_multi.gml
34393439
type: vector
3440+
3441+
- algorithm: native:collect
3442+
name: Test (native:collect)
3443+
params:
3444+
INPUT:
3445+
name: dissolve_polys.gml
3446+
type: vector
3447+
results:
3448+
OUTPUT:
3449+
name: expected/collect_all.gml
3450+
type: vector
3451+
3452+
- algorithm: native:collect
3453+
name: Test (native:collect)
3454+
params:
3455+
FIELD:
3456+
- name
3457+
INPUT:
3458+
name: dissolve_polys.gml
3459+
type: vector
3460+
results:
3461+
OUTPUT:
3462+
name: expected/collect_one_field.gml
3463+
type: vector
3464+
3465+
- algorithm: native:collect
3466+
name: Test (native:collect)
3467+
params:
3468+
FIELD:
3469+
- intval
3470+
- name
3471+
INPUT:
3472+
name: dissolve_polys.gml
3473+
type: vector
3474+
results:
3475+
OUTPUT:
3476+
name: expected/collect_two_fields.gml
3477+
type: vector
3478+

‎src/core/processing/qgsnativealgorithms.cpp

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "qgsgeometryengine.h"
2626
#include "qgswkbtypes.h"
2727

28+
#include <functional>
29+
2830
///@cond PRIVATE
2931

3032
QgsNativeAlgorithms::QgsNativeAlgorithms( QObject *parent )
@@ -62,6 +64,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
6264
addAlgorithm( new QgsCentroidAlgorithm() );
6365
addAlgorithm( new QgsClipAlgorithm() );
6466
addAlgorithm( new QgsDissolveAlgorithm() );
67+
addAlgorithm( new QgsCollectAlgorithm() );
6568
addAlgorithm( new QgsExtractByAttributeAlgorithm() );
6669
addAlgorithm( new QgsExtractByExpressionAlgorithm() );
6770
addAlgorithm( new QgsMultipartToSinglepartAlgorithm() );
@@ -243,7 +246,8 @@ QgsDissolveAlgorithm *QgsDissolveAlgorithm::createInstance() const
243246
return new QgsDissolveAlgorithm();
244247
}
245248

246-
QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
249+
QVariantMap QgsCollectorAlgorithm::processCollection( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback,
250+
std::function<QgsGeometry( const QList< QgsGeometry >& )> collector, int maxQueueLength )
247251
{
248252
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
249253
if ( !source )
@@ -289,10 +293,10 @@ QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameter
289293
if ( f.hasGeometry() && f.geometry() )
290294
{
291295
geomQueue.append( f.geometry() );
292-
if ( geomQueue.length() > 10000 )
296+
if ( maxQueueLength > 0 && geomQueue.length() > maxQueueLength )
293297
{
294298
// queue too long, combine it
295-
QgsGeometry tempOutputGeometry = QgsGeometry::unaryUnion( geomQueue );
299+
QgsGeometry tempOutputGeometry = collector( geomQueue );
296300
geomQueue.clear();
297301
geomQueue << tempOutputGeometry;
298302
}
@@ -302,7 +306,7 @@ QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameter
302306
current++;
303307
}
304308

305-
outputFeature.setGeometry( QgsGeometry::unaryUnion( geomQueue ) );
309+
outputFeature.setGeometry( collector( geomQueue ) );
306310
sink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
307311
}
308312
else
@@ -355,7 +359,7 @@ QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameter
355359
QgsFeature outputFeature;
356360
if ( geometryHash.contains( attrIt.key() ) )
357361
{
358-
QgsGeometry geom = QgsGeometry::unaryUnion( geometryHash.value( attrIt.key() ) );
362+
QgsGeometry geom = collector( geometryHash.value( attrIt.key() ) );
359363
if ( !geom.isMultipart() )
360364
{
361365
geom.convertToMultiType();
@@ -375,6 +379,23 @@ QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameter
375379
return outputs;
376380
}
377381

382+
QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
383+
{
384+
return processCollection( parameters, context, feedback, []( const QList< QgsGeometry > &parts )->QgsGeometry
385+
{
386+
return QgsGeometry::unaryUnion( parts );
387+
}, 10000 );
388+
}
389+
390+
QVariantMap QgsCollectAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
391+
{
392+
return processCollection( parameters, context, feedback, []( const QList< QgsGeometry > &parts )->QgsGeometry
393+
{
394+
return QgsGeometry::collectGeometry( parts );
395+
} );
396+
}
397+
398+
378399
void QgsClipAlgorithm::initAlgorithm( const QVariantMap & )
379400
{
380401
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
@@ -1289,6 +1310,31 @@ QgsFeature QgsPromoteToMultipartAlgorithm::processFeature( const QgsFeature &fea
12891310
}
12901311
return f;
12911312
}
1313+
1314+
1315+
void QgsCollectAlgorithm::initAlgorithm( const QVariantMap & )
1316+
{
1317+
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
1318+
addParameter( new QgsProcessingParameterField( QStringLiteral( "FIELD" ), QObject::tr( "Unique ID fields" ), QVariant(),
1319+
QStringLiteral( "INPUT" ), QgsProcessingParameterField::Any, true, true ) );
1320+
1321+
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Collected" ) ) );
1322+
}
1323+
1324+
QString QgsCollectAlgorithm::shortHelpString() const
1325+
{
1326+
return QObject::tr( "This algorithm takes a vector layer and collects its geometries into new multipart geometries. One or more attributes can "
1327+
"be specified to collect only geometries belonging to the same class (having the same value for the specified attributes), alternatively "
1328+
"all geometries can be collected.\n\n"
1329+
"All output geometries will be converted to multi geometries, even those with just a single part. "
1330+
"This algorithm does not dissolve overlapping geometries - they will be collected together without modifying the shape of each geometry part." );
1331+
}
1332+
1333+
QgsCollectAlgorithm *QgsCollectAlgorithm::createInstance() const
1334+
{
1335+
return new QgsCollectAlgorithm();
1336+
}
1337+
12921338
///@endcond
12931339

12941340

‎src/core/processing/qgsnativealgorithms.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,21 @@ class QgsBufferAlgorithm : public QgsProcessingAlgorithm
131131

132132
};
133133

134+
/**
135+
* Base class for dissolve/collect type algorithms.
136+
*/
137+
class QgsCollectorAlgorithm : public QgsProcessingAlgorithm
138+
{
139+
protected:
140+
141+
QVariantMap processCollection( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback,
142+
std::function<QgsGeometry( const QList< QgsGeometry >& )> collector, int maxQueueLength = 0 );
143+
};
144+
134145
/**
135146
* Native dissolve algorithm.
136147
*/
137-
class QgsDissolveAlgorithm : public QgsProcessingAlgorithm
148+
class QgsDissolveAlgorithm : public QgsCollectorAlgorithm
138149
{
139150

140151
public:
@@ -155,6 +166,30 @@ class QgsDissolveAlgorithm : public QgsProcessingAlgorithm
155166

156167
};
157168

169+
/**
170+
* Native collect geometries algorithm.
171+
*/
172+
class QgsCollectAlgorithm : public QgsCollectorAlgorithm
173+
{
174+
175+
public:
176+
177+
QgsCollectAlgorithm() = default;
178+
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
179+
QString name() const override { return QStringLiteral( "collect" ); }
180+
QString displayName() const override { return QObject::tr( "Collect geometries" ); }
181+
virtual QStringList tags() const override { return QObject::tr( "union,combine,collect,multipart,parts,single" ).split( ',' ); }
182+
QString group() const override { return QObject::tr( "Vector geometry" ); }
183+
QString shortHelpString() const override;
184+
QgsCollectAlgorithm *createInstance() const override SIP_FACTORY;
185+
186+
protected:
187+
188+
virtual QVariantMap processAlgorithm( const QVariantMap &parameters,
189+
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
190+
191+
};
192+
158193
/**
159194
* Native extract by attribute algorithm.
160195
*/

0 commit comments

Comments
 (0)
Please sign in to comment.