27 const std::function<
QgsGeometry(
const QVector< QgsGeometry >& )> &collector,
int maxQueueLength, QgsProcessingFeatureSource::Flags sourceFlags,
bool separateDisjoint )
29 std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral(
"INPUT" ), context ) );
34 std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT" ), context, dest, source->fields(),
QgsWkbTypes::multiType( source->wkbType() ), source->sourceCrs() ) );
39 const QStringList fields = parameterAsFields( parameters, QStringLiteral(
"FIELD" ), context );
41 const long count = source->featureCount();
46 const double step = count > 0 ? 100.0 / count : 1;
49 if ( fields.isEmpty() )
52 bool firstFeature =
true;
54 QVector< QgsGeometry > geomQueue;
73 if ( maxQueueLength > 0 && geomQueue.length() > maxQueueLength )
76 const QgsGeometry tempOutputGeometry = collector( geomQueue );
78 geomQueue << tempOutputGeometry;
86 if ( !separateDisjoint )
88 outputFeature.
setGeometry( collector( geomQueue ) );
94 const QgsGeometry combinedGeometry = collector( geomQueue );
98 partGeom.convertToMultiType();
107 QList< int > fieldIndexes;
108 fieldIndexes.reserve( fields.size() );
109 for (
const QString &
field : fields )
111 const int index = source->fields().lookupField(
field );
113 fieldIndexes << index;
116 QHash< QVariant, QgsAttributes > attributeHash;
117 QHash< QVariant, QVector< QgsGeometry > > geometryHash;
126 QVariantList indexAttributes;
127 indexAttributes.reserve( fieldIndexes.size() );
128 for (
const int index : std::as_const( fieldIndexes ) )
133 if ( !attributeHash.contains( indexAttributes ) )
136 attributeHash.insert( indexAttributes, f.
attributes() );
141 geometryHash[ indexAttributes ].append( f.
geometry() );
145 const int numberFeatures = attributeHash.count();
146 QHash< QVariant, QgsAttributes >::const_iterator attrIt = attributeHash.constBegin();
147 for ( ; attrIt != attributeHash.constEnd(); ++attrIt )
156 auto geometryHashIt = geometryHash.find( attrIt.key() );
157 if ( geometryHashIt != geometryHash.end() )
159 QgsGeometry geom = collector( geometryHashIt.value() );
164 if ( !separateDisjoint )
175 partGeom.convertToMultiType();
188 feedback->
setProgress( current * 100.0 / numberFeatures );
194 outputs.insert( QStringLiteral(
"OUTPUT" ), dest );
203 QString QgsDissolveAlgorithm::name()
const
205 return QStringLiteral(
"dissolve" );
208 QString QgsDissolveAlgorithm::displayName()
const
210 return QObject::tr(
"Dissolve" );
213 QStringList QgsDissolveAlgorithm::tags()
const
215 return QObject::tr(
"dissolve,union,combine,collect" ).split(
',' );
218 QString QgsDissolveAlgorithm::group()
const
220 return QObject::tr(
"Vector geometry" );
223 QString QgsDissolveAlgorithm::groupId()
const
225 return QStringLiteral(
"vectorgeometry" );
229 void QgsDissolveAlgorithm::initAlgorithm(
const QVariantMap & )
235 std::unique_ptr< QgsProcessingParameterBoolean > disjointParam = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral(
"SEPARATE_DISJOINT" ),
236 QObject::tr(
"Keep disjoint features separate" ),
false );
238 addParameter( disjointParam.release() );
243 QString QgsDissolveAlgorithm::shortHelpString()
const
245 return QObject::tr(
"This algorithm takes a vector layer and combines their features into new features. One or more attributes can "
246 "be specified to dissolve features belonging to the same class (having the same value for the specified attributes), alternatively "
247 "all features can be dissolved in a single one.\n\n"
248 "All output geometries will be converted to multi geometries. "
249 "In case the input is a polygon layer, common boundaries of adjacent polygons being dissolved will get erased.\n\n"
250 "If enabled, the optional \"Keep disjoint features separate\" setting will cause features and parts that do not overlap or touch to be exported "
251 "as separate features (instead of parts of a single multipart feature)." );
254 QgsDissolveAlgorithm *QgsDissolveAlgorithm::createInstance()
const
256 return new QgsDissolveAlgorithm();
261 const bool separateDisjoint = parameterAsBool( parameters, QStringLiteral(
"SEPARATE_DISJOINT" ), context );
263 return processCollection( parameters, context, feedback, [ & ](
const QVector< QgsGeometry > &parts )->
QgsGeometry
267 result = result.mergeLines();
270 if ( ! result.lastError().isEmpty() && parts.count() > 2 )
275 feedback->
pushDebugInfo( QObject::tr(
"GEOS exception: taking the slower route ..." ) );
277 for (
const auto &p : parts )
281 result = result.mergeLines();
286 if ( ! result.lastError().isEmpty() )
289 if ( result.isEmpty() )
293 }, 10000, QgsProcessingFeatureSource::Flags(), separateDisjoint );
300 QString QgsCollectAlgorithm::name()
const
302 return QStringLiteral(
"collect" );
305 QString QgsCollectAlgorithm::displayName()
const
307 return QObject::tr(
"Collect geometries" );
310 QStringList QgsCollectAlgorithm::tags()
const
312 return QObject::tr(
"union,combine,collect,multipart,parts,single" ).split(
',' );
315 QString QgsCollectAlgorithm::group()
const
317 return QObject::tr(
"Vector geometry" );
320 QString QgsCollectAlgorithm::groupId()
const
322 return QStringLiteral(
"vectorgeometry" );
327 return processCollection( parameters, context, feedback, [](
const QVector< QgsGeometry > &parts )->
QgsGeometry
334 void QgsCollectAlgorithm::initAlgorithm(
const QVariantMap & )
343 QString QgsCollectAlgorithm::shortHelpString()
const
345 return QObject::tr(
"This algorithm takes a vector layer and collects its geometries into new multipart geometries. One or more attributes can "
346 "be specified to collect only geometries belonging to the same class (having the same value for the specified attributes), alternatively "
347 "all geometries can be collected." ) +
348 QStringLiteral(
"\n\n" ) +
349 QObject::tr(
"All output geometries will be converted to multi geometries, even those with just a single part. "
350 "This algorithm does not dissolve overlapping geometries - they will be collected together without modifying the shape of each geometry part." ) +
351 QStringLiteral(
"\n\n" ) +
352 QObject::tr(
"See the 'Promote to multipart' or 'Aggregate' algorithms for alternative options." );
355 QgsCollectAlgorithm *QgsCollectAlgorithm::createInstance()
const
357 return new QgsCollectAlgorithm();