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 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
171 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
175 const long long cellcnt = rows * cols;
177 int thisProgress = 0;
178 int lastProgress = 0;
180 for (
long long col = 0; col < cols; col++ )
182 const double x = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
184 for (
long long row = 0; row < rows; row++ )
186 const double y = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
191 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
196 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
197 if ( thisProgress != lastProgress )
199 lastProgress = thisProgress;
211 void QgsGridAlgorithm::createLineGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
218 hSpace[0] = mHSpacing - mHOverlay;
219 hSpace[1] = mHOverlay;
223 hSpace[0] = mHSpacing;
224 hSpace[1] = mHSpacing;
230 vSpace[0] = mVSpacing - mVOverlay;
231 vSpace[1] = mVOverlay;
235 vSpace[0] = mVSpacing;
236 vSpace[1] = mVSpacing;
243 double cntMax = mGridExtent.height() / mVSpacing;
245 int thisProgress = 0;
246 int lastProgress = 0;
248 double y = mGridExtent.yMaximum();
250 while ( y >= mGridExtent.yMinimum() )
261 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
262 y = y - vSpace[cnt % 2];
268 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) / cntMax ) * 50 );
269 if ( thisProgress != lastProgress )
271 lastProgress = thisProgress;
283 cntMax = mGridExtent.width() / mHSpacing;
287 double x = mGridExtent.xMinimum();
289 while ( x <= mGridExtent.xMaximum() )
299 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
300 x = x + hSpace[cnt % 2];
305 thisProgress =
static_cast<int>(
static_cast<double>( 50 ) + (
static_cast<double>( cnt ) / cntMax ) * 100 );
306 if ( thisProgress != lastProgress )
308 lastProgress = thisProgress;
315 void QgsGridAlgorithm::createRectangleGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
319 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHSpacing - mHOverlay ) ) );
320 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
324 const long long cellcnt = rows * cols;
326 int thisProgress = 0;
327 int lastProgress = 0;
328 QVector< double > ringX( 5 );
329 QVector< double > ringY( 5 );
331 for (
long long col = 0; col < cols; col++ )
336 const double x1 = mGridExtent.xMinimum() + ( col * mHSpacing - col * mHOverlay );
337 const double x2 = x1 + mHSpacing;
339 for (
long long row = 0; row < rows; row++ )
341 const double y1 = mGridExtent.yMaximum() - ( row * mVSpacing - row * mVOverlay );
342 const double y2 = y1 - mVSpacing;
344 ringX = { x1, x2, x2, x1, x1 };
345 ringY = { y1, y1, y2, y2, y1 };
346 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
351 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
356 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
357 if ( thisProgress != lastProgress )
359 lastProgress = thisProgress;
369 void QgsGridAlgorithm::createDiamondGrid( std::unique_ptr< QgsFeatureSink > &sink,
QgsProcessingFeedback *feedback )
373 const double halfHSpacing = mHSpacing / 2;
374 const double halfVSpacing = mVSpacing / 2;
376 const double halfHOverlay = mHOverlay / 2;
377 const double halfVOverlay = mVOverlay / 2;
379 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( halfHSpacing - halfHOverlay ) ) );
380 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - halfVOverlay ) ) );
384 const long long cellcnt = rows * cols;
386 int thisProgress = 0;
387 int lastProgress = 0;
388 QVector< double > ringX( 5 );
389 QVector< double > ringY( 5 );
391 for (
long long col = 0; col < cols; col++ )
396 const double x = mGridExtent.xMinimum() - ( col * halfHOverlay );
397 const double x1 = x + ( ( col + 0 ) * halfHSpacing );
398 const double x2 = x + ( ( col + 1 ) * halfHSpacing );
399 const double x3 = x + ( ( col + 2 ) * halfHSpacing );
401 for (
long long row = 0; row < rows; row++ )
403 const double y = mGridExtent.yMaximum() + ( row * halfVOverlay );
409 if ( ( col % 2 ) == 0 )
411 y1 = y - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
412 y2 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
413 y3 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
417 y1 = y - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
418 y2 = y - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
419 y3 = y - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
422 ringX = { x1, x2, x3, x2, x1 };
423 ringY = { y2, y1, y2, y3, y2 };
424 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
429 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
434 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
435 if ( thisProgress != lastProgress )
437 lastProgress = thisProgress;
447 void QgsGridAlgorithm::createHexagonGrid( std::unique_ptr<QgsFeatureSink> &sink,
QgsProcessingFeedback *feedback )
452 const double xVertexLo = 0.288675134594813 * mVSpacing;
453 const double xVertexHi = 0.577350269189626 * mVSpacing;
455 mHSpacing = xVertexLo + xVertexHi;
457 mHOverlay = mHSpacing - mHOverlay;
461 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 ) );
464 const double halfVSpacing = mVSpacing / 2;
466 const long long cols =
static_cast<long long>( std::ceil( mGridExtent.width() / ( mHOverlay ) ) );
467 const long long rows =
static_cast<long long>( std::ceil( mGridExtent.height() / ( mVSpacing - mVOverlay ) ) );
471 const long long cellcnt = rows * cols;
473 int thisProgress = 0;
474 int lastProgress = 0;
476 QVector< double > ringX( 7 );
477 QVector< double > ringY( 7 );
478 for (
long long col = 0; col < cols; col++ )
487 const double x1 = mGridExtent.xMinimum() + ( col * mHOverlay );
488 const double x2 = x1 + ( xVertexHi - xVertexLo );
489 const double x3 = mGridExtent.xMinimum() + ( col * mHOverlay ) + mHSpacing;
490 const double x4 = x3 + ( xVertexHi - xVertexLo );
492 for (
long long row = 0; row < rows; row++ )
498 if ( ( col % 2 ) == 0 )
500 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 0 ) * halfVSpacing );
501 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
502 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
506 y1 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 1 ) * halfVSpacing );
507 y2 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 2 ) * halfVSpacing );
508 y3 = mGridExtent.yMaximum() + ( row * mVOverlay ) - ( ( ( row * 2 ) + 3 ) * halfVSpacing );
511 ringX = { x1, x2, x3, x4, x3, x2, x1 };
512 ringY = { y2, y1, y1, y2, y3, y3, y2 };
513 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
518 throw QgsProcessingException( writeFeatureError( sink.get(), QVariantMap(), QStringLiteral(
"OUTPUT" ) ) );
523 thisProgress =
static_cast<int>( (
static_cast<double>( cnt ) /
static_cast<double>( cellcnt ) ) * 100 );
524 if ( thisProgress != lastProgress )
526 lastProgress = thisProgress;