QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 
QgsFeatureId id
Definition: qgsfeature.h:64
Base class for all map layer types.
Definition: qgsmaplayer.h:63
Positive integer values (including 0)
Definition: qgsproperty.h:55
Base class for providing feedback from a processing algorithm.
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:127
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
Positive double value (including 0)
Definition: qgsproperty.h:58
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...
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
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
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.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
A store for object properties.
Definition: qgsproperty.h:229
QgsExpressionContext & expressionContext()
Returns the expression context.
Definition for a property.
Definition: qgsproperty.h:46
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
QgsGeometry symDifference(const QgsGeometry &geometry) const
Returns a geometry representing the points making up this geometry that do not make up other...
bool supportInPlaceEdit(const QgsMapLayer *layer) const override
Checks whether this algorithm supports in-place editing on the given layer Default implementation for...
QgsGeometry geometry
Definition: qgsfeature.h:67
A vector of attributes.
Definition: qgsattributes.h:57
Represents a vector layer which manages a vector based data sets.
Contains information about the context in which a processing algorithm is executed.
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...
QgsAttributes attributes
Definition: qgsfeature.h:65