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 = parameterAsStrings( 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 );
203QString QgsDissolveAlgorithm::name()
const
205 return QStringLiteral(
"dissolve" );
208QString QgsDissolveAlgorithm::displayName()
const
210 return QObject::tr(
"Dissolve" );
213QStringList QgsDissolveAlgorithm::tags()
const
215 return QObject::tr(
"dissolve,union,combine,collect" ).split(
',' );
218QString QgsDissolveAlgorithm::group()
const
220 return QObject::tr(
"Vector geometry" );
223QString QgsDissolveAlgorithm::groupId()
const
225 return QStringLiteral(
"vectorgeometry" );
229void 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() );
243QString 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)." );
254QgsDissolveAlgorithm *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 );
300QString QgsCollectAlgorithm::name()
const
302 return QStringLiteral(
"collect" );
305QString QgsCollectAlgorithm::displayName()
const
307 return QObject::tr(
"Collect geometries" );
310QStringList QgsCollectAlgorithm::tags()
const
312 return QObject::tr(
"union,combine,collect,multipart,parts,single" ).split(
',' );
315QString QgsCollectAlgorithm::group()
const
317 return QObject::tr(
"Vector geometry" );
320QString QgsCollectAlgorithm::groupId()
const
322 return QStringLiteral(
"vectorgeometry" );
327 return processCollection( parameters, context, feedback, [](
const QVector< QgsGeometry > &parts )->
QgsGeometry
334void QgsCollectAlgorithm::initAlgorithm(
const QVariantMap & )
343QString 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." );
355QgsCollectAlgorithm *QgsCollectAlgorithm::createInstance()
const
357 return new QgsCollectAlgorithm();
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
A geometry is the spatial representation of a feature.
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters())
Compute the unary union on a list of geometries.
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Base class for providing feedback from a processing algorithm.
virtual void pushDebugInfo(const QString &info)
Pushes an informational message containing debugging helpers from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
@ FlagAdvanced
Parameter is an advanced parameter which should be hidden from users by default.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
A vector layer or feature source field parameter for processing algorithms.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static Qgis::WkbType multiType(Qgis::WkbType type)
Returns the multi type for a WKB type.