Skip to content

Commit 585a4d3

Browse files
committed
[processing] Split multiparts and explode are feature based algorithms
1 parent 43cd62b commit 585a4d3

File tree

3 files changed

+56
-96
lines changed

3 files changed

+56
-96
lines changed

python/plugins/processing/algs/qgis/Explode.py

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,11 @@
3030
QgsFeatureSink,
3131
QgsWkbTypes,
3232
QgsProcessing,
33-
QgsProcessingParameterFeatureSource,
34-
QgsProcessingParameterFeatureSink,
3533
QgsLineString)
36-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
34+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3735

3836

39-
class Explode(QgisAlgorithm):
37+
class Explode(QgisFeatureBasedAlgorithm):
4038

4139
INPUT = 'INPUT'
4240
OUTPUT = 'OUTPUT'
@@ -50,43 +48,36 @@ def groupId(self):
5048
def __init__(self):
5149
super().__init__()
5250

53-
def initAlgorithm(self, config=None):
54-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
55-
self.tr('Input layer'), [QgsProcessing.TypeVectorLine]))
56-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT,
57-
self.tr('Exploded'), QgsProcessing.TypeVectorLine))
51+
def inputLayerTypes(self):
52+
return [QgsProcessing.TypeVectorLine]
53+
54+
def outputName(self):
55+
return self.tr('Exploded')
56+
57+
def outputWkbType(self, inputWkb):
58+
return QgsWkbTypes.singleType(inputWkb)
59+
60+
def outputLayerType(self):
61+
return QgsProcessing.TypeVectorLine
5862

5963
def name(self):
6064
return 'explodelines'
6165

6266
def displayName(self):
6367
return self.tr('Explode lines')
6468

65-
def processAlgorithm(self, parameters, context, feedback):
66-
source = self.parameterAsSource(parameters, self.INPUT, context)
67-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
68-
source.fields(), QgsWkbTypes.singleType(source.wkbType()), source.sourceCrs())
69-
70-
features = source.getFeatures()
71-
total = 100.0 / source.featureCount() if source.featureCount() else 0
72-
for current, feature in enumerate(features):
73-
if feedback.isCanceled():
74-
break
75-
76-
feedback.setProgress(int(current * total))
77-
78-
if not feature.hasGeometry():
79-
sink.addFeature(feature, QgsFeatureSink.FastInsert)
80-
continue
81-
82-
outFeat = QgsFeature()
83-
inGeom = feature.geometry()
84-
segments = self.extractAsSingleSegments(inGeom)
85-
outFeat.setAttributes(feature.attributes())
86-
for segment in segments:
87-
outFeat.setGeometry(segment)
88-
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
89-
return {self.OUTPUT: dest_id}
69+
def processFeature(self, feature, context, feedback):
70+
if not feature.hasGeometry():
71+
return [feature]
72+
73+
segments = self.extractAsSingleSegments(feature.geometry())
74+
output_features = []
75+
for segment in segments:
76+
output_feature = QgsFeature()
77+
output_feature.setAttributes(feature.attributes())
78+
output_feature.setGeometry(segment)
79+
output_features.append(output_feature)
80+
return output_features
9081

9182
def extractAsSingleSegments(self, geom):
9283
segments = []

src/analysis/processing/qgsalgorithmmultiparttosinglepart.cpp

Lines changed: 26 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ QString QgsMultipartToSinglepartAlgorithm::displayName() const
2929
return QObject::tr( "Multipart to singleparts" );
3030
}
3131

32+
QString QgsMultipartToSinglepartAlgorithm::outputName() const
33+
{
34+
return QObject::tr( "Single parts" );
35+
}
36+
37+
QgsWkbTypes::Type QgsMultipartToSinglepartAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
38+
{
39+
return QgsWkbTypes::singleType( inputWkbType );
40+
}
41+
3242
QStringList QgsMultipartToSinglepartAlgorithm::tags() const
3343
{
3444
return QObject::tr( "multi,single,multiple,split,dump" ).split( ',' );
@@ -44,13 +54,6 @@ QString QgsMultipartToSinglepartAlgorithm::groupId() const
4454
return QStringLiteral( "vectorgeometry" );
4555
}
4656

