29using namespace Qt::StringLiterals;
33QString QgsGridAlgorithm::name()
const
35 return u
"creategrid"_s;
38QString QgsGridAlgorithm::displayName()
const
40 return QObject::tr(
"Create grid" );
43QStringList QgsGridAlgorithm::tags()
const
45 return QObject::tr(
"grid,lines,polygons,vector,create,fishnet,diamond,hexagon" ).split(
',' );
48QString QgsGridAlgorithm::group()
const
50 return QObject::tr(
"Vector creation" );
53QString QgsGridAlgorithm::groupId()
const
55 return u
"vectorcreation"_s;
58void QgsGridAlgorithm::initAlgorithm(
const QVariantMap & )
62 QObject::tr(
"Grid type" ),
63 QStringList() << QObject::tr(
"Point" ) << QObject::tr(
"Line" ) << QObject::tr(
"Rectangle (Polygon)" ) << QObject::tr(
"Diamond (Polygon)" ) << QObject::tr(
"Hexagon (Polygon)" ),
81QString QgsGridAlgorithm::shortHelpString()
const
84 "This algorithm creates a vector layer with a grid covering a given extent. "
85 "Elements in the grid can be points, lines or polygons. The size and/or "
86 "placement of each element in the grid is defined using a horizontal and "
87 "vertical spacing. The CRS of the output layer must be defined. The grid extent "
88 "and the spacing values must be expressed in the coordinates and units of "
89 "this CRS. The top-left point (minX, maxY) is used as the reference point. "
90 "That means that, at that point, an element is guaranteed to be placed. "
91 "Unless the width and height of the selected extent is a multiple of the "
92 "selected spacing, that is not true for the other points that define that extent."
95QString QgsGridAlgorithm::shortDescription()
const
97 return QObject::tr(
"Creates a vector layer with a grid covering a given extent." );
100QgsGridAlgorithm *QgsGridAlgorithm::createInstance()
const
102 return new QgsGridAlgorithm();
107 mIdx = parameterAsEnum( parameters, u
"TYPE"_s, context );
108 mHSpacing = parameterAsDouble( parameters, u
"HSPACING"_s, context );
109 mVSpacing = parameterAsDouble( parameters, u
"VSPACING"_s, context );
110 mHOverlay = parameterAsDouble( parameters, u
"HOVERLAY"_s, context );
111 mVOverlay = parameterAsDouble( parameters, u
"VOVERLAY"_s, context );
112 mCrs = parameterAsCrs( parameters, u
"CRS"_s, context );
113 mGridExtent = parameterAsExtent( parameters, u
"EXTENT"_s, context, mCrs );
120 QGS_MARK_ALGORITHM_SOURCE
122 if ( mHSpacing <= 0 || mVSpacing <= 0 )
123 throw QgsProcessingException( QObject::tr(
"Invalid grid spacing. horizontal: '%1', vertical: '%2'" ).arg( mHSpacing ).arg( mVSpacing ) );
125 if ( mGridExtent.width() < mHSpacing )
128 if ( mGridExtent.height() < mVSpacing )
139 fields.
append(
QgsField( u
"bottom"_s, QMetaType::Type::Double ) );
146 fields.
append(
QgsField( u
"row_index"_s, QMetaType::Type::LongLong ) );
147 fields.
append(
QgsField( u
"col_index"_s, QMetaType::Type::LongLong ) );
166 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u
"OUTPUT"_s, context, dest, fields, outputWkb, mCrs ) );
175 createPointGrid( sink, feedback );
178 createLineGrid( sink, feedback );
181 createRectangleGrid( sink, feedback );
184 createDiamondGrid( sink, feedback );
187 createHexagonGrid( sink, feedback );
194 outputs.insert( u
"OUTPUT"_s, dest );
198void QgsGridAlgorithm::createPointGrid( std::unique_ptr<QgsFeatureSink> &sink,
QgsProcessingFeedback *feedback )
202 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
203 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
207 const long long cellcnt = rows * cols;
209 int thisProgress = 0;
210 int lastProgress = 0;
212 for (
long long col = 0; col < cols; col++ )
214 const double x = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
216 for (
long long row = 0; row < rows; row++ )
218 const double y = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
230 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
231 if ( feedback && thisProgress != lastProgress )
233 lastProgress = thisProgress;
245void QgsGridAlgorithm::createLineGrid( std::unique_ptr<QgsFeatureSink> &sink,
QgsProcessingFeedback *feedback )
252 hSpace[0] = mHSpacing - mHOverlay;
253 hSpace[1] = mHOverlay;
257 hSpace[0] = mHSpacing;
258 hSpace[1] = mHSpacing;
264 vSpace[0] = mVSpacing - mVOverlay;
265 vSpace[1] = mVOverlay;
269 vSpace[0] = mVSpacing;
270 vSpace[1] = mVSpacing;
277 double cntMax = mGridExtent.height() / mVSpacing;
279 int thisProgress = 0;
280 int lastProgress = 0;
282 double y = mGridExtent.yMaximum();
284 while ( y >= mGridExtent.yMinimum() )
298 y = y - vSpace[cnt % 2];
304 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) / cntMax ) * 50 );
305 if ( feedback && thisProgress != lastProgress )
307 lastProgress = thisProgress;
319 cntMax = mGridExtent.width() / mHSpacing;
323 double x = mGridExtent.xMinimum();
325 while ( x <= mGridExtent.xMaximum() )
338 x = x + hSpace[cnt % 2];
343 thisProgress =
static_cast<int>(
static_cast<double>( 50 ) + (
static_cast<double>( cnt ) / cntMax ) * 100 );
344 if ( feedback && thisProgress != lastProgress )
346 lastProgress = thisProgress;
354void QgsGridAlgorithm::createRectangleGrid( std::unique_ptr<QgsFeatureSink> &sink,
QgsProcessingFeedback *feedback )
358 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
359 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
363 const long long cellcnt = rows * cols;
365 int thisProgress = 0;
366 int lastProgress = 0;
367 QVector<double> ringX( 5 );
368 QVector<double> ringY( 5 );
370 for (
long long col = 0; col < cols; col++ )
375 const double x1 = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
376 const double x2 = x1 + mHSpacing;
378 for (
long long row = 0; row < rows; row++ )
380 const double y1 = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
381 const double y2 = y1 - mVSpacing;
383 ringX = { x1, x2, x2, x1, x1 };
384 ringY = { y1, y1, y2, y2, y1 };
385 auto poly = std::make_unique<QgsPolygon>();
397 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
398 if ( feedback && thisProgress != lastProgress )
400 lastProgress = thisProgress;
410void QgsGridAlgorithm::createDiamondGrid( std::unique_ptr<QgsFeatureSink> &sink,
QgsProcessingFeedback *feedback )
414 const double halfHSpacing = mHSpacing / 2;
415 const double halfVSpacing = mVSpacing / 2;
417 const double halfHOverlay = mHOverlay / 2;
418 const double halfVOverlay = mVOverlay / 2;
420 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( halfHSpacing - halfHOverlay ) ) );
421 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - halfVOverlay ) ) );
425 const long long cellcnt = rows * cols;
427 int thisProgress = 0;
428 int lastProgress = 0;
429 QVector<double> ringX( 5 );
430 QVector<double> ringY( 5 );
432 for (
long long col = 0; col < cols; col++ )
437 const double x = mGridExtent.xMinimum() - ( col * halfHOverlay );
438 const double x1 = x + ( ( col + 0 ) * halfHSpacing );
439 const double x2 = x + ( ( col + 1 ) * halfHSpacing );
440 const double x3 = x + ( ( col + 2 ) * halfHSpacing );
442 for (
long long row = 0; row < rows; row++ )
444 const double y = mGridExtent.yMaximum() + ( row * halfVOverlay );
450 if ( ( col % 2 ) == 0 )
452 y1 = y - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
453 y2 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
454 y3 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
458 y1 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
459 y2 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
460 y3 = y - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
463 ringX = { x1, x2, x3, x2, x1 };
464 ringY = { y2, y1, y2, y3, y2 };
465 auto poly = std::make_unique<QgsPolygon>();
477 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
478 if ( feedback && thisProgress != lastProgress )
480 lastProgress = thisProgress;
490void QgsGridAlgorithm::createHexagonGrid( std::unique_ptr<QgsFeatureSink> &sink,
QgsProcessingFeedback *feedback )
495 const double xVertexLo = 0.288675134594813 * mVSpacing;
496 const double xVertexHi = 0.577350269189626 * mVSpacing;
498 mHSpacing = xVertexLo + xVertexHi;
500 mHOverlay = mHSpacing - mHOverlay;
505 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." )
511 const double halfVSpacing = mVSpacing / 2;
513 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHOverlay ) ) );
514 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
518 const long long cellcnt = rows * cols;
520 int thisProgress = 0;
521 int lastProgress = 0;
523 QVector<double> ringX( 7 );
524 QVector<double> ringY( 7 );
525 for (
long long col = 0; col < cols; col++ )
534 const double x1 = mGridExtent.xMinimum() + ( col * mHOverlay );
535 const double x2 = x1 + ( xVertexHi - xVertexLo );
536 const double x3 = mGridExtent.xMinimum() + ( col * mHOverlay ) + mHSpacing;
537 const double x4 = x3 + ( xVertexHi - xVertexLo );
539 for (
long long row = 0; row < rows; row++ )
545 if ( ( col % 2 ) == 0 )
547 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
548 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
549 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
553 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
554 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
555 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
558 ringX = { x1, x2, x3, x4, x3, x2, x1 };
559 ringY = { y2, y1, y1, y2, y3, y3, y2 };
560 auto poly = std::make_unique<QgsPolygon>();
572 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
573 if ( feedback && thisProgress != lastProgress )
575 lastProgress = thisProgress;
@ VectorAnyGeometry
Any vector layer with geometry.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ 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...
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.
void setProgress(double progress)
Sets the current progress for the feedback object.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
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.
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.
void featureAddedToSink(const QString &output)
Reports that a feature was added to the the sink associated with the specified algorithm output.
void featureSinkFinalized(const QString &output)
Reports that a feature sink has been finalized.
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.