QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 = std::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 = std::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 
A vector of attributes.
Definition: qgsattributes.h:58
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsAttributes attributes
Definition: qgsfeature.h:65
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:135
QgsGeometry geometry
Definition: qgsfeature.h:67
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:145
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
Container of fields for a vector layer.
Definition: qgsfields.h:45
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
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
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...
QgsGeometry symDifference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Base class for all map layer types.
Definition: qgsmaplayer.h:70
Contains information about the context in which a processing algorithm is executed.
QgsExpressionContext & expressionContext()
Returns the expression context.
bool supportInPlaceEdit(const QgsMapLayer *layer) const override
Checks whether this algorithm supports in-place editing on the given layer Default implementation for...
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
@ 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 reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
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 for a property.
Definition: qgsproperty.h:48
@ IntegerPositive
Positive integer values (including 0)
Definition: qgsproperty.h:56
@ DoublePositive
Positive double value (including 0)
Definition: qgsproperty.h:59
A store for object properties.
Definition: qgsproperty.h:232
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.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:736