QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsalgorithmmultiringconstantbuffer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmnultitingconstantbuffer.cpp
3  --------------------------
4  begin : February 2018
5  copyright : (C) 2018 by Alexander Bruy
6  email : alexander dot bruy 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 
19 #include "qgsvectorlayer.h"
20 
22 
23 QString QgsMultiRingConstantBufferAlgorithm::name() const
24 {
25  return QStringLiteral( "multiringconstantbuffer" );
26 }
27 
28 QString QgsMultiRingConstantBufferAlgorithm::displayName() const
29 {
30  return QObject::tr( "Multi-ring buffer (constant distance)" );
31 }
32 
33 QStringList QgsMultiRingConstantBufferAlgorithm::tags() const
34 {
35  return QObject::tr( "buffer,grow,multiple,rings,distance,donut" ).split( ',' );
36 }
37 
38 QString QgsMultiRingConstantBufferAlgorithm::group() const
39 {
40  return QObject::tr( "Vector geometry" );
41 }
42 
43 QString QgsMultiRingConstantBufferAlgorithm::groupId() const
44 {
45  return QStringLiteral( "vectorgeometry" );
46 }
47 
48 QString QgsMultiRingConstantBufferAlgorithm::outputName() const
49 {
50  return QObject::tr( "Multi-ring buffer (constant distance)" );
51 }
52 
53 QString QgsMultiRingConstantBufferAlgorithm::shortHelpString() const
54 {
55  return QObject::tr( "This algorithm computes multi-ring ('donuts') buffer for all the features in an input layer, using a fixed or dynamic distance and rings number." );
56 }
57 
58 QgsMultiRingConstantBufferAlgorithm *QgsMultiRingConstantBufferAlgorithm::createInstance() const
59 {
60  return new QgsMultiRingConstantBufferAlgorithm();
61 }
62 
63 void QgsMultiRingConstantBufferAlgorithm::initParameters( const QVariantMap & )
64 {
65  std::unique_ptr< QgsProcessingParameterNumber> rings = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "RINGS" ),
66  QObject::tr( "Number of rings" ), QgsProcessingParameterNumber::Integer,
67  1, false, 0 );
68  rings->setIsDynamic( true );
69  rings->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "RINGS" ), QObject::tr( "Number of rings" ), QgsPropertyDefinition::IntegerPositive ) );
70  rings->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
71  addParameter( rings.release() );
72 
73  std::unique_ptr< QgsProcessingParameterDistance > distance = qgis::make_unique< QgsProcessingParameterDistance >( QStringLiteral( "DISTANCE" ),
74  QObject::tr( "Distance between rings" ), 1, QStringLiteral( "INPUT" ), false );
75  distance->setIsDynamic( true );
76  distance->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "DISTANCE" ), QObject::tr( "Distance between rings" ), QgsPropertyDefinition::DoublePositive ) );
77  distance->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
78  addParameter( distance.release() );
79 }
80 
81 bool QgsMultiRingConstantBufferAlgorithm::supportInPlaceEdit( const QgsMapLayer *l ) const
82 {
83  const QgsVectorLayer *layer = qobject_cast< const QgsVectorLayer * >( l );
84  if ( !layer )
85  return false;
86 
88  return false;
89  // Polygons only
90  return layer->wkbType() == QgsWkbTypes::Type::Polygon || layer->wkbType() == QgsWkbTypes::Type::MultiPolygon;
91 }
92 
93 bool QgsMultiRingConstantBufferAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
94 {
95  mRingsNumber = parameterAsInt( parameters, QStringLiteral( "RINGS" ), context );
96  mDynamicRingsNumber = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "RINGS" ) );
97  if ( mDynamicRingsNumber )
98  mRingsNumberProperty = parameters.value( QStringLiteral( "RINGS" ) ).value< QgsProperty >();
99 
100  mDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
101  mDynamicDistance = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
102  if ( mDynamicDistance )
103  mDistanceProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >();
104 
105  return true;
106 }
107 
108 QgsFields QgsMultiRingConstantBufferAlgorithm::outputFields( const QgsFields &inputFields ) const
109 {
110  QgsFields fields = inputFields;
111  fields.append( QgsField( QStringLiteral( "ringId" ), QVariant::Int, QString(), 10, 0 ) );
112  fields.append( QgsField( QStringLiteral( "distance" ), QVariant::Double, QString(), 20, 6 ) );
113  return fields;
114 }
115 
116 QgsProcessingFeatureSource::Flag QgsMultiRingConstantBufferAlgorithm::sourceFlags() const
117 {
119 }
120 
121 QgsFeatureSink::SinkFlags QgsMultiRingConstantBufferAlgorithm::sinkFlags() const
122 {
124 }
125 
126 QgsFeatureList QgsMultiRingConstantBufferAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
127 {
128  double currentDistance = 0;
129  QgsGeometry outputGeometry, previousGeometry;
130 
131  int rings = mRingsNumber;
132  if ( mDynamicRingsNumber )
133  rings = mRingsNumberProperty.valueAsInt( context.expressionContext(), rings );
134 
135  double distance = mDistance;
136  if ( mDynamicDistance )
137  distance = mDistanceProperty.valueAsDouble( context.expressionContext(), distance );
138 
139  QgsFeatureList outputs;
140 
141  // Set previous geometry to a zero-distance buffer of the original geometry,
142  // this is needed for negative distance values
143  previousGeometry = feature.geometry().buffer( 0.0, 40 );
144  previousGeometry.convertToMultiType();
145 
146  for ( int i = 1; i <= rings; ++i )
147  {
148  QgsFeature out;
149  currentDistance = i * distance;
150  outputGeometry = feature.geometry().buffer( currentDistance, 40 );
151  outputGeometry.convertToMultiType();
152  if ( outputGeometry.isNull() )
153  {
154  feedback->reportError( QObject::tr( "Error calculating buffer for feature %1" ).arg( feature.id() ) );
155  continue;
156  }
157 
158  if ( distance < 0.0 )
159  {
160  out.setGeometry( previousGeometry.symDifference( outputGeometry ) );
161  }
162  else if ( i == 1 )
163  {
164  out.setGeometry( outputGeometry );
165  }
166  else
167  {
168  out.setGeometry( outputGeometry.symDifference( previousGeometry ) );
169  }
170  previousGeometry = outputGeometry;
171  QgsAttributes attrs = feature.attributes();
172  attrs << i << currentDistance;
173  out.setAttributes( attrs );
174  outputs.append( out );
175  }
176 
177  // For negative distance values, the last generated buffer geometry needs to be added
178  if ( distance < 0.0 )
179  {
180  QgsFeature out;
181  out.setGeometry( previousGeometry );
182  QgsAttributes attrs = feature.attributes();
183  attrs << 0 << 0.0;
184  out.setAttributes( attrs );
185  outputs.append( out );
186  }
187 
188  return outputs;
189 }
190 
QgsFeature::id
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
QgsVectorLayer::wkbType
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Definition: qgsvectorlayer.cpp:664
qgsalgorithmmultiringconstantbuffer.h
QgsProperty
A store for object properties.
Definition: qgsproperty.h:232
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
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:38
QgsGeometry::isNull
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
QgsProcessingFeedback::reportError
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
Definition: qgsprocessingfeedback.cpp:39
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:67
QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition: qgsprocessingutils.h:477
QgsProcessingFeatureBasedAlgorithm::supportInPlaceEdit
bool supportInPlaceEdit(const QgsMapLayer *layer) const override
Checks whether this algorithm supports in-place editing on the given layer Default implementation for...
Definition: qgsprocessingalgorithm.cpp:1031
QgsFields::append
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
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:1904
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:139
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:44
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:583
QgsPropertyDefinition
Definition for a property.
Definition: qgsproperty.h:48
QgsFeatureSink::RegeneratePrimaryKey
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
Definition: qgsfeaturesink.h:55
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsProcessingParameterNumber::Integer
@ Integer
Integer values.
Definition: qgsprocessingparameters.h:1966
qgsvectorlayer.h
QgsPropertyDefinition::IntegerPositive
@ IntegerPositive
Positive integer values (including 0)
Definition: qgsproperty.h:56
QgsProcessingFeatureSource::Flag
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
Definition: qgsprocessingutils.h:476
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsProcessingContext::expressionContext
QgsExpressionContext & expressionContext()
Returns the expression context.
Definition: qgsprocessingcontext.h:133
QgsGeometry::convertToMultiType
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Definition: qgsgeometry.cpp:1453
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
A vector of attributes.
Definition: qgsattributes.h:58
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsGeometry::symDifference
QgsGeometry symDifference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other.
Definition: qgsgeometry.cpp:2461
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:129
QgsPropertyDefinition::DoublePositive
@ DoublePositive
Positive double value (including 0)
Definition: qgsproperty.h:59
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50