QGIS API Documentation  3.0.2-Girona (307d082)
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 
21 
22 QString QgsBufferAlgorithm::name() const
23 {
24  return QStringLiteral( "buffer" );
25 }
26 
27 QString QgsBufferAlgorithm::displayName() const
28 {
29  return QObject::tr( "Buffer" );
30 }
31 
32 QStringList QgsBufferAlgorithm::tags() const
33 {
34  return QObject::tr( "buffer,grow,fixed,variable,distance" ).split( ',' );
35 }
36 
37 QString QgsBufferAlgorithm::group() const
38 {
39  return QObject::tr( "Vector geometry" );
40 }
41 
42 QString QgsBufferAlgorithm::groupId() const
43 {
44  return QStringLiteral( "vectorgeometry" );
45 }
46 
47 void QgsBufferAlgorithm::initAlgorithm( const QVariantMap & )
48 {
49  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
50 
51  auto bufferParam = qgis::make_unique < QgsProcessingParameterNumber >( QStringLiteral( "DISTANCE" ), QObject::tr( "Distance" ), QgsProcessingParameterNumber::Double, 10 );
52  bufferParam->setIsDynamic( true );
53  bufferParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Distance" ), QObject::tr( "Buffer distance" ), QgsPropertyDefinition::Double ) );
54  bufferParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
55  addParameter( bufferParam.release() );
56  addParameter( new QgsProcessingParameterNumber( QStringLiteral( "SEGMENTS" ), QObject::tr( "Segments" ), QgsProcessingParameterNumber::Integer, 5, false, 1 ) );
57 
58  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "END_CAP_STYLE" ), QObject::tr( "End cap style" ), QStringList() << QObject::tr( "Round" ) << QObject::tr( "Flat" ) << QObject::tr( "Square" ), false ) );
59  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "JOIN_STYLE" ), QObject::tr( "Join style" ), QStringList() << QObject::tr( "Round" ) << QObject::tr( "Miter" ) << QObject::tr( "Bevel" ), false ) );
60  addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MITER_LIMIT" ), QObject::tr( "Miter limit" ), QgsProcessingParameterNumber::Double, 2, false, 1 ) );
61 
62  addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "DISSOLVE" ), QObject::tr( "Dissolve result" ), false ) );
63  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Buffered" ), QgsProcessing::TypeVectorPolygon ) );
64 }
65 
66 QString QgsBufferAlgorithm::shortHelpString() const
67 {
68  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"
69  "The segments parameter controls the number of line segments to use to approximate a quarter circle when creating rounded offsets.\n\n"
70  "The end cap style parameter controls how line endings are handled in the buffer.\n\n"
71  "The join style parameter specifies whether round, miter or beveled joins should be used when offsetting corners in a line.\n\n"
72  "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." );
73 }
74 
75 QgsBufferAlgorithm *QgsBufferAlgorithm::createInstance() const
76 {
77  return new QgsBufferAlgorithm();
78 }
79 
80 QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
81 {
82  std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
83  if ( !source )
84  throw QgsProcessingException( QObject::tr( "Could not load source layer for INPUT" ) );
85 
86  QString dest;
87  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), QgsWkbTypes::Polygon, source->sourceCrs() ) );
88  if ( !sink )
89  throw QgsProcessingException( QObject::tr( "Could not create destination layer for OUTPUT" ) );
90 
91  // fixed parameters
92  bool dissolve = parameterAsBool( parameters, QStringLiteral( "DISSOLVE" ), context );
93  int segments = parameterAsInt( parameters, QStringLiteral( "SEGMENTS" ), context );
94  QgsGeometry::EndCapStyle endCapStyle = static_cast< QgsGeometry::EndCapStyle >( 1 + parameterAsInt( parameters, QStringLiteral( "END_CAP_STYLE" ), context ) );
95  QgsGeometry::JoinStyle joinStyle = static_cast< QgsGeometry::JoinStyle>( 1 + parameterAsInt( parameters, QStringLiteral( "JOIN_STYLE" ), context ) );
96  double miterLimit = parameterAsDouble( parameters, QStringLiteral( "MITER_LIMIT" ), context );
97  double bufferDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
98  bool dynamicBuffer = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
99  QgsExpressionContext expressionContext = createExpressionContext( parameters, context, dynamic_cast< QgsProcessingFeatureSource * >( source.get() ) );
100  QgsProperty bufferProperty;
101  if ( dynamicBuffer )
102  {
103  bufferProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >();
104  }
105 
106  long count = source->featureCount();
107 
108  QgsFeature f;
109  QgsFeatureIterator it = source->getFeatures();
110 
111  double step = count > 0 ? 100.0 / count : 1;
112  int current = 0;
113 
114  QVector< QgsGeometry > bufferedGeometriesForDissolve;
115  QgsAttributes dissolveAttrs;
116 
117  while ( it.nextFeature( f ) )
118  {
119  if ( feedback->isCanceled() )
120  {
121  break;
122  }
123  if ( dissolveAttrs.isEmpty() )
124  dissolveAttrs = f.attributes();
125 
126  QgsFeature out = f;
127  if ( out.hasGeometry() )
128  {
129  double distance = bufferDistance;
130  if ( dynamicBuffer )
131  {
132  expressionContext.setFeature( f );
133  distance = bufferProperty.valueAsDouble( expressionContext, bufferDistance );
134  }
135 
136  QgsGeometry outputGeometry = f.geometry().buffer( distance, segments, endCapStyle, joinStyle, miterLimit );
137  if ( !outputGeometry )
138  {
139  QgsMessageLog::logMessage( QObject::tr( "Error calculating buffer for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), Qgis::Warning );
140  }
141  if ( dissolve )
142  bufferedGeometriesForDissolve << outputGeometry;
143  else
144  out.setGeometry( outputGeometry );
145  }
146 
147  if ( !dissolve )
148  sink->addFeature( out, QgsFeatureSink::FastInsert );
149 
150  feedback->setProgress( current * step );
151  current++;
152  }
153 
154  if ( dissolve )
155  {
156  QgsGeometry finalGeometry = QgsGeometry::unaryUnion( bufferedGeometriesForDissolve );
157  QgsFeature f;
158  f.setGeometry( finalGeometry );
159  f.setAttributes( dissolveAttrs );
160  sink->addFeature( f, QgsFeatureSink::FastInsert );
161  }
162 
163  QVariantMap outputs;
164  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
165  return outputs;
166 }
167 
A boolean parameter for processing algorithms.
QgsFeatureId id
Definition: qgsfeature.h:71
Wrapper for iterator of features from vector data provider or vector layer.
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
Base class for providing feedback from a processing algorithm.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:127
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...
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...
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:62
EndCapStyle
End cap styles for buffers.
Definition: qgsgeometry.h:905
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:190
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning)
add a message to the instance (and create it if necessary)
A feature sink output for processing algorithms.
An enum based parameter for processing algorithms, allowing for selection from predefined values...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
Vector polygon layers.
Definition: qgsprocessing.h:51
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
A store for object properties.
Definition: qgsproperty.h:229
Double value (including negative values)
Definition: qgsproperty.h:57
A numeric parameter for processing algorithms.
Definition for a property.
Definition: qgsproperty.h:46
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.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
An input feature source (such as vector layers) parameter for processing algorithms.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
bool nextFeature(QgsFeature &f)
JoinStyle
Join styles for buffers.
Definition: qgsgeometry.h:914
A vector of attributes.
Definition: qgsattributes.h:58
Contains information about the context in which a processing algorithm is executed.
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries)
Compute the unary union on a list of geometries.
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:72