47-
void QgsMultipartToSinglepartAlgorithm::initAlgorithm( const QVariantMap & )
48-
{
49-
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
50-
51-
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Single parts" ) ) );
52-
}
53-
5457
QString QgsMultipartToSinglepartAlgorithm::shortHelpString() const
5558
{
5659
return QObject::tr( "This algorithm takes a vector layer with multipart geometries and generates a new one in which all geometries contain "
@@ -63,63 +66,28 @@ QgsMultipartToSinglepartAlgorithm *QgsMultipartToSinglepartAlgorithm::createInst
6366
return new QgsMultipartToSinglepartAlgorithm();
6467
}
6568

66-
QVariantMap QgsMultipartToSinglepartAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
69+
QgsFeatureList QgsMultipartToSinglepartAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
6770
{
68-
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
69-
if ( !source )
70-
return QVariantMap();
71-
72-
QgsWkbTypes::Type sinkType = QgsWkbTypes::singleType( source->wkbType() );
73-
74-
QString dest;
75-
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(),
76-
sinkType, source->sourceCrs() ) );
77-
if ( !sink )
78-
return QVariantMap();
71+
if ( !feature.hasGeometry() )
72+
return QgsFeatureList() << feature;
7973

80-
long count = source->featureCount();
81-
82-
QgsFeature f;
83-
QgsFeatureIterator it = source->getFeatures();
84-
85-
double step = count > 0 ? 100.0 / count : 1;
86-
int current = 0;
87-
while ( it.nextFeature( f ) )
74+
QgsGeometry inputGeometry = feature.geometry();
75+
QgsFeatureList outputs;
76+
if ( inputGeometry.isMultipart() )
8877
{
89-
if ( feedback->isCanceled() )
90-
{
91-
break;
92-
}
93-
94-
QgsFeature out = f;
95-
if ( out.hasGeometry() )
78+
const QVector<QgsGeometry> parts = inputGeometry.asGeometryCollection();
79+
for ( const QgsGeometry &g : parts )
9680
{
97-
QgsGeometry inputGeometry = f.geometry();
98-
if ( inputGeometry.isMultipart() )
99-
{
100-
Q_FOREACH ( const QgsGeometry &g, inputGeometry.asGeometryCollection() )
101-
{
102-
out.setGeometry( g );
103-
sink->addFeature( out, QgsFeatureSink::FastInsert );
104-
}
105-
}
106-
else
107-
{
108-
sink->addFeature( out, QgsFeatureSink::FastInsert );
109-
}
81+
QgsFeature out;
82+
out.setAttributes( feature.attributes() );
83+
out.setGeometry( g );
84+
outputs.append( out );
11085
}
111-
else
112-
{
113-
// feature with null geometry
114-
sink->addFeature( out, QgsFeatureSink::FastInsert );
115-
}
116-
117-
feedback->setProgress( current * step );
118-
current++;
11986
}
120-
121-
QVariantMap outputs;
122-
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
87+
else
88+
{
89+
outputs.append( feature );
90+
}
12391
return outputs;
12492
}
12593

src/analysis/processing/qgsalgorithmmultiparttosinglepart.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@
2828
/**
2929
* Native multipart to singlepart algorithm.
3030
*/
31-
class QgsMultipartToSinglepartAlgorithm : public QgsProcessingAlgorithm
31+
class QgsMultipartToSinglepartAlgorithm : public QgsProcessingFeatureBasedAlgorithm
3232
{
3333

3434
public:
3535

3636
QgsMultipartToSinglepartAlgorithm() = default;
37-
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
3837
QString name() const override;
3938
QString displayName() const override;
39+
QString outputName() const override;
40+
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const override;
4041
QStringList tags() const override;
4142
QString group() const override;
4243
QString groupId() const override;
@@ -45,8 +46,8 @@ class QgsMultipartToSinglepartAlgorithm : public QgsProcessingAlgorithm
4546

4647
protected:
4748

48-
QVariantMap processAlgorithm( const QVariantMap &parameters,
49-
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
49+
QgsFeatureList processFeature( const QgsFeature &feature,
50+
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
5051

5152
};
5253

0 commit comments

Comments
 (0)