28QString QgsGridAlgorithm::name()
const
30 return QStringLiteral(
"creategrid" );
33QString QgsGridAlgorithm::displayName()
const
35 return QObject::tr(
"Create grid" );
38QStringList QgsGridAlgorithm::tags()
const
40 return QObject::tr(
"grid,lines,polygons,vector,create,fishnet,diamond,hexagon" ).split(
',' );
43QString QgsGridAlgorithm::group()
const
45 return QObject::tr(
"Vector creation" );
48QString QgsGridAlgorithm::groupId()
const
50 return QStringLiteral(
"vectorcreation" );
53void QgsGridAlgorithm::initAlgorithm(
const QVariantMap & )
55 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"TYPE" ), 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 ) );
59 addParameter(
new QgsProcessingParameterDistance( QStringLiteral(
"HSPACING" ), QObject::tr(
"Horizontal spacing" ), 1, QStringLiteral(
"CRS" ),
false, 0, 1000000000.0 ) );
60 addParameter(
new QgsProcessingParameterDistance( QStringLiteral(
"VSPACING" ), QObject::tr(
"Vertical spacing" ), 1, QStringLiteral(
"CRS" ),
false, 0, 1000000000.0 ) );
62 addParameter(
new QgsProcessingParameterDistance( QStringLiteral(
"HOVERLAY" ), QObject::tr(
"Horizontal overlay" ), 0, QStringLiteral(
"CRS" ),
false ) );
63 addParameter(
new QgsProcessingParameterDistance( QStringLiteral(
"VOVERLAY" ), QObject::tr(
"Vertical overlay" ), 0, QStringLiteral(
"CRS" ),
false ) );
65 addParameter(
new QgsProcessingParameterCrs( QStringLiteral(
"CRS" ), QObject::tr(
"Grid CRS" ), QStringLiteral(
"ProjectCrs" ) ) );
70QString QgsGridAlgorithm::shortHelpString()
const
72 return QObject::tr(
"This algorithm creates a vector layer with a grid covering a given extent. "
73 "Elements in the grid can be points, lines or polygons. The size and/or "
74 "placement of each element in the grid is defined using a horizontal and "
75 "vertical spacing. The CRS of the output layer must be defined. The grid extent "
76 "and the spacing values must be expressed in the coordinates and units of "
77 "this CRS. The top-left point (minX, maxY) is used as the reference point. "
78 "That means that, at that point, an element is guaranteed to be placed. "
79 "Unless the width and height of the selected extent is a multiple of the "
80 "selected spacing, that is not true for the other points that define that extent."
84QgsGridAlgorithm *QgsGridAlgorithm::createInstance()
const
86 return new QgsGridAlgorithm();
91 mIdx = parameterAsEnum( parameters, QStringLiteral(
"TYPE" ), context );
92 mHSpacing = parameterAsDouble( parameters, QStringLiteral(
"HSPACING" ), context );
93 mVSpacing = parameterAsDouble( parameters, QStringLiteral(
"VSPACING" ), context );
94 mHOverlay = parameterAsDouble( parameters, QStringLiteral(
"HOVERLAY" ), context );
95 mVOverlay = parameterAsDouble( parameters, QStringLiteral(
"VOVERLAY" ), context );
96 mCrs = parameterAsCrs( parameters, QStringLiteral(
"CRS" ), context );
97 mGridExtent = parameterAsExtent( parameters, QStringLiteral(
"EXTENT" ), context, mCrs );
104 if ( mHSpacing <= 0 || mVSpacing <= 0 )
105 throw QgsProcessingException( QObject::tr(
"Invalid grid spacing. horizontal: '%1', vertical: '%2'" ).arg( mHSpacing ).arg( mVSpacing ) );
107 if ( mGridExtent.width() < mHSpacing )
110 if ( mGridExtent.height() < mVSpacing )
117 fields.
append(
QgsField( QStringLiteral(
"id" ), QMetaType::Type::LongLong ) );
118 fields.
append(
QgsField( QStringLiteral(
"left" ), QMetaType::Type::Double ) );
119 fields.
append(
QgsField( QStringLiteral(
"top" ), QMetaType::Type::Double ) );
120 fields.
append(
QgsField( QStringLiteral(
"right" ), QMetaType::Type::Double ) );
121 fields.
append(
QgsField( QStringLiteral(
"bottom" ), QMetaType::Type::Double ) );
128 fields.
append(
QgsField( QStringLiteral(
"row_index" ), QMetaType::Type::LongLong ) );
129 fields.
append(
QgsField( QStringLiteral(
"col_index" ), QMetaType::Type::LongLong ) );
148 std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT" ), context, dest, fields, outputWkb, mCrs ) );
157 createPointGrid( sink, feedback );
160 createLineGrid( sink, feedback );
163 createRectangleGrid( sink, feedback );
166 createDiamondGrid( sink, feedback );
169 createHexagonGrid( sink, feedback );
175 outputs.insert( QStringLiteral(
"OUTPUT" ), dest );
179void QgsGridAlgorithm::createPointGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
183 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
184 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
188 const long long cellcnt = rows * cols;
190 int thisProgress = 0;
191 int lastProgress = 0;
193 for (
long long col = 0; col < cols; col++ )
195 const double x = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
197 for (
long long row = 0; row < rows; row++ )
199 const double y = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
204 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
209 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
210 if ( thisProgress != lastProgress )
212 lastProgress = thisProgress;
224void QgsGridAlgorithm::createLineGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
231 hSpace[0] = mHSpacing - mHOverlay;
232 hSpace[1] = mHOverlay;
236 hSpace[0] = mHSpacing;
237 hSpace[1] = mHSpacing;
243 vSpace[0] = mVSpacing - mVOverlay;
244 vSpace[1] = mVOverlay;
248 vSpace[0] = mVSpacing;
249 vSpace[1] = mVSpacing;
256 double cntMax = mGridExtent.height() / mVSpacing;
258 int thisProgress = 0;
259 int lastProgress = 0;
261 double y = mGridExtent.yMaximum();
263 while ( y >= mGridExtent.yMinimum() )
274 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
275 y = y - vSpace[cnt % 2];
281 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) / cntMax ) * 50 );
282 if ( thisProgress != lastProgress )
284 lastProgress = thisProgress;
296 cntMax = mGridExtent.width() / mHSpacing;
300 double x = mGridExtent.xMinimum();
302 while ( x <= mGridExtent.xMaximum() )
312 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
313 x = x + hSpace[cnt % 2];
318 thisProgress =
static_cast<int>(
static_cast<double>( 50 ) + (
static_cast<double>( cnt ) / cntMax ) * 100 );
319 if ( thisProgress != lastProgress )
321 lastProgress = thisProgress;
328void QgsGridAlgorithm::createRectangleGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
332 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
333 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
337 const long long cellcnt = rows * cols;
339 int thisProgress = 0;
340 int lastProgress = 0;
341 QVector< double > ringX( 5 );
342 QVector< double > ringY( 5 );
344 for (
long long col = 0; col < cols; col++ )
349 const double x1 = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
350 const double x2 = x1 + mHSpacing;
352 for (
long long row = 0; row < rows; row++ )
354 const double y1 = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
355 const double y2 = y1 - mVSpacing;
357 ringX = { x1, x2, x2, x1, x1 };
358 ringY = { y1, y1, y2, y2, y1 };
359 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
364 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
369 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
370 if ( thisProgress != lastProgress )
372 lastProgress = thisProgress;
382void QgsGridAlgorithm::createDiamondGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
386 const double halfHSpacing = mHSpacing / 2;
387 const double halfVSpacing = mVSpacing / 2;
389 const double halfHOverlay = mHOverlay / 2;
390 const double halfVOverlay = mVOverlay / 2;
392 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( halfHSpacing - halfHOverlay ) ) );
393 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - halfVOverlay ) ) );
397 const long long cellcnt = rows * cols;
399 int thisProgress = 0;
400 int lastProgress = 0;
401 QVector< double > ringX( 5 );
402 QVector< double > ringY( 5 );
404 for (
long long col = 0; col < cols; col++ )
409 const double x = mGridExtent.xMinimum() - ( col * halfHOverlay );
410 const double x1 = x + ( ( col + 0 ) * halfHSpacing );
411 const double x2 = x + ( ( col + 1 ) * halfHSpacing );
412 const double x3 = x + ( ( col + 2 ) * halfHSpacing );
414 for (
long long row = 0; row < rows; row++ )
416 const double y = mGridExtent.yMaximum() + ( row * halfVOverlay );
422 if ( ( col % 2 ) == 0 )
424 y1 = y - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
425 y2 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
426 y3 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
430 y1 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
431 y2 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
432 y3 = y - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
435 ringX = { x1, x2, x3, x2, x1 };
436 ringY = { y2, y1, y2, y3, y2 };
437 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
442 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
447 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
448 if ( thisProgress != lastProgress )
450 lastProgress = thisProgress;
460void QgsGridAlgorithm::createHexagonGrid( std::unique_ptr<QgsFeatureSink> &sink,
QgsProcessingFeedback *feedback )
465 const double xVertexLo = 0.288675134594813 * mVSpacing;
466 const double xVertexHi = 0.577350269189626 * mVSpacing;
468 mHSpacing = xVertexLo + xVertexHi;
470 mHOverlay = mHSpacing - mHOverlay;
474 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 ) );
477 const double halfVSpacing = mVSpacing / 2;
479 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHOverlay ) ) );
480 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
484 const long long cellcnt = rows * cols;
486 int thisProgress = 0;
487 int lastProgress = 0;
489 QVector< double > ringX( 7 );
490 QVector< double > ringY( 7 );
491 for (
long long col = 0; col < cols; col++ )
500 const double x1 = mGridExtent.xMinimum() + ( col * mHOverlay );
501 const double x2 = x1 + ( xVertexHi - xVertexLo );
502 const double x3 = mGridExtent.xMinimum() + ( col * mHOverlay ) + mHSpacing;
503 const double x4 = x3 + ( xVertexHi - xVertexLo );
505 for (
long long row = 0; row < rows; row++ )
511 if ( ( col % 2 ) == 0 )
513 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
514 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
515 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
519 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
520 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
521 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
524 ringX = { x1, x2, x3, x4, x3, x2, x1 };
525 ringY = { y2, y1, y1, y2, y3, y3, y2 };
526 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
531 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
536 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
537 if ( thisProgress != lastProgress )
539 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.
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.