diff --git a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
index e029ff62f33..7ab3688e630 100644
--- a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
+++ b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
@@ -111,6 +111,7 @@ from .ShortestPathLayerToPoint import ShortestPathLayerToPoint
from .ShortestPathPointToLayer import ShortestPathPointToLayer
from .ShortestPathPointToPoint import ShortestPathPointToPoint
from .SimplifyGeometries import SimplifyGeometries
+from .SinglePartsToMultiparts import SinglePartsToMultiparts
from .SingleSidedBuffer import SingleSidedBuffer
from .Slope import Slope
from .Smooth import Smooth
@@ -130,7 +131,6 @@ from .VoronoiPolygons import VoronoiPolygons
from .ZonalStatistics import ZonalStatistics
# from .ExtractByLocation import ExtractByLocation
-# from .SinglePartsToMultiparts import SinglePartsToMultiparts
# from .ConvexHull import ConvexHull
# from .FixedDistanceBuffer import FixedDistanceBuffer
# from .VariableDistanceBuffer import VariableDistanceBuffer
@@ -185,7 +185,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
def getAlgs(self):
# algs = [
- # SinglePartsToMultiparts(),
# ConvexHull(), FixedDistanceBuffer(),
# VariableDistanceBuffer(),
# RandomSelection(), RandomSelectionWithinSubsets(),
@@ -285,6 +284,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
ShortestPathPointToLayer(),
ShortestPathPointToPoint(),
SimplifyGeometries(),
+ SinglePartsToMultiparts(),
SingleSidedBuffer(),
Slope(),
Smooth(),
diff --git a/python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py b/python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py
index 544b5e8a747..1d4f86a740b 100644
--- a/python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py
+++ b/python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py
@@ -30,12 +30,17 @@ import os
from qgis.PyQt.QtGui import QIcon
-from qgis.core import QgsFeature, QgsFeatureSink, QgsGeometry, QgsWkbTypes, QgsProcessingUtils, NULL
+from qgis.core import (QgsFeature,
+ QgsFeatureSink,
+ QgsGeometry,
+ QgsWkbTypes,
+ QgsProcessingUtils,
+ NULL,
+ QgsProcessingParameterFeatureSource,
+ QgsProcessingParameterField,
+ QgsProcessingParameterFeatureSink)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
-from processing.core.parameters import ParameterVector
-from processing.core.parameters import ParameterTableField
-from processing.core.outputs import OutputVector
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
@@ -56,11 +61,12 @@ class SinglePartsToMultiparts(QgisAlgorithm):
super().__init__()
def initAlgorithm(self, config=None):
- self.addParameter(ParameterVector(self.INPUT, self.tr('Input layer')))
- self.addParameter(ParameterTableField(self.FIELD,
- self.tr('Unique ID field'), self.INPUT))
+ self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
+ self.tr('Input layer')))
+ self.addParameter(QgsProcessingParameterField(self.FIELD,
+ self.tr('Unique ID field'), parentLayerParameterName=self.INPUT))
- self.addOutput(OutputVector(self.OUTPUT, self.tr('Multipart')))
+ self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Multipart')))
def name(self):
return 'singlepartstomultipart'
@@ -69,31 +75,29 @@ class SinglePartsToMultiparts(QgisAlgorithm):
return self.tr('Singleparts to multipart')
def processAlgorithm(self, parameters, context, feedback):
- layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
- fieldName = self.getParameterValue(self.FIELD)
+ source = self.parameterAsSource(parameters, self.INPUT, context)
+ field_name = self.parameterAsString(parameters, self.FIELD, context)
- geomType = QgsWkbTypes.multiType(layer.wkbType())
+ geom_type = QgsWkbTypes.multiType(source.wkbType())
- writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(layer.fields(), geomType, layer.crs(),
- context)
+ (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
+ source.fields(), geom_type, source.sourceCrs())
- outFeat = QgsFeature()
- inGeom = QgsGeometry()
-
- index = layer.fields().lookupField(fieldName)
+ index = source.fields().lookupField(field_name)
collection_geom = {}
collection_attrs = {}
- features = QgsProcessingUtils.getFeatures(layer, context)
- total = 100.0 / layer.featureCount() if layer.featureCount() else 0
+ features = source.getFeatures()
+ total = 100.0 / source.featureCount() if source.featureCount() else 0
for current, feature in enumerate(features):
+ if feedback.isCanceled():
+ break
+
atMap = feature.attributes()
idVar = atMap[index]
- if idVar in [None, NULL]:
- outFeat.setAttributes(atMap)
- outFeat.setGeometry(feature.geometry())
- writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
+ if idVar in [None, NULL] or not feature.hasGeometry():
+ sink.addFeature(feature, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total))
continue
@@ -108,8 +112,12 @@ class SinglePartsToMultiparts(QgisAlgorithm):
feedback.setProgress(int(current * total))
for key, geoms in collection_geom.items():
- outFeat.setAttributes(collection_attrs[key])
- outFeat.setGeometry(QgsGeometry.collectGeometry(geoms))
- writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
+ if feedback.isCanceled():
+ break
- del writer
+ feature = QgsFeature()
+ feature.setAttributes(collection_attrs[key])
+ feature.setGeometry(QgsGeometry.collectGeometry(geoms))
+ sink.addFeature(feature, QgsFeatureSink.FastInsert)
+
+ return {self.OUTPUT: dest_id}
diff --git a/python/plugins/processing/tests/testdata/expected/single_to_multi.gfs b/python/plugins/processing/tests/testdata/expected/single_to_multi.gfs
index 70b2931c296..099f6342305 100644
--- a/python/plugins/processing/tests/testdata/expected/single_to_multi.gfs
+++ b/python/plugins/processing/tests/testdata/expected/single_to_multi.gfs
@@ -6,7 +6,7 @@
6
EPSG:4326
- 4
+ 5
0.21020
8.96288
-5.48232
diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
index 713280e7d26..a8109607c2e 100644
--- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
+++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
@@ -2363,20 +2363,18 @@ tests:
name: expected/mean_coordinates.gml
type: vector
-# # Temporarily disable until we figure out why it failed after merging
-# # into master
-# #- algorithm: qgis:singlepartstomultipart
-# # name: single part to multipart
-# # params:
-# # FIELD: id
-# # INPUT:
-# # name: custom/single_part_poly.gml
-# # type: vector
-# # results:
-# # OUTPUT:
-# # name: expected/single_to_multi.gml
-# # type: vector
-#
+ - algorithm: qgis:singlepartstomultipart
+ name: single part to multipart
+ params:
+ FIELD: id
+ INPUT:
+ name: custom/single_part_poly.gml
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/single_to_multi.gml
+ type: vector
+
# - algorithm: qgis:zonalstatistics
# name: simple zonal statistics
# params: