28 QString QgsGridAlgorithm::name()
const
30 return QStringLiteral(
"creategrid" );
33 QString QgsGridAlgorithm::displayName()
const
35 return QObject::tr(
"Create grid" );
38 QStringList QgsGridAlgorithm::tags()
const
40 return QObject::tr(
"grid,lines,polygons,vector,create,fishnet,diamond,hexagon" ).split(
',' );
43 QString QgsGridAlgorithm::group()
const
45 return QObject::tr(
"Vector creation" );
48 QString QgsGridAlgorithm::groupId()
const
50 return QStringLiteral(
"vectorcreation" );
53 void 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, 0, 1000000000.0 ) );
63 addParameter(
new QgsProcessingParameterDistance( QStringLiteral(
"VOVERLAY" ), QObject::tr(
"Vertical overlay" ), 0, QStringLiteral(
"CRS" ),
false, 0, 1000000000.0 ) );
65 addParameter(
new QgsProcessingParameterCrs( QStringLiteral(
"CRS" ), QObject::tr(
"Grid CRS" ), QStringLiteral(
"ProjectCrs" ) ) );
70 QString 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."
84 QgsGridAlgorithm *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 )
113 if ( mHSpacing <= mHOverlay || mVSpacing <= mVOverlay )
114 throw QgsProcessingException( QObject::tr(
"Invalid overlay: horizontal: '%1', vertical: '%2'" ).arg( mHOverlay ).arg( mVOverlay ) );
117 fields.
append(
QgsField( QStringLiteral(
"id" ), QVariant::LongLong ) );
118 fields.
append(
QgsField( QStringLiteral(
"left" ), QVariant::Double ) );
119 fields.
append(
QgsField( QStringLiteral(
"top" ), QVariant::Double ) );
120 fields.
append(
QgsField( QStringLiteral(
"right" ), QVariant::Double ) );
121 fields.
append(
QgsField( QStringLiteral(
"bottom" ), QVariant::Double ) );
135 std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT" ), context, dest, fields, outputWkb, mCrs ) );
144 createPointGrid( sink, feedback );
147 createLineGrid( sink, feedback );
150 createRectangleGrid( sink, feedback );
153 createDiamondGrid( sink, feedback );
156 createHexagonGrid( sink, feedback );
162 outputs.insert( QStringLiteral(
"OUTPUT" ), dest );
166 void QgsGridAlgorithm::createPointGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
170 long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
171 long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
175 long long cellcnt = rows * cols;
177 int thisProgress = 0;
178 int lastProgress = 0;
180 for (
long long col = 0; col < cols; col++ )
182 double x = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
184 for (
long long row = 0; row < rows; row++ )
186 double y = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
195 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
196 if ( thisProgress != lastProgress )
198 lastProgress = thisProgress;
210 void QgsGridAlgorithm::createLineGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
217 hSpace[0] = mHSpacing - mHOverlay;
218 hSpace[1] = mHOverlay;
222 hSpace[0] = mHSpacing;
223 hSpace[1] = mHSpacing;
229 vSpace[0] = mVSpacing - mVOverlay;
230 vSpace[1] = mVOverlay;
234 vSpace[0] = mVSpacing;
235 vSpace[1] = mVSpacing;
242 double cntMax = mGridExtent.height() / mVSpacing;
244 int thisProgress = 0;
245 int lastProgress = 0;
247 double y = mGridExtent.yMaximum();
249 while ( y >= mGridExtent.yMinimum() )
260 y = y - vSpace[cnt % 2];
266 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) / cntMax ) * 50 );
267 if ( thisProgress != lastProgress )
269 lastProgress = thisProgress;
281 cntMax = mGridExtent.width() / mHSpacing;
285 double x = mGridExtent.xMinimum();
287 while ( x <= mGridExtent.xMaximum() )
297 x = x + hSpace[cnt % 2];
302 thisProgress =
static_cast<int>(
static_cast<double>( 50 ) + (
static_cast<double>( cnt ) / cntMax ) * 100 );
303 if ( thisProgress != lastProgress )
305 lastProgress = thisProgress;
312 void QgsGridAlgorithm::createRectangleGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
316 long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
317 long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
321 long long cellcnt = rows * cols;
323 int thisProgress = 0;
324 int lastProgress = 0;
325 QVector< double > ringX( 5 );
326 QVector< double > ringY( 5 );
328 for (
long long col = 0; col < cols; col++ )
333 const double x1 = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
334 const double x2 = x1 + mHSpacing;
336 for (
long long row = 0; row < rows; row++ )
338 const double y1 = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
339 const double y2 = y1 - mVSpacing;
341 ringX = { x1, x2, x2, x1, x1 };
342 ringY = { y1, y1, y2, y2, y1 };
343 std::unique_ptr< QgsPolygon > poly = qgis::make_unique< QgsPolygon >();
352 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
353 if ( thisProgress != lastProgress )
355 lastProgress = thisProgress;
365 void QgsGridAlgorithm::createDiamondGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
369 double halfHSpacing = mHSpacing / 2;
370 double halfVSpacing = mVSpacing / 2;
372 double halfHOverlay = mHOverlay / 2;
373 double halfVOverlay = mVOverlay / 2;
375 long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( halfHSpacing - halfHOverlay ) ) );
376 long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - halfVOverlay ) ) );
380 long long cellcnt = rows * cols;
382 int thisProgress = 0;
383 int lastProgress = 0;
384 QVector< double > ringX( 5 );
385 QVector< double > ringY( 5 );
387 for (
long long col = 0; col < cols; col++ )
392 double x = mGridExtent.xMinimum() - ( col * halfHOverlay );
393 double x1 = x + ( ( col + 0 ) * halfHSpacing );
394 double x2 = x + ( ( col + 1 ) * halfHSpacing );
395 double x3 = x + ( ( col + 2 ) * halfHSpacing );
397 for (
long long row = 0; row < rows; row++ )
399 double y = mGridExtent.yMaximum() + ( row * halfVOverlay );
405 if ( ( col % 2 ) == 0 )
407 y1 = y - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
408 y2 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
409 y3 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
413 y1 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
414 y2 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
415 y3 = y - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
418 ringX = { x1, x2, x3, x2, x1 };
419 ringY = { y2, y1, y2, y3, y2 };
420 std::unique_ptr< QgsPolygon > poly = qgis::make_unique< QgsPolygon >();
429 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
430 if ( thisProgress != lastProgress )
432 lastProgress = thisProgress;
442 void QgsGridAlgorithm::createHexagonGrid( std::unique_ptr<QgsFeatureSink> &sink,
QgsProcessingFeedback *feedback )
447 double xVertexLo = 0.288675134594813 * mVSpacing;
448 double xVertexHi = 0.577350269189626 * mVSpacing;
450 mHSpacing = xVertexLo + xVertexHi;
452 mHOverlay = mHSpacing - mHOverlay;
456 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 ) );
459 double halfVSpacing = mVSpacing / 2;
461 long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHOverlay ) ) );
462 long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
466 long long cellcnt = rows * cols;
468 int thisProgress = 0;
469 int lastProgress = 0;
471 QVector< double > ringX( 7 );
472 QVector< double > ringY( 7 );
473 for (
long long col = 0; col < cols; col++ )
482 double x1 = mGridExtent.xMinimum() + ( col * mHOverlay );
483 double x2 = x1 + ( xVertexHi - xVertexLo );
484 double x3 = mGridExtent.xMinimum() + ( col * mHOverlay ) + mHSpacing;
485 double x4 = x3 + ( xVertexHi - xVertexLo );
487 for (
long long row = 0; row < rows; row++ )
493 if ( ( col % 2 ) == 0 )
495 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
496 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
497 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
501 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
502 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
503 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
506 ringX = { x1, x2, x3, x4, x3, x2, x1 };
507 ringY = { y2, y1, y1, y2, y3, y3, y2 };
508 std::unique_ptr< QgsPolygon > poly = qgis::make_unique< QgsPolygon >();
517 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
518 if ( thisProgress != lastProgress )
520 lastProgress = thisProgress;