QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsalgorithmcoverageunion.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmcoverageunion.cpp
3 ---------------------
4 begin : October 2023
5 copyright : (C) 2023 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18
21#include "qgsgeos.h"
22
23
25
26QString QgsCoverageUnionAlgorithm::name() const
27{
28 return QStringLiteral( "coverageunion" );
29}
30
31QString QgsCoverageUnionAlgorithm::displayName() const
32{
33 return QObject::tr( "Dissolve coverage" );
34}
35
36QStringList QgsCoverageUnionAlgorithm::tags() const
37{
38 return QObject::tr( "union,merge,topological,boundary" ).split( ',' );
39}
40
41QString QgsCoverageUnionAlgorithm::group() const
42{
43 return QObject::tr( "Vector coverage" );
44}
45
46QString QgsCoverageUnionAlgorithm::groupId() const
47{
48 return QStringLiteral( "vectorcoverage" );
49}
50
51void QgsCoverageUnionAlgorithm::initAlgorithm( const QVariantMap & )
52{
53 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ), QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorPolygon ) ) );
54 addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Dissolved" ), Qgis::ProcessingSourceType::VectorPolygon ) );
55}
56
57QString QgsCoverageUnionAlgorithm::shortDescription() const
58{
59 return QObject::tr( "Dissolves a coverage of polygon features" );
60}
61
62QString QgsCoverageUnionAlgorithm::shortHelpString() const
63{
64 return QObject::tr( "This algorithm operates on a coverage (represented as a set of polygon features "
65 "with exactly matching edge geometry) to dissolve (union) the geometries.\n\n"
66 "It provides a heavily optimized approach for unioning these features compared with "
67 "the standard Dissolve tools." );
68}
69
70QgsCoverageUnionAlgorithm *QgsCoverageUnionAlgorithm::createInstance() const
71{
72 return new QgsCoverageUnionAlgorithm();
73}
74
75QVariantMap QgsCoverageUnionAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
76{
77 std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
78 if ( !source )
79 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
80
81 QString sinkId;
82 std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, sinkId, source->fields(), Qgis::WkbType::MultiPolygon, source->sourceCrs() ) );
83 if ( !sink )
84 throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
85
86 // we have to build up a list of geometries in advance
87 QgsGeometryCollection collection;
88
89 const long count = source->featureCount();
90 if ( count > 0 )
91 {
92 collection.reserve( count );
93 }
94
95 const double step = count > 0 ? 100.0 / count : 1;
96 int current = 0;
97
98 feedback->pushInfo( QObject::tr( "Collecting features" ) );
99
100 QgsFeature inFeature;
102 req.setNoAttributes();
103 QgsFeatureIterator features = source->getFeatures( req );
104 while ( features.nextFeature( inFeature ) )
105 {
106 if ( feedback->isCanceled() )
107 {
108 break;
109 }
110
111 if ( inFeature.hasGeometry() )
112 {
113 collection.addGeometry( inFeature.geometry().constGet()->clone() );
114 }
115
116 feedback->setProgress( current * step * 0.2 );
117 current++;
118 }
119
120 feedback->pushInfo( QObject::tr( "Dissolving coverage" ) );
121
122 QgsGeos geos( &collection );
123 QString error;
124
125 switch ( source->invalidGeometryCheck() )
126 {
128 break;
129
132 {
133 if ( geos.validateCoverage( 0, nullptr, &error ) != Qgis::CoverageValidityResult::Valid )
134 {
135 throw QgsProcessingException( QObject::tr( "Coverage is not valid" ) );
136 }
137 break;
138 }
139 }
140
141 std::unique_ptr< QgsAbstractGeometry > dissolved = geos.unionCoverage( &error );
142
143 if ( !dissolved )
144 {
145 if ( !error.isEmpty() )
146 throw QgsProcessingException( error );
147 else
148 throw QgsProcessingException( QObject::tr( "No geometry was returned for dissolved coverage" ) );
149 }
150
151 feedback->setProgress( 95 );
152
153 feedback->pushInfo( QObject::tr( "Storing output" ) );
154 QgsFeature outFeature( source->fields() );
155 outFeature.setGeometry( std::move( dissolved ) );
156 if ( !sink->addFeature( outFeature, QgsFeatureSink::FastInsert ) )
157 throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
158
159 QVariantMap outputs;
160 outputs.insert( QStringLiteral( "OUTPUT" ), sinkId );
161 return outputs;
162}
163
@ VectorPolygon
Vector polygon layers.
@ Valid
Coverage is valid.
@ NoCheck
No invalid geometry checking.
@ AbortOnInvalid
Close iterator on encountering any features with invalid geometry. This requires a slow geometry vali...
@ SkipInvalid
Skip any features with invalid geometry. This requires a slow geometry validity check for every featu...
@ MultiPolygon
MultiPolygon.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
@ 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...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:230
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:53
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:61
Geometry collection.
void reserve(int size)
Attempts to allocate memory for at least size geometries.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Does vector analysis using the geos library and handles import, export, exception handling*.
Definition: qgsgeos.h:98
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
Contains geos related utilities and functions.
Definition: qgsgeos.h:36