QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsalgorithmbuffer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmbuffer.cpp
3  ---------------------
4  begin : April 2017
5  copyright : (C) 2017 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 #include "qgsalgorithmbuffer.h"
19 #include "qgswkbtypes.h"
20 #include "qgsvectorlayer.h"
21 
23 
24 QString QgsBufferAlgorithm::name() const
25 {
26  return QStringLiteral( "buffer" );
27 }
28 
29 QString QgsBufferAlgorithm::displayName() const
30 {
31  return QObject::tr( "Buffer" );
32 }
33 
34 QStringList QgsBufferAlgorithm::tags() const
35 {
36  return QObject::tr( "buffer,grow,fixed,variable,distance" ).split( ',' );
37 }
38 
39 QString QgsBufferAlgorithm::group() const
40 {
41  return QObject::tr( "Vector geometry" );
42 }
43 
44 QString QgsBufferAlgorithm::groupId() const
45 {
46  return QStringLiteral( "vectorgeometry" );
47 }
48 
49 void QgsBufferAlgorithm::initAlgorithm( const QVariantMap & )
50 {
51  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
52 
53  auto bufferParam = std::make_unique < QgsProcessingParameterDistance >( QStringLiteral( "DISTANCE" ), QObject::tr( "Distance" ), 10, QStringLiteral( "INPUT" ) );
54  bufferParam->setIsDynamic( true );
55  bufferParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Distance" ), QObject::tr( "Buffer distance" ), QgsPropertyDefinition::Double ) );
56  bufferParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
57  addParameter( bufferParam.release() );
58  auto segmentParam = std::make_unique < QgsProcessingParameterNumber >( QStringLiteral( "SEGMENTS" ), QObject::tr( "Segments" ), QgsProcessingParameterNumber::Integer, 5, false, 1 );
59  segmentParam->setHelp( QObject::tr( "The segments parameter controls the number of line segments to use to approximate a quarter circle when creating rounded offsets." ) );
60  addParameter( segmentParam.release() );
61  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "END_CAP_STYLE" ), QObject::tr( "End cap style" ), QStringList() << QObject::tr( "Round" ) << QObject::tr( "Flat" ) << QObject::tr( "Square" ), false, 0 ) );
62  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "JOIN_STYLE" ), QObject::tr( "Join style" ), QStringList() << QObject::tr( "Round" ) << QObject::tr( "Miter" ) << QObject::tr( "Bevel" ), false, 0 ) );
63  addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MITER_LIMIT" ), QObject::tr( "Miter limit" ), QgsProcessingParameterNumber::Double, 2, false, 1 ) );
64 
65  addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "DISSOLVE" ), QObject::tr( "Dissolve result" ), false ) );
66  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Buffered" ), QgsProcessing::TypeVectorPolygon, QVariant(), false, true, true ) );
67 }
68 
69 QString QgsBufferAlgorithm::shortHelpString() const
70 {
71  return QObject::tr( "This algorithm computes a buffer area for all the features in an input layer, using a fixed or dynamic distance.\n\n"
72  "The segments parameter controls the number of line segments to use to approximate a quarter circle when creating rounded offsets.\n\n"
73  "The end cap style parameter controls how line endings are handled in the buffer.\n\n"
74  "The join style parameter specifies whether round, miter or beveled joins should be used when offsetting corners in a line.\n\n"
75  "The miter limit parameter is only applicable for miter join styles, and controls the maximum distance from the offset curve to use when creating a mitered join." );
76 }
77 
78 QgsBufferAlgorithm *QgsBufferAlgorithm::createInstance() const
79 {
80  return new QgsBufferAlgorithm();
81 }
82 
83 QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
84 {
85  std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
86  if ( !source )
87  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
88 
89  QString dest;
90  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), QgsWkbTypes::MultiPolygon, source->sourceCrs() ) );
91  if ( !sink )
92  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
93 
94  // fixed parameters
95  const bool dissolve = parameterAsBoolean( parameters, QStringLiteral( "DISSOLVE" ), context );
96  const int segments = parameterAsInt( parameters, QStringLiteral( "SEGMENTS" ), context );
97  const Qgis::EndCapStyle endCapStyle = static_cast< Qgis::EndCapStyle >( 1 + parameterAsInt( parameters, QStringLiteral( "END_CAP_STYLE" ), context ) );
98  const Qgis::JoinStyle joinStyle = static_cast< Qgis::JoinStyle>( 1 + parameterAsInt( parameters, QStringLiteral( "JOIN_STYLE" ), context ) );
99  const double miterLimit = parameterAsDouble( parameters, QStringLiteral( "MITER_LIMIT" ), context );
100  const double bufferDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
101  const bool dynamicBuffer = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
102  QgsExpressionContext expressionContext = createExpressionContext( parameters, context, source.get() );
103  QgsProperty bufferProperty;
104  if ( dynamicBuffer )
105  {
106  bufferProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >();
107  }
108 
109  const long count = source->featureCount();
110 
111  QgsFeature f;
112  // buffer doesn't care about invalid features, and buffering can be used to repair geometries
114 
115  const double step = count > 0 ? 100.0 / count : 1;
116  int current = 0;
117 
118  QVector< QgsGeometry > bufferedGeometriesForDissolve;
119  QgsAttributes dissolveAttrs;
120 
121  while ( it.nextFeature( f ) )
122  {
123  if ( feedback->isCanceled() )
124  {
125  break;
126  }
127  if ( dissolveAttrs.isEmpty() )
128  dissolveAttrs = f.attributes();
129 
130  QgsFeature out = f;
131  if ( out.hasGeometry() )
132  {
133  double distance = bufferDistance;
134  if ( dynamicBuffer )
135  {
136  expressionContext.setFeature( f );
137  distance = bufferProperty.valueAsDouble( expressionContext, bufferDistance );
138  }
139 
140  QgsGeometry outputGeometry = f.geometry().buffer( distance, segments, endCapStyle, joinStyle, miterLimit );
141  if ( outputGeometry.isNull() )
142  {
143  QgsMessageLog::logMessage( QObject::tr( "Error calculating buffer for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), Qgis::MessageLevel::Warning );
144  }
145  if ( dissolve )
146  bufferedGeometriesForDissolve << outputGeometry;
147  else
148  {
149  outputGeometry.convertToMultiType();
150  out.setGeometry( outputGeometry );
151  }
152  }
153 
154  if ( !dissolve )
155  {
156  if ( !sink->addFeature( out, QgsFeatureSink::FastInsert ) )
157  throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
158  }
159 
160  feedback->setProgress( current * step );
161  current++;
162  }
163 
164  if ( dissolve && !bufferedGeometriesForDissolve.isEmpty() )
165  {
166  QgsGeometry finalGeometry = QgsGeometry::unaryUnion( bufferedGeometriesForDissolve );
167  finalGeometry.convertToMultiType();
168  QgsFeature f;
169  f.setGeometry( finalGeometry );
170  f.setAttributes( dissolveAttrs );
171  if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
172  throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
173  }
174 
175  QVariantMap outputs;
176  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
177  return outputs;
178 }
179 
180 QgsProcessingAlgorithm::Flags QgsBufferAlgorithm::flags() const
181 {
182  Flags f = QgsProcessingAlgorithm::flags();
184  return f;
185 }
186 
187 QgsProcessingAlgorithm::VectorProperties QgsBufferAlgorithm::sinkProperties( const QString &sink, const QVariantMap &parameters, QgsProcessingContext &context, const QMap<QString, QgsProcessingAlgorithm::VectorProperties> &sourceProperties ) const
188 {
190  if ( sink == QLatin1String( "OUTPUT" ) )
191  {
192  if ( sourceProperties.value( QStringLiteral( "INPUT" ) ).availability == QgsProcessingAlgorithm::Available )
193  {
194  const VectorProperties inputProps = sourceProperties.value( QStringLiteral( "INPUT" ) );
195  result.fields = inputProps.fields;
196  result.crs = inputProps.crs;
198  result.availability = Available;
199  return result;
200  }
201  else
202  {
203  std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
204  if ( source )
205  {
206  result.fields = source->fields();
207  result.crs = source->sourceCrs();
209  result.availability = Available;
210  return result;
211  }
212  }
213  }
214  return result;
215 }
216 
217 bool QgsBufferAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
218 {
219  const QgsVectorLayer *vlayer = qobject_cast< const QgsVectorLayer * >( layer );
220  if ( !vlayer )
221  return false;
222  //Only Polygons
223  return vlayer->wkbType() == QgsWkbTypes::Type::Polygon || vlayer->wkbType() == QgsWkbTypes::Type::MultiPolygon;
224 }
225 
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:76
QgsProcessingParameterNumber::Double
@ Double
Double/float values.
Definition: qgsprocessingparameters.h:2187
QgsVectorLayer::wkbType
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Definition: qgsvectorlayer.cpp:725
QgsProperty
A store for object properties.
Definition: qgsproperty.h:230
QgsWkbTypes::MultiPolygon
@ MultiPolygon
Definition: qgswkbtypes.h:78
QgsProcessingParameters::isDynamic
static bool isDynamic(const QVariantMap &parameters, const QString &name)
Returns true if the parameter with matching name is a dynamic parameter, and must be evaluated once f...
Definition: qgsprocessingparameters.cpp:114
QgsProcessingParameterNumber
A numeric parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2179
QgsProcessingAlgorithm::VectorProperties::fields
QgsFields fields
Fields.
Definition: qgsprocessingalgorithm.h:339
QgsProcessingAlgorithm::VectorProperties::crs
QgsCoordinateReferenceSystem crs
Coordinate Reference System.
Definition: qgsprocessingalgorithm.h:345
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:37
Qgis::EndCapStyle
EndCapStyle
End cap styles for buffers.
Definition: qgis.h:966
QgsProcessing::TypeVectorPolygon
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:51
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsFeedback::isCanceled
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:67
QgsPropertyDefinition::Double
@ Double
Double value (including negative values)
Definition: qgsproperty.h:57
QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition: qgsprocessingutils.h:584
QgsProcessingParameterFeatureSource
An input feature source (such as vector layers) parameter for processing algorithms.
Definition: qgsprocessingparameters.h:3057
QgsGeometry::buffer
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
Definition: qgsgeometry.cpp:2050
QgsProperty::value
QVariant value(const QgsExpressionContext &context, const QVariant &defaultValue=QVariant(), bool *ok=nullptr) const
Calculates the current value of the property, including any transforms which are set for the property...
Definition: qgsproperty.cpp:585
QgsProcessingAlgorithm::Available
@ Available
Properties are available.
Definition: qgsprocessingalgorithm.h:328
QgsProcessingParameterFeatureSink
A feature sink output for processing algorithms.
Definition: qgsprocessingparameters.h:3219
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:46
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsPropertyDefinition
Definition for a property.
Definition: qgsproperty.h:46
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:127
Qgis::JoinStyle
JoinStyle
Join styles for buffers.
Definition: qgis.h:979
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:69
QgsProcessingParameterNumber::Integer
@ Integer
Integer values.
Definition: qgsprocessingparameters.h:2186
qgsvectorlayer.h
QgsProcessingParameterBoolean
A boolean parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1709
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:399
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsProcessingAlgorithm::VectorProperties
Properties of a vector source or sink used in an algorithm.
Definition: qgsprocessingalgorithm.h:336
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:230
qgsalgorithmbuffer.h
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
QgsProcessingAlgorithm::VectorProperties::wkbType
QgsWkbTypes::Type wkbType
Geometry (WKB) type.
Definition: qgsprocessingalgorithm.h:342
QgsGeometry::convertToMultiType
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Definition: qgsgeometry.cpp:1571
QgsProperty::valueAsDouble
double valueAsDouble(const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property and interprets it as a double.
Definition: qgsproperty.cpp:690
QgsAttributes
A vector of attributes. Mostly equal to QVector<QVariant>.
Definition: qgsattributes.h:57
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsProcessingParameterEnum
An enum based parameter for processing algorithms, allowing for selection from predefined values.
Definition: qgsprocessingparameters.h:2540
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
QgsProcessingAlgorithm::flags
virtual Flags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Definition: qgsprocessingalgorithm.cpp:90
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
qgswkbtypes.h
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
QgsProcessingAlgorithm::FlagSupportsInPlaceEdits
@ FlagSupportsInPlaceEdits
Algorithm supports in-place editing.
Definition: qgsprocessingalgorithm.h:78
QgsGeometry::unaryUnion
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries)
Compute the unary union on a list of geometries.
Definition: qgsgeometry.cpp:3079
QgsFeatureSink::FastInsert
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
Definition: qgsfeaturesink.h:70
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:525
QgsProcessingAlgorithm::VectorProperties::availability
QgsProcessingAlgorithm::PropertyAvailability availability
Availability of the properties. By default properties are not available.
Definition: qgsprocessingalgorithm.h:348