QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 = qgis::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  addParameter( new QgsProcessingParameterNumber( QStringLiteral( "SEGMENTS" ), QObject::tr( "Segments" ), QgsProcessingParameterNumber::Integer, 5, false, 1 ) );
59 
60  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "END_CAP_STYLE" ), QObject::tr( "End cap style" ), QStringList() << QObject::tr( "Round" ) << QObject::tr( "Flat" ) << QObject::tr( "Square" ), false, 0 ) );
61  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "JOIN_STYLE" ), QObject::tr( "Join style" ), QStringList() << QObject::tr( "Round" ) << QObject::tr( "Miter" ) << QObject::tr( "Bevel" ), false, 0 ) );
62  addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MITER_LIMIT" ), QObject::tr( "Miter limit" ), QgsProcessingParameterNumber::Double, 2, false, 1 ) );
63 
64  addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "DISSOLVE" ), QObject::tr( "Dissolve result" ), false ) );
65  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Buffered" ), QgsProcessing::TypeVectorPolygon, QVariant(), false, true, true ) );
66 }
67 
68 QString QgsBufferAlgorithm::shortHelpString() const
69 {
70  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"
71  "The segments parameter controls the number of line segments to use to approximate a quarter circle when creating rounded offsets.\n\n"
72  "The end cap style parameter controls how line endings are handled in the buffer.\n\n"
73  "The join style parameter specifies whether round, miter or beveled joins should be used when offsetting corners in a line.\n\n"
74  "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." );
75 }
76 
77 QgsBufferAlgorithm *QgsBufferAlgorithm::createInstance() const
78 {
79  return new QgsBufferAlgorithm();
80 }
81 
82 QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
83 {
84  std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
85  if ( !source )
86  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
87 
88  QString dest;
89  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), QgsWkbTypes::MultiPolygon, source->sourceCrs() ) );
90  if ( !sink )
91  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
92 
93  // fixed parameters
94  bool dissolve = parameterAsBoolean( parameters, QStringLiteral( "DISSOLVE" ), context );
95  int segments = parameterAsInt( parameters, QStringLiteral( "SEGMENTS" ), context );
96  QgsGeometry::EndCapStyle endCapStyle = static_cast< QgsGeometry::EndCapStyle >( 1 + parameterAsInt( parameters, QStringLiteral( "END_CAP_STYLE" ), context ) );
97  QgsGeometry::JoinStyle joinStyle = static_cast< QgsGeometry::JoinStyle>( 1 + parameterAsInt( parameters, QStringLiteral( "JOIN_STYLE" ), context ) );
98  double miterLimit = parameterAsDouble( parameters, QStringLiteral( "MITER_LIMIT" ), context );
99  double bufferDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
100  bool dynamicBuffer = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
101  QgsExpressionContext expressionContext = createExpressionContext( parameters, context, source.get() );
102  QgsProperty bufferProperty;
103  if ( dynamicBuffer )
104  {
105  bufferProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >();
106  }
107 
108  long count = source->featureCount();
109 
110  QgsFeature f;
111  // buffer doesn't care about invalid features, and buffering can be used to repair geometries
113 
114  double step = count > 0 ? 100.0 / count : 1;
115  int current = 0;
116 
117  QVector< QgsGeometry > bufferedGeometriesForDissolve;
118  QgsAttributes dissolveAttrs;
119 
120  while ( it.nextFeature( f ) )
121  {
122  if ( feedback->isCanceled() )
123  {
124  break;
125  }
126  if ( dissolveAttrs.isEmpty() )
127  dissolveAttrs = f.attributes();
128 
129  QgsFeature out = f;
130  if ( out.hasGeometry() )
131  {
132  double distance = bufferDistance;
133  if ( dynamicBuffer )
134  {
135  expressionContext.setFeature( f );
136  distance = bufferProperty.valueAsDouble( expressionContext, bufferDistance );
137  }
138 
139  QgsGeometry outputGeometry = f.geometry().buffer( distance, segments, endCapStyle, joinStyle, miterLimit );
140  if ( outputGeometry.isNull() )
141  {
142  QgsMessageLog::logMessage( QObject::tr( "Error calculating buffer for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), Qgis::Warning );
143  }
144  if ( dissolve )
145  bufferedGeometriesForDissolve << outputGeometry;
146  else
147  {
148  outputGeometry.convertToMultiType();
149  out.setGeometry( outputGeometry );
150  }
151  }
152 
153  if ( !dissolve )
154  sink->addFeature( out, QgsFeatureSink::FastInsert );
155 
156  feedback->setProgress( current * step );
157  current++;
158  }
159 
160  if ( dissolve )
161  {
162  QgsGeometry finalGeometry = QgsGeometry::unaryUnion( bufferedGeometriesForDissolve );
163  finalGeometry.convertToMultiType();
164  QgsFeature f;
165  f.setGeometry( finalGeometry );
166  f.setAttributes( dissolveAttrs );
167  sink->addFeature( f, QgsFeatureSink::FastInsert );
168  }
169 
170  QVariantMap outputs;
171  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
172  return outputs;
173 }
174 
175 QgsProcessingAlgorithm::Flags QgsBufferAlgorithm::flags() const
176 {
177  Flags f = QgsProcessingAlgorithm::flags();
179  return f;
180 }
181 
182 QgsProcessingAlgorithm::VectorProperties QgsBufferAlgorithm::sinkProperties( const QString &sink, const QVariantMap &parameters, QgsProcessingContext &context, const QMap<QString, QgsProcessingAlgorithm::VectorProperties> &sourceProperties ) const
183 {
185  if ( sink == QStringLiteral( "OUTPUT" ) )
186  {
187  if ( sourceProperties.value( QStringLiteral( "INPUT" ) ).availability == QgsProcessingAlgorithm::Available )
188  {
189  const VectorProperties inputProps = sourceProperties.value( QStringLiteral( "INPUT" ) );
190  result.fields = inputProps.fields;
191  result.crs = inputProps.crs;
193  result.availability = Available;
194  return result;
195  }
196  else
197  {
198  std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
199  if ( source )
200  {
201  result.fields = source->fields();
202  result.crs = source->sourceCrs();
204  result.availability = Available;
205  return result;
206  }
207  }
208  }
209  return result;
210 }
211 
212 bool QgsBufferAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
213 {
214  const QgsVectorLayer *vlayer = qobject_cast< const QgsVectorLayer * >( layer );
215  if ( !vlayer )
216  return false;
217  //Only Polygons
218  return vlayer->wkbType() == QgsWkbTypes::Type::Polygon || vlayer->wkbType() == QgsWkbTypes::Type::MultiPolygon;
219 }
220 
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:75
QgsProcessingParameterNumber::Double
@ Double
Double/float values.
Definition: qgsprocessingparameters.h:1846
QgsVectorLayer::wkbType
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Definition: qgsvectorlayer.cpp:664
QgsProperty
A store for object properties.
Definition: qgsproperty.h:231
QgsWkbTypes::MultiPolygon
@ MultiPolygon
Definition: qgswkbtypes.h:77
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:111
QgsProcessingParameterNumber
Definition: qgsprocessingparameters.h:1838
QgsProcessingAlgorithm::VectorProperties::fields
QgsFields fields
Fields.
Definition: qgsprocessingalgorithm.h:336
QgsProcessingAlgorithm::VectorProperties::crs
QgsCoordinateReferenceSystem crs
Coordinate Reference System.
Definition: qgsprocessingalgorithm.h:342
QgsProcessingFeedback
Definition: qgsprocessingfeedback.h:37
Qgis::Warning
@ Warning
Definition: qgis.h:104
QgsProcessing::TypeVectorPolygon
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:50
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsPropertyDefinition::Double
@ Double
Double value (including negative values)
Definition: qgsproperty.h:58
QgsGeometry::EndCapStyle
EndCapStyle
End cap styles for buffers.
Definition: qgsgeometry.h:1116
QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition: qgsprocessingutils.h:475
QgsProcessingParameterFeatureSource
Definition: qgsprocessingparameters.h:2612
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:1919
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:519
QgsProcessingAlgorithm::Available
@ Available
Properties are available.
Definition: qgsprocessingalgorithm.h:325
QgsProcessingParameterFeatureSink
Definition: qgsprocessingparameters.h:2773
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsFeatureRequest
Definition: qgsfeaturerequest.h:75
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:137
QgsProcessingContext
Definition: qgsprocessingcontext.h:43
QgsPropertyDefinition
Definition for a property.
Definition: qgsproperty.h:47
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:125
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:69
QgsProcessingParameterNumber::Integer
@ Integer
Integer values.
Definition: qgsprocessingparameters.h:1845
qgsvectorlayer.h
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:66
QgsProcessingParameterBoolean
Definition: qgsprocessingparameters.h:1439
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:373
QgsGeometry
Definition: qgsgeometry.h:122
QgsProcessingAlgorithm::VectorProperties
Properties of a vector source or sink used in an algorithm.
Definition: qgsprocessingalgorithm.h:333
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
qgsalgorithmbuffer.h
QgsMapLayer
Definition: qgsmaplayer.h:81
QgsProcessingAlgorithm::VectorProperties::wkbType
QgsWkbTypes::Type wkbType
Geometry (WKB) type.
Definition: qgsprocessingalgorithm.h:339
QgsGeometry::convertToMultiType
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Definition: qgsgeometry.cpp:1468
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
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:620
QgsAttributes
Definition: qgsattributes.h:57
QgsGeometry::JoinStyle
JoinStyle
Join styles for buffers.
Definition: qgsgeometry.h:1125
QgsFeature
Definition: qgsfeature.h:55
QgsProcessingParameterEnum
Definition: qgsprocessingparameters.h:2134
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:127
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:88
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
qgswkbtypes.h
QgsProcessingException
Definition: qgsexception.h:82
QgsProcessingAlgorithm::FlagSupportsInPlaceEdits
@ FlagSupportsInPlaceEdits
Algorithm supports in-place editing.
Definition: qgsprocessingalgorithm.h:77
QgsGeometry::unaryUnion
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries)
Compute the unary union on a list of geometries.
Definition: qgsgeometry.cpp:2785
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:521
QgsProcessingAlgorithm::VectorProperties::availability
QgsProcessingAlgorithm::PropertyAvailability availability
Availability of the properties. By default properties are not available.
Definition: qgsprocessingalgorithm.h:345