QGIS API Documentation 3.99.0-Master (357b655ed83)
Loading...
Searching...
No Matches
qgsalgorithmgrid.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmgrid.cpp
3 ---------------------
4 begin : August 2019
5 copyright : (C) 2019 by Clemens Raffler
6 email : clemens dot raffler 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//Disclaimer:This feature was developed by: Michael Minn, 2010
19
20#include "qgsalgorithmgrid.h"
21
22#include "qgslinestring.h"
23#include "qgspolygon.h"
24#include "qgsvectorlayer.h"
25#include "qgswkbtypes.h"
26
27#include <QString>
28
29using namespace Qt::StringLiterals;
30
32
33QString QgsGridAlgorithm::name() const
34{
35 return u"creategrid"_s;
36}
37
38QString QgsGridAlgorithm::displayName() const
39{
40 return QObject::tr( "Create grid" );
41}
42
43QStringList QgsGridAlgorithm::tags() const
44{
45 return QObject::tr( "grid,lines,polygons,vector,create,fishnet,diamond,hexagon" ).split( ',' );
46}
47
48QString QgsGridAlgorithm::group() const
49{
50 return QObject::tr( "Vector creation" );
51}
52
53QString QgsGridAlgorithm::groupId() const
54{
55 return u"vectorcreation"_s;
56}
57
58void QgsGridAlgorithm::initAlgorithm( const QVariantMap & )
59{
60 addParameter( new QgsProcessingParameterEnum( u"TYPE"_s, QObject::tr( "Grid type" ), QStringList() << QObject::tr( "Point" ) << QObject::tr( "Line" ) << QObject::tr( "Rectangle (Polygon)" ) << QObject::tr( "Diamond (Polygon)" ) << QObject::tr( "Hexagon (Polygon)" ), false, 0 ) );
61
62 addParameter( new QgsProcessingParameterExtent( u"EXTENT"_s, QObject::tr( "Grid extent" ) ) );
63
64 addParameter( new QgsProcessingParameterDistance( u"HSPACING"_s, QObject::tr( "Horizontal spacing" ), 1, u"CRS"_s, false, 0, 1000000000.0 ) );
65 addParameter( new QgsProcessingParameterDistance( u"VSPACING"_s, QObject::tr( "Vertical spacing" ), 1, u"CRS"_s, false, 0, 1000000000.0 ) );
66
67 addParameter( new QgsProcessingParameterDistance( u"HOVERLAY"_s, QObject::tr( "Horizontal overlay" ), 0, u"CRS"_s, false ) );
68 addParameter( new QgsProcessingParameterDistance( u"VOVERLAY"_s, QObject::tr( "Vertical overlay" ), 0, u"CRS"_s, false ) );
69
70 addParameter( new QgsProcessingParameterCrs( u"CRS"_s, QObject::tr( "Grid CRS" ), u"ProjectCrs"_s ) );
71
72 addParameter( new QgsProcessingParameterFeatureSink( u"OUTPUT"_s, QObject::tr( "Grid" ), Qgis::ProcessingSourceType::VectorAnyGeometry ) );
73}
74
75QString QgsGridAlgorithm::shortHelpString() const
76{
77 return QObject::tr( "This algorithm creates a vector layer with a grid covering a given extent. "
78 "Elements in the grid can be points, lines or polygons. The size and/or "
79 "placement of each element in the grid is defined using a horizontal and "
80 "vertical spacing. The CRS of the output layer must be defined. The grid extent "
81 "and the spacing values must be expressed in the coordinates and units of "
82 "this CRS. The top-left point (minX, maxY) is used as the reference point. "
83 "That means that, at that point, an element is guaranteed to be placed. "
84 "Unless the width and height of the selected extent is a multiple of the "
85 "selected spacing, that is not true for the other points that define that extent."
86 );
87}
88QString QgsGridAlgorithm::shortDescription() const
89{
90 return QObject::tr( "Creates a vector layer with a grid covering a given extent." );
91}
92
93QgsGridAlgorithm *QgsGridAlgorithm::createInstance() const
94{
95 return new QgsGridAlgorithm();
96}
97
98bool QgsGridAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
99{
100 mIdx = parameterAsEnum( parameters, u"TYPE"_s, context );
101 mHSpacing = parameterAsDouble( parameters, u"HSPACING"_s, context );
102 mVSpacing = parameterAsDouble( parameters, u"VSPACING"_s, context );
103 mHOverlay = parameterAsDouble( parameters, u"HOVERLAY"_s, context );
104 mVOverlay = parameterAsDouble( parameters, u"VOVERLAY"_s, context );
105 mCrs = parameterAsCrs( parameters, u"CRS"_s, context );
106 mGridExtent = parameterAsExtent( parameters, u"EXTENT"_s, context, mCrs );
107
108 return true;
109}
110
111QVariantMap QgsGridAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
112{
113 if ( mHSpacing <= 0 || mVSpacing <= 0 )
114 throw QgsProcessingException( QObject::tr( "Invalid grid spacing. horizontal: '%1', vertical: '%2'" ).arg( mHSpacing ).arg( mVSpacing ) );
115
116 if ( mGridExtent.width() < mHSpacing ) //check if grid extent is smaller than horizontal spacing
117 throw QgsProcessingException( QObject::tr( "Horizontal spacing is too large for the covered area." ) );
118
119 if ( mGridExtent.height() < mVSpacing ) //check if grid extent is smaller than vertical spacing
120 throw QgsProcessingException( QObject::tr( "Vertical spacing is too large for the covered area." ) );
121
122 // if ( mHSpacing <= mHOverlay || mVSpacing <= mVOverlay )
123 // throw QgsProcessingException( QObject::tr( "Invalid overlay: horizontal: '%1', vertical: '%2'" ).arg( mHOverlay ).arg( mVOverlay ) );
124
125 QgsFields fields = QgsFields();
126 fields.append( QgsField( u"id"_s, QMetaType::Type::LongLong ) );
127 fields.append( QgsField( u"left"_s, QMetaType::Type::Double ) );
128 fields.append( QgsField( u"top"_s, QMetaType::Type::Double ) );
129 fields.append( QgsField( u"right"_s, QMetaType::Type::Double ) );
130 fields.append( QgsField( u"bottom"_s, QMetaType::Type::Double ) );
131
132 switch ( mIdx )
133 {
134 case 0: //point
135 case 2: //rectangle
136 case 4: //hexagon
137 fields.append( QgsField( u"row_index"_s, QMetaType::Type::LongLong ) );
138 fields.append( QgsField( u"col_index"_s, QMetaType::Type::LongLong ) );
139 break;
140 default:
141 break;
142 }
143
144
146 switch ( mIdx )
147 {
148 case 0:
149 outputWkb = Qgis::WkbType::Point;
150 break;
151 case 1:
152 outputWkb = Qgis::WkbType::LineString;
153 break;
154 }
155
156 QString dest;
157 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u"OUTPUT"_s, context, dest, fields, outputWkb, mCrs ) );
158 if ( !sink )
159 throw QgsProcessingException( invalidSinkError( parameters, u"OUTPUT"_s ) );
160
161 feedback->setProgress( 0 );
162
163 switch ( mIdx )
164 {
165 case 0: //point
166 createPointGrid( sink, feedback );
167 break;
168 case 1: //line
169 createLineGrid( sink, feedback );
170 break;
171 case 2: //rectangle
172 createRectangleGrid( sink, feedback );
173 break;
174 case 3: //diamond
175 createDiamondGrid( sink, feedback );
176 break;
177 case 4: //hexagon
178 createHexagonGrid( sink, feedback );
179 break;
180 }
181
182 sink->finalize();
183 QVariantMap outputs;
184 outputs.insert( u"OUTPUT"_s, dest );
185 return outputs;
186}
187
188void QgsGridAlgorithm::createPointGrid( std::unique_ptr<QgsFeatureSink> &sink, QgsProcessingFeedback *feedback )
189{
191
192 const long long cols = static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
193 const long long rows = static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
194
195 long long id = 1;
196 long long cnt = 0;
197 const long long cellcnt = rows * cols;
198
199 int thisProgress = 0;
200 int lastProgress = 0;
201
202 for ( long long col = 0; col < cols; col++ )
203 {
204 const double x = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
205
206 for ( long long row = 0; row < rows; row++ )
207 {
208 const double y = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
209
210 f.setGeometry( QgsGeometry( new QgsPoint( x, y ) ) );
211 f.setAttributes( QgsAttributes() << id << x << y << x + mHSpacing << y + mVSpacing << row << col );
212 if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
213 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), u"OUTPUT"_s ) );
214
215 id++;
216 cnt++;
217
218 thisProgress = static_cast<int>( ( static_cast<double>( cnt ) / static_cast<double>( cellcnt ) ) * 100 );
219 if ( feedback && thisProgress != lastProgress )
220 {
221 lastProgress = thisProgress;
222 feedback->setProgress( lastProgress );
223 }
224
225 if ( feedback && feedback->isCanceled() )
226 break;
227 }
228 if ( feedback && feedback->isCanceled() )
229 break;
230 }
231}
232
233void QgsGridAlgorithm::createLineGrid( std::unique_ptr<QgsFeatureSink> &sink, QgsProcessingFeedback *feedback )
234{
236
237 double hSpace[2];
238 if ( mHOverlay > 0 )
239 {
240 hSpace[0] = mHSpacing - mHOverlay;
241 hSpace[1] = mHOverlay;
242 }
243 else
244 {
245 hSpace[0] = mHSpacing;
246 hSpace[1] = mHSpacing;
247 }
248
249 double vSpace[2];
250 if ( mVOverlay > 0 )
251 {
252 vSpace[0] = mVSpacing - mVOverlay;
253 vSpace[1] = mVOverlay;
254 }
255 else
256 {
257 vSpace[0] = mVSpacing;
258 vSpace[1] = mVSpacing;
259 }
260
261 long long cnt = 0;
262 long long id = 1;
263
264 //latitude lines
265 double cntMax = mGridExtent.height() / mVSpacing;
266
267 int thisProgress = 0;
268 int lastProgress = 0;
269
270 double y = mGridExtent.yMaximum();
271
272 while ( y >= mGridExtent.yMinimum() )
273 {
274 if ( feedback && feedback->isCanceled() )
275 break;
276
277 const QgsPoint pt1 = QgsPoint( mGridExtent.xMinimum(), y );
278 const QgsPoint pt2 = QgsPoint( mGridExtent.xMaximum(), y );
279
280 f.setGeometry( QgsGeometry( new QgsLineString( pt1, pt2 ) ) );
281 f.setAttributes( QgsAttributes() << id << mGridExtent.xMinimum() << y << mGridExtent.xMaximum() << y );
282 if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
283 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), u"OUTPUT"_s ) );
284 y = y - vSpace[cnt % 2];
285
286 id++;
287 cnt++;
288
289 //use 50 as count multiplicator because only half of the features are processed at this point
290 thisProgress = static_cast<int>( ( static_cast<double>( cnt ) / cntMax ) * 50 );
291 if ( feedback && thisProgress != lastProgress )
292 {
293 lastProgress = thisProgress;
294 feedback->setProgress( lastProgress );
295 }
296 }
297 //set progress to 50 manually in case the division doesn't amount to 50.
298 if ( feedback )
299 feedback->setProgress( 50 );
300
301 //longitude lines
302 cnt = 0;
303
304 //latitude lines
305 cntMax = mGridExtent.width() / mHSpacing;
306
307 lastProgress = 50;
308
309 double x = mGridExtent.xMinimum();
310
311 while ( x <= mGridExtent.xMaximum() )
312 {
313 if ( feedback && feedback->isCanceled() )
314 break;
315
316 const QgsPoint pt1 = QgsPoint( x, mGridExtent.yMaximum() );
317 const QgsPoint pt2 = QgsPoint( x, mGridExtent.yMinimum() );
318 f.setGeometry( QgsGeometry( new QgsLineString( pt1, pt2 ) ) );
319 f.setAttributes( QgsAttributes() << id << x << mGridExtent.yMaximum() << x << mGridExtent.yMinimum() );
320 if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
321 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), u"OUTPUT"_s ) );
322 x = x + hSpace[cnt % 2];
323
324 id++;
325 cnt++;
326
327 thisProgress = static_cast<int>( static_cast<double>( 50 ) + ( static_cast<double>( cnt ) / cntMax ) * 100 );
328 if ( feedback && thisProgress != lastProgress )
329 {
330 lastProgress = thisProgress;
331 feedback->setProgress( lastProgress );
332 }
333 }
334 if ( feedback )
335 feedback->setProgress( 100 );
336}
337
338void QgsGridAlgorithm::createRectangleGrid( std::unique_ptr<QgsFeatureSink> &sink, QgsProcessingFeedback *feedback )
339{
341
342 const long long cols = static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
343 const long long rows = static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
344
345 long long id = 1;
346 long long cnt = 0;
347 const long long cellcnt = rows * cols;
348
349 int thisProgress = 0;
350 int lastProgress = 0;
351 QVector<double> ringX( 5 );
352 QVector<double> ringY( 5 );
353
354 for ( long long col = 0; col < cols; col++ )
355 {
356 if ( feedback && feedback->isCanceled() )
357 break;
358
359 const double x1 = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
360 const double x2 = x1 + mHSpacing;
361
362 for ( long long row = 0; row < rows; row++ )
363 {
364 const double y1 = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
365 const double y2 = y1 - mVSpacing;
366
367 ringX = { x1, x2, x2, x1, x1 };
368 ringY = { y1, y1, y2, y2, y1 };
369 auto poly = std::make_unique<QgsPolygon>();
370 poly->setExteriorRing( new QgsLineString( ringX, ringY ) );
371 f.setGeometry( std::move( poly ) );
372 f.setAttributes( QgsAttributes() << id << x1 << y1 << x2 << y2 << row << col );
373 if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
374 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), u"OUTPUT"_s ) );
375
376 id++;
377 cnt++;
378
379 thisProgress = static_cast<int>( ( static_cast<double>( cnt ) / static_cast<double>( cellcnt ) ) * 100 );
380 if ( feedback && thisProgress != lastProgress )
381 {
382 lastProgress = thisProgress;
383 feedback->setProgress( lastProgress );
384 }
385
386 if ( feedback && feedback->isCanceled() )
387 break;
388 }
389 }
390}
391
392void QgsGridAlgorithm::createDiamondGrid( std::unique_ptr<QgsFeatureSink> &sink, QgsProcessingFeedback *feedback )
393{
395
396 const double halfHSpacing = mHSpacing / 2;
397 const double halfVSpacing = mVSpacing / 2;
398
399 const double halfHOverlay = mHOverlay / 2;
400 const double halfVOverlay = mVOverlay / 2;
401
402 const long long cols = static_cast<long long>( std::ceil( mGridExtent.width() / ( halfHSpacing - halfHOverlay ) ) );
403 const long long rows = static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - halfVOverlay ) ) );
404
405 long long id = 1;
406 long long cnt = 0;
407 const long long cellcnt = rows * cols;
408
409 int thisProgress = 0;
410 int lastProgress = 0;
411 QVector<double> ringX( 5 );
412 QVector<double> ringY( 5 );
413
414 for ( long long col = 0; col < cols; col++ )
415 {
416 if ( feedback && feedback->isCanceled() )
417 break;
418
419 const double x = mGridExtent.xMinimum() - ( col * halfHOverlay );
420 const double x1 = x + ( ( col + 0 ) * halfHSpacing );
421 const double x2 = x + ( ( col + 1 ) * halfHSpacing );
422 const double x3 = x + ( ( col + 2 ) * halfHSpacing );
423
424 for ( long long row = 0; row < rows; row++ )
425 {
426 const double y = mGridExtent.yMaximum() + ( row * halfVOverlay );
427
428 double y1;
429 double y2;
430 double y3;
431
432 if ( ( col % 2 ) == 0 )
433 {
434 y1 = y - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
435 y2 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
436 y3 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
437 }
438 else
439 {
440 y1 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
441 y2 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
442 y3 = y - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
443 }
444
445 ringX = { x1, x2, x3, x2, x1 };
446 ringY = { y2, y1, y2, y3, y2 };
447 auto poly = std::make_unique<QgsPolygon>();
448 poly->setExteriorRing( new QgsLineString( ringX, ringY ) );
449 f.setGeometry( std::move( poly ) );
450 f.setAttributes( QgsAttributes() << id << x1 << y1 << x3 << y3 );
451 if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
452 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), u"OUTPUT"_s ) );
453
454 id++;
455 cnt++;
456
457 thisProgress = static_cast<int>( ( static_cast<double>( cnt ) / static_cast<double>( cellcnt ) ) * 100 );
458 if ( feedback && thisProgress != lastProgress )
459 {
460 lastProgress = thisProgress;
461 feedback->setProgress( lastProgress );
462 }
463
464 if ( feedback && feedback->isCanceled() )
465 break;
466 }
467 }
468}
469
470void QgsGridAlgorithm::createHexagonGrid( std::unique_ptr<QgsFeatureSink> &sink, QgsProcessingFeedback *feedback )
471{
473
474 // To preserve symmetry, hspacing is fixed relative to vspacing
475 const double xVertexLo = 0.288675134594813 * mVSpacing;
476 const double xVertexHi = 0.577350269189626 * mVSpacing;
477
478 mHSpacing = xVertexLo + xVertexHi;
479
480 mHOverlay = mHSpacing - mHOverlay;
481
482 if ( mHOverlay < 0 )
483 {
484 throw QgsProcessingException( QObject::tr( "To preserve symmetry, hspacing is fixed relative to vspacing\n hspacing is fixed at: %1 and hoverlay is fixed at: %2 hoverlay cannot be negative. Increase hoverlay." ).arg( mHSpacing ).arg( mHOverlay ) );
485 }
486
487 const double halfVSpacing = mVSpacing / 2;
488
489 const long long cols = static_cast<long long>( std::ceil( mGridExtent.width() / ( mHOverlay ) ) );
490 const long long rows = static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
491
492 long long id = 1;
493 long long cnt = 0;
494 const long long cellcnt = rows * cols;
495
496 int thisProgress = 0;
497 int lastProgress = 0;
498
499 QVector<double> ringX( 7 );
500 QVector<double> ringY( 7 );
501 for ( long long col = 0; col < cols; col++ )
502 {
503 if ( feedback && feedback->isCanceled() )
504 break;
505
506 // (column + 1) and (row + 1) calculation is used to maintain
507 // topology between adjacent shapes and avoid overlaps/holes
508 // due to rounding errors
509
510 const double x1 = mGridExtent.xMinimum() + ( col * mHOverlay );
511 const double x2 = x1 + ( xVertexHi - xVertexLo );
512 const double x3 = mGridExtent.xMinimum() + ( col * mHOverlay ) + mHSpacing;
513 const double x4 = x3 + ( xVertexHi - xVertexLo );
514
515 for ( long long row = 0; row < rows; row++ )
516 {
517 double y1;
518 double y2;
519 double y3;
520
521 if ( ( col % 2 ) == 0 )
522 {
523 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
524 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
525 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
526 }
527 else
528 {
529 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
530 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
531 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
532 }
533
534 ringX = { x1, x2, x3, x4, x3, x2, x1 };
535 ringY = { y2, y1, y1, y2, y3, y3, y2 };
536 auto poly = std::make_unique<QgsPolygon>();
537 poly->setExteriorRing( new QgsLineString( ringX, ringY ) );
538 f.setGeometry( std::move( poly ) );
539 f.setAttributes( QgsAttributes() << id << x1 << y1 << x4 << y3 << row << col );
540 if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
541 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), u"OUTPUT"_s ) );
542
543 id++;
544 cnt++;
545
546 thisProgress = static_cast<int>( ( static_cast<double>( cnt ) / static_cast<double>( cellcnt ) ) * 100 );
547 if ( feedback && thisProgress != lastProgress )
548 {
549 lastProgress = thisProgress;
550 feedback->setProgress( lastProgress );
551 }
552
553 if ( feedback && feedback->isCanceled() )
554 break;
555 }
556 }
557}
558
@ VectorAnyGeometry
Any vector layer with geometry.
Definition qgis.h:3604
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:280
@ Point
Point.
Definition qgis.h:282
@ LineString
LineString.
Definition qgis.h:283
@ Polygon
Polygon.
Definition qgis.h:284
A vector of attributes.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:55
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:63
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
Container of fields for a vector layer.
Definition qgsfields.h:46
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:76
A geometry is the spatial representation of a feature.
Line string geometry type, with support for z-dimension and m-values.
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
A coordinate reference system parameter for processing algorithms.
A double numeric parameter for distance values.
An enum based parameter for processing algorithms, allowing for selection from predefined values.
A rectangular map extent parameter for processing algorithms.
A feature sink output for processing algorithms.