QGIS API Documentation 3.43.0-Master (2a27c31701b)
qgsalgorithmrandomraster.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmrandomraster.cpp
3 ---------------------
4 begin : May 2020
5 copyright : (C) 2020 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
19#include "qgsrasterfilewriter.h"
20#include "qgsstringutils.h"
21#include "random"
22#include "limits"
23
25
26//
27// QgsRandomRasterAlgorithmBase
28//
29QString QgsRandomRasterAlgorithmBase::group() const
30{
31 return QObject::tr( "Raster creation" );
32}
33
34QString QgsRandomRasterAlgorithmBase::groupId() const
35{
36 return QStringLiteral( "rastercreation" );
37}
38
39void QgsRandomRasterAlgorithmBase::initAlgorithm( const QVariantMap & )
40{
41 addParameter( new QgsProcessingParameterExtent( QStringLiteral( "EXTENT" ), QObject::tr( "Desired extent" ) ) );
42 addParameter( new QgsProcessingParameterCrs( QStringLiteral( "TARGET_CRS" ), QObject::tr( "Target CRS" ), QStringLiteral( "ProjectCrs" ) ) );
43 addParameter( new QgsProcessingParameterNumber( QStringLiteral( "PIXEL_SIZE" ), QObject::tr( "Pixel size" ), Qgis::ProcessingNumberParameterType::Double, 1, false, 0 ) );
44
45 //add specific parameters
46 addAlgorithmParams();
47
48 auto createOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral( "CREATE_OPTIONS" ), QObject::tr( "Creation options" ), QVariant(), false, true );
49 createOptsParam->setMetadata( QVariantMap( { { QStringLiteral( "widget_wrapper" ), QVariantMap( { { QStringLiteral( "widget_type" ), QStringLiteral( "rasteroptions" ) } } ) } } ) );
50 createOptsParam->setFlags( createOptsParam->flags() | Qgis::ProcessingParameterFlag::Advanced );
51 addParameter( createOptsParam.release() );
52
53 addParameter( new QgsProcessingParameterRasterDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Output raster" ) ) );
54}
55
56bool QgsRandomRasterAlgorithmBase::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
57{
58 Q_UNUSED( feedback );
59 mCrs = parameterAsCrs( parameters, QStringLiteral( "TARGET_CRS" ), context );
60 mExtent = parameterAsExtent( parameters, QStringLiteral( "EXTENT" ), context, mCrs );
61 mPixelSize = parameterAsDouble( parameters, QStringLiteral( "PIXEL_SIZE" ), context );
62
63 if ( mPixelSize <= 0 )
64 {
65 throw QgsProcessingException( QObject::tr( "Pixel size must be greater than 0." ) );
66 }
67
68 return true;
69}
70
71QVariantMap QgsRandomRasterAlgorithmBase::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
72{
73 const int typeId = parameterAsInt( parameters, QStringLiteral( "OUTPUT_TYPE" ), context );
74 //prepare specific parameters
75 mRasterDataType = getRasterDataType( typeId );
76 prepareRandomParameters( parameters, context );
77
78 std::random_device rd {};
79 std::mt19937 mersenneTwister { rd() };
80
81 const QString createOptions = parameterAsString( parameters, QStringLiteral( "CREATE_OPTIONS" ), context ).trimmed();
82 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral( "OUTPUT" ), context );
83 const QFileInfo fi( outputFile );
84 const QString outputFormat = QgsRasterFileWriter::driverForExtension( fi.suffix() );
85
86 // round up width and height to the nearest integer as GDAL does (e.g. in gdal_rasterize)
87 // see https://github.com/qgis/QGIS/issues/43547
88 const int rows = static_cast<int>( 0.5 + mExtent.height() / mPixelSize );
89 const int cols = static_cast<int>( 0.5 + mExtent.width() / mPixelSize );
90
91 //build new raster extent based on number of columns and cellsize
92 //this prevents output cellsize being calculated too small
93 const QgsRectangle rasterExtent = QgsRectangle( mExtent.xMinimum(), mExtent.yMaximum() - ( rows * mPixelSize ), mExtent.xMinimum() + ( cols * mPixelSize ), mExtent.yMaximum() );
94
95 auto writer = std::make_unique<QgsRasterFileWriter>( outputFile );
96 writer->setOutputProviderKey( QStringLiteral( "gdal" ) );
97 if ( !createOptions.isEmpty() )
98 {
99 writer->setCreateOptions( createOptions.split( '|' ) );
100 }
101
102 writer->setOutputFormat( outputFormat );
103 std::unique_ptr<QgsRasterDataProvider> provider( writer->createOneBandRaster( mRasterDataType, cols, rows, rasterExtent, mCrs ) );
104 if ( !provider )
105 throw QgsProcessingException( QObject::tr( "Could not create raster output: %1" ).arg( outputFile ) );
106 if ( !provider->isValid() )
107 throw QgsProcessingException( QObject::tr( "Could not create raster output %1: %2" ).arg( outputFile, provider->error().message( QgsErrorMessage::Text ) ) );
108
109 const double step = rows > 0 ? 100.0 / rows : 1;
110
111 for ( int row = 0; row < rows; row++ )
112 {
113 if ( feedback->isCanceled() )
114 {
115 break;
116 }
117 //prepare raw data depending on raster data type
118 QgsRasterBlock block( mRasterDataType, cols, 1 );
119 switch ( mRasterDataType )
120 {
122 {
123 std::vector<quint8> byteRow( cols );
124 for ( int col = 0; col < cols; col++ )
125 {
126 byteRow[col] = static_cast<quint8>( generateRandomLongValue( mersenneTwister ) );
127 }
128 block.setData( QByteArray( reinterpret_cast<const char *>( byteRow.data() ), QgsRasterBlock::typeSize( Qgis::DataType::Byte ) * cols ) );
129 break;
130 }
132 {
133 std::vector<qint8> int8Row( cols );
134 for ( int col = 0; col < cols; col++ )
135 {
136 int8Row[col] = static_cast<qint8>( generateRandomLongValue( mersenneTwister ) );
137 }
138 block.setData( QByteArray( reinterpret_cast<const char *>( int8Row.data() ), QgsRasterBlock::typeSize( Qgis::DataType::Int8 ) * cols ) );
139 break;
140 }
142 {
143 std::vector<qint16> int16Row( cols );
144 for ( int col = 0; col < cols; col++ )
145 {
146 int16Row[col] = static_cast<qint16>( generateRandomLongValue( mersenneTwister ) );
147 }
148 block.setData( QByteArray( reinterpret_cast<const char *>( int16Row.data() ), QgsRasterBlock::typeSize( Qgis::DataType::Int16 ) * cols ) );
149 break;
150 }
152 {
153 std::vector<quint16> uInt16Row( cols );
154 for ( int col = 0; col < cols; col++ )
155 {
156 uInt16Row[col] = static_cast<quint16>( generateRandomLongValue( mersenneTwister ) );
157 }
158 block.setData( QByteArray( reinterpret_cast<const char *>( uInt16Row.data() ), QgsRasterBlock::typeSize( Qgis::DataType::UInt16 ) * cols ) );
159 break;
160 }
162 {
163 std::vector<qint32> int32Row( cols );
164 for ( int col = 0; col < cols; col++ )
165 {
166 int32Row[col] = generateRandomLongValue( mersenneTwister );
167 }
168 block.setData( QByteArray( reinterpret_cast<const char *>( int32Row.data() ), QgsRasterBlock::typeSize( Qgis::DataType::Int32 ) * cols ) );
169 break;
170 }
172 {
173 std::vector<quint32> uInt32Row( cols );
174 for ( int col = 0; col < cols; col++ )
175 {
176 uInt32Row[col] = static_cast<quint32>( generateRandomLongValue( mersenneTwister ) );
177 }
178 block.setData( QByteArray( reinterpret_cast<const char *>( uInt32Row.data() ), QgsRasterBlock::typeSize( Qgis::DataType::UInt32 ) * cols ) );
179 break;
180 }
182 {
183 std::vector<float> float32Row( cols );
184 for ( int col = 0; col < cols; col++ )
185 {
186 float32Row[col] = static_cast<float>( generateRandomDoubleValue( mersenneTwister ) );
187 }
188 block.setData( QByteArray( reinterpret_cast<const char *>( float32Row.data() ), QgsRasterBlock::typeSize( Qgis::DataType::Float32 ) * cols ) );
189 break;
190 }
192 {
193 std::vector<double> float64Row( cols );
194 for ( int col = 0; col < cols; col++ )
195 {
196 float64Row[col] = generateRandomDoubleValue( mersenneTwister );
197 }
198 block.setData( QByteArray( reinterpret_cast<const char *>( float64Row.data() ), QgsRasterBlock::typeSize( Qgis::DataType::Float64 ) * cols ) );
199 break;
200 }
201 default:
202 break;
203 }
204 if ( !provider->writeBlock( &block, 1, 0, row ) )
205 {
206 throw QgsProcessingException( QObject::tr( "Could not write raster block: %1" ).arg( provider->error().summary() ) );
207 }
208 feedback->setProgress( row * step );
209 }
210
211 QVariantMap outputs;
212 outputs.insert( QStringLiteral( "OUTPUT" ), outputFile );
213 return outputs;
214}
215
216//
217//QgsRandomUniformRasterAlgorithm
218//
219QString QgsRandomUniformRasterAlgorithm::name() const
220{
221 return QStringLiteral( "createrandomuniformrasterlayer" );
222}
223
224QString QgsRandomUniformRasterAlgorithm::displayName() const
225{
226 return QObject::tr( "Create random raster layer (uniform distribution)" );
227}
228
229QStringList QgsRandomUniformRasterAlgorithm::tags() const
230{
231 return QObject::tr( "raster,create,random" ).split( ',' );
232}
233
234QString QgsRandomUniformRasterAlgorithm::shortHelpString() const
235{
236 return QObject::tr( "Generates a raster layer for given extent and cell size "
237 "filled with random values.\n"
238 "By default, the values will range between the minimum and "
239 "maximum value of the specified output raster type. This can "
240 "be overridden by using the advanced parameters for lower and "
241 "upper bound value. If the bounds have the same value or both "
242 "are zero (default) the algorithm will create random values in "
243 "the full value range of the chosen raster data type. "
244 "Choosing bounds outside the acceptable range of the output "
245 "raster type will abort the algorithm." );
246}
247
248QgsRandomUniformRasterAlgorithm *QgsRandomUniformRasterAlgorithm::createInstance() const
249{
250 return new QgsRandomUniformRasterAlgorithm();
251}
252
253void QgsRandomUniformRasterAlgorithm::addAlgorithmParams()
254{
255 QStringList rasterDataTypes = QStringList();
256 rasterDataTypes << QStringLiteral( "Byte" )
257 << QStringLiteral( "Integer16" )
258 << QStringLiteral( "Unsigned Integer16" )
259 << QStringLiteral( "Integer32" )
260 << QStringLiteral( "Unsigned Integer32" )
261 << QStringLiteral( "Float32" )
262 << QStringLiteral( "Float64" );
263
264 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 5, false );
265 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
266 addParameter( rasterTypeParameter.release() );
267
268 auto lowerBoundParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "LOWER_BOUND" ), QStringLiteral( "Lower bound for random number range" ), Qgis::ProcessingNumberParameterType::Double, QVariant(), true );
269 lowerBoundParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
270 addParameter( lowerBoundParameter.release() );
271
272 auto upperBoundParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "UPPER_BOUND" ), QStringLiteral( "Upper bound for random number range" ), Qgis::ProcessingNumberParameterType::Double, QVariant(), true );
273 upperBoundParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
274 addParameter( upperBoundParameter.release() );
275}
276
277Qgis::DataType QgsRandomUniformRasterAlgorithm::getRasterDataType( int typeId )
278{
279 switch ( typeId )
280 {
281 case 0:
283 case 1:
285 case 2:
287 case 3:
289 case 4:
291 case 5:
293 case 6:
295 default:
297 }
298}
299
300bool QgsRandomUniformRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
301{
302 mRandomUpperBound = parameterAsDouble( parameters, QStringLiteral( "UPPER_BOUND" ), context );
303 mRandomLowerBound = parameterAsDouble( parameters, QStringLiteral( "LOWER_BOUND" ), context );
304
305 if ( mRandomLowerBound > mRandomUpperBound )
306 throw QgsProcessingException( QObject::tr( "The chosen lower bound for random number range is greater than the upper bound. The lower bound value must be smaller than the upper bound value." ) );
307
308 const int typeId = parameterAsInt( parameters, QStringLiteral( "OUTPUT_TYPE" ), context );
309 const Qgis::DataType rasterDataType = getRasterDataType( typeId );
310
311 switch ( rasterDataType )
312 {
314 if ( mRandomLowerBound < std::numeric_limits<quint8>::min() || mRandomUpperBound > std::numeric_limits<quint8>::max() )
315 throw QgsProcessingException( QObject::tr( "Raster datasets of type %3 only accept positive values between %1 and %2. Please choose other bounds for random values." ).arg( std::numeric_limits<quint8>::min() ).arg( std::numeric_limits<quint8>::max() ).arg( QLatin1String( "Byte" ) ) );
316 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
317 {
318 //if parameters unset (=both are 0 or equal) --> use the whole value range
319 mRandomUpperBound = std::numeric_limits<quint8>::max();
320 mRandomLowerBound = std::numeric_limits<quint8>::min();
321 }
322 break;
324 if ( mRandomLowerBound < std::numeric_limits<qint8>::min() || mRandomUpperBound > std::numeric_limits<qint8>::max() )
325 throw QgsProcessingException( QObject::tr( "Raster datasets of type %3 only accept positive values between %1 and %2. Please choose other bounds for random values." ).arg( std::numeric_limits<qint8>::min() ).arg( std::numeric_limits<qint8>::max() ).arg( QLatin1String( "Int8" ) ) );
326 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
327 {
328 //if parameters unset (=both are 0 or equal) --> use the whole value range
329 mRandomUpperBound = std::numeric_limits<qint8>::max();
330 mRandomLowerBound = std::numeric_limits<qint8>::min();
331 }
332 break;
334 if ( mRandomLowerBound < std::numeric_limits<qint16>::min() || mRandomUpperBound > std::numeric_limits<qint16>::max() )
335 throw QgsProcessingException( QObject::tr( "Raster datasets of type %3 only accept values between %1 and %2. Please choose other bounds for random values." ).arg( std::numeric_limits<qint16>::min() ).arg( std::numeric_limits<qint16>::max() ).arg( QLatin1String( "Integer16" ) ) );
336 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
337 {
338 mRandomUpperBound = std::numeric_limits<qint16>::max();
339 mRandomLowerBound = std::numeric_limits<qint16>::min();
340 }
341 break;
343 if ( mRandomLowerBound < std::numeric_limits<quint16>::min() || mRandomUpperBound > std::numeric_limits<quint16>::max() )
344 throw QgsProcessingException( QObject::tr( "Raster datasets of type %3 only accept positive values between %1 and %2. Please choose other bounds for random values." ).arg( std::numeric_limits<quint16>::min() ).arg( std::numeric_limits<quint16>::max() ).arg( QLatin1String( "Unsigned Integer16" ) ) );
345 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
346 {
347 mRandomUpperBound = std::numeric_limits<quint16>::max();
348 mRandomLowerBound = std::numeric_limits<quint16>::min();
349 }
350 break;
352 if ( mRandomLowerBound < std::numeric_limits<qint32>::min() || mRandomUpperBound > std::numeric_limits<qint32>::max() )
353 throw QgsProcessingException( QObject::tr( "Raster datasets of type %3 only accept values between %1 and %2. Please choose other bounds for random values." ).arg( std::numeric_limits<qint32>::min() ).arg( std::numeric_limits<qint32>::max() ).arg( QLatin1String( "Integer32" ) ) );
354 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
355 {
356 mRandomUpperBound = std::numeric_limits<qint32>::max();
357 mRandomLowerBound = std::numeric_limits<qint32>::min();
358 }
359 break;
361 if ( mRandomLowerBound < std::numeric_limits<quint32>::min() || mRandomUpperBound > std::numeric_limits<quint32>::max() )
362 throw QgsProcessingException( QObject::tr( "Raster datasets of type %3 only accept positive values between %1 and %2. Please choose other bounds for random values." ).arg( std::numeric_limits<quint32>::min() ).arg( std::numeric_limits<quint32>::max() ).arg( QLatin1String( "Unsigned Integer32" ) ) );
363 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
364 {
365 mRandomUpperBound = std::numeric_limits<quint32>::max();
366 mRandomLowerBound = std::numeric_limits<quint32>::min();
367 }
368 break;
370 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
371 {
372 mRandomUpperBound = std::numeric_limits<float>::max();
373 mRandomLowerBound = std::numeric_limits<float>::min();
374 }
375 break;
377 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
378 {
379 mRandomUpperBound = std::numeric_limits<double>::max();
380 mRandomLowerBound = std::numeric_limits<double>::min();
381 }
382 break;
390 break;
391 }
392
393 mRandomUniformIntDistribution = std::uniform_int_distribution<long>( mRandomLowerBound, mRandomUpperBound );
394 mRandomUniformDoubleDistribution = std::uniform_real_distribution<double>( mRandomLowerBound, mRandomUpperBound );
395
396 return true;
397}
398
399long QgsRandomUniformRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
400{
401 return mRandomUniformIntDistribution( mersenneTwister );
402}
403
404double QgsRandomUniformRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
405{
406 return mRandomUniformDoubleDistribution( mersenneTwister );
407}
408
409//
410// QgsRandomBinomialRasterAlgorithm
411//
412QString QgsRandomBinomialRasterAlgorithm::name() const
413{
414 return QStringLiteral( "createrandombinomialrasterlayer" );
415}
416
417QString QgsRandomBinomialRasterAlgorithm::displayName() const
418{
419 return QObject::tr( "Create random raster layer (binomial distribution)" );
420}
421
422QStringList QgsRandomBinomialRasterAlgorithm::tags() const
423{
424 return QObject::tr( "raster,create,binomial,random" ).split( ',' );
425}
426
427QString QgsRandomBinomialRasterAlgorithm::shortHelpString() const
428{
429 return QObject::tr( "Generates a raster layer for given extent and cell size "
430 "filled with binomially distributed random values.\n"
431 "By default, the values will be chosen given an N of 10 and a probability of 0.5. "
432 "This can be overridden by using the advanced parameter for N and probability. "
433 "The raster data type is set to Integer types (Integer16 by default). "
434 "The binomial distribution random values are defined as positive integer numbers. "
435 "A floating point raster will represent a cast of integer values "
436 "to floating point." );
437}
438
439QgsRandomBinomialRasterAlgorithm *QgsRandomBinomialRasterAlgorithm::createInstance() const
440{
441 return new QgsRandomBinomialRasterAlgorithm();
442}
443
444
445void QgsRandomBinomialRasterAlgorithm::addAlgorithmParams()
446{
447 QStringList rasterDataTypes = QStringList();
448 rasterDataTypes << QStringLiteral( "Integer16" )
449 << QStringLiteral( "Unsigned Integer16" )
450 << QStringLiteral( "Integer32" )
451 << QStringLiteral( "Unsigned Integer32" )
452 << QStringLiteral( "Float32" )
453 << QStringLiteral( "Float64" );
454
455 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
456 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
457 addParameter( rasterTypeParameter.release() );
458
459 auto nParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "N" ), QStringLiteral( "N" ), Qgis::ProcessingNumberParameterType::Integer, 10, true, 0 );
460 nParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
461 addParameter( nParameter.release() );
462
463 auto probabilityParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "PROBABILITY" ), QStringLiteral( "Probability" ), Qgis::ProcessingNumberParameterType::Double, 0.5, true, 0 );
464 probabilityParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
465 addParameter( probabilityParameter.release() );
466}
467
468Qgis::DataType QgsRandomBinomialRasterAlgorithm::getRasterDataType( int typeId )
469{
470 switch ( typeId )
471 {
472 case 0:
474 case 1:
476 case 2:
478 case 3:
480 case 4:
482 case 5:
484 default:
486 }
487}
488
489bool QgsRandomBinomialRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
490{
491 const int n = parameterAsInt( parameters, QStringLiteral( "N" ), context );
492 const double probability = parameterAsDouble( parameters, QStringLiteral( "PROBABILITY" ), context );
493 mRandombinomialDistribution = std::binomial_distribution<long>( n, probability );
494 return true;
495}
496
497long QgsRandomBinomialRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
498{
499 return mRandombinomialDistribution( mersenneTwister );
500}
501
502double QgsRandomBinomialRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
503{
504 return static_cast<double>( mRandombinomialDistribution( mersenneTwister ) );
505}
506
507//
508// QgsRandomExponentialRasterAlgorithm
509//
510QString QgsRandomExponentialRasterAlgorithm::name() const
511{
512 return QStringLiteral( "createrandomexponentialrasterlayer" );
513}
514
515QString QgsRandomExponentialRasterAlgorithm::displayName() const
516{
517 return QObject::tr( "Create random raster layer (exponential distribution)" );
518}
519
520QStringList QgsRandomExponentialRasterAlgorithm::tags() const
521{
522 return QObject::tr( "raster,create,random,exponential" ).split( ',' );
523}
524
525QString QgsRandomExponentialRasterAlgorithm::shortHelpString() const
526{
527 return QObject::tr( "Generates a raster layer for given extent and cell size "
528 "filled with exponentially distributed random values.\n"
529 "By default, the values will be chosen given a lambda of 1.0. "
530 "This can be overridden by using the advanced parameter for lambda. "
531 "The raster data type is set to Float32 by default as "
532 "the exponential distribution random values are floating point numbers." );
533}
534
535QgsRandomExponentialRasterAlgorithm *QgsRandomExponentialRasterAlgorithm::createInstance() const
536{
537 return new QgsRandomExponentialRasterAlgorithm();
538}
539
540
541void QgsRandomExponentialRasterAlgorithm::addAlgorithmParams()
542{
543 QStringList rasterDataTypes = QStringList();
544 rasterDataTypes << QStringLiteral( "Float32" )
545 << QStringLiteral( "Float64" );
546
547 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
548 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
549 addParameter( rasterTypeParameter.release() );
550
551 auto lambdaParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "LAMBDA" ), QStringLiteral( "Lambda" ), Qgis::ProcessingNumberParameterType::Double, 1.0, true, 0.000001 );
552 lambdaParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
553 addParameter( lambdaParameter.release() );
554}
555
556Qgis::DataType QgsRandomExponentialRasterAlgorithm::getRasterDataType( int typeId )
557{
558 switch ( typeId )
559 {
560 case 0:
562 case 1:
564 default:
566 }
567}
568
569bool QgsRandomExponentialRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
570{
571 const double lambda = parameterAsDouble( parameters, QStringLiteral( "LAMBDA" ), context );
572 mRandomExponentialDistribution = std::exponential_distribution<double>( lambda );
573 return true;
574}
575
576long QgsRandomExponentialRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
577{
578 return static_cast<long>( mRandomExponentialDistribution( mersenneTwister ) );
579}
580
581double QgsRandomExponentialRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
582{
583 return mRandomExponentialDistribution( mersenneTwister );
584}
585
586//
587// QgsRandomGammaRasterAlgorithm
588//
589QString QgsRandomGammaRasterAlgorithm::name() const
590{
591 return QStringLiteral( "createrandomgammarasterlayer" );
592}
593
594QString QgsRandomGammaRasterAlgorithm::displayName() const
595{
596 return QObject::tr( "Create random raster layer (gamma distribution)" );
597}
598
599QStringList QgsRandomGammaRasterAlgorithm::tags() const
600{
601 return QObject::tr( "raster,create,random,gamma" ).split( ',' );
602}
603
604QString QgsRandomGammaRasterAlgorithm::shortHelpString() const
605{
606 return QObject::tr( "Generates a raster layer for given extent and cell size "
607 "filled with gamma distributed random values.\n"
608 "By default, the values will be chosen given an alpha and beta value of 1.0. "
609 "This can be overridden by using the advanced parameter for alpha and beta. "
610 "The raster data type is set to Float32 by default as "
611 "the gamma distribution random values are floating point numbers." );
612}
613
614QgsRandomGammaRasterAlgorithm *QgsRandomGammaRasterAlgorithm::createInstance() const
615{
616 return new QgsRandomGammaRasterAlgorithm();
617}
618
619
620void QgsRandomGammaRasterAlgorithm::addAlgorithmParams()
621{
622 QStringList rasterDataTypes = QStringList();
623 rasterDataTypes << QStringLiteral( "Float32" )
624 << QStringLiteral( "Float64" );
625
626 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
627 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
628 addParameter( rasterTypeParameter.release() );
629
630 auto alphaParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "ALPHA" ), QStringLiteral( "Alpha" ), Qgis::ProcessingNumberParameterType::Double, 1.0, true, 0.000001 );
631 alphaParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
632 addParameter( alphaParameter.release() );
633
634 auto betaParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "BETA" ), QStringLiteral( "Beta" ), Qgis::ProcessingNumberParameterType::Double, 1.0, true, 0.000001 );
635 betaParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
636 addParameter( betaParameter.release() );
637}
638
639Qgis::DataType QgsRandomGammaRasterAlgorithm::getRasterDataType( int typeId )
640{
641 switch ( typeId )
642 {
643 case 0:
645 case 1:
647 default:
649 }
650}
651
652bool QgsRandomGammaRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
653{
654 const double alpha = parameterAsDouble( parameters, QStringLiteral( "ALPHA" ), context );
655 const double beta = parameterAsDouble( parameters, QStringLiteral( "BETA" ), context );
656 mRandomGammaDistribution = std::gamma_distribution<double>( alpha, beta );
657 return true;
658}
659
660long QgsRandomGammaRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
661{
662 return static_cast<long>( mRandomGammaDistribution( mersenneTwister ) );
663}
664
665double QgsRandomGammaRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
666{
667 return mRandomGammaDistribution( mersenneTwister );
668}
669
670//
671// QgsRandomGeometricRasterAlgorithm
672//
673QString QgsRandomGeometricRasterAlgorithm::name() const
674{
675 return QStringLiteral( "createrandomgeometricrasterlayer" );
676}
677
678QString QgsRandomGeometricRasterAlgorithm::displayName() const
679{
680 return QObject::tr( "Create random raster layer (geometric distribution)" );
681}
682
683QStringList QgsRandomGeometricRasterAlgorithm::tags() const
684{
685 return QObject::tr( "raster,create,random,geometric" ).split( ',' );
686}
687
688QString QgsRandomGeometricRasterAlgorithm::shortHelpString() const
689{
690 return QObject::tr( "Generates a raster layer for given extent and cell size "
691 "filled with geometrically distributed random values.\n"
692 "By default, the values will be chosen given a probability of 0.5. "
693 "This can be overridden by using the advanced parameter for mean "
694 "value. The raster data type is set to Integer types (Integer16 by default). "
695 "The geometric distribution random values are defined as positive integer numbers. "
696 "A floating point raster will represent a cast of "
697 "integer values to floating point." );
698}
699
700QgsRandomGeometricRasterAlgorithm *QgsRandomGeometricRasterAlgorithm::createInstance() const
701{
702 return new QgsRandomGeometricRasterAlgorithm();
703}
704
705
706void QgsRandomGeometricRasterAlgorithm::addAlgorithmParams()
707{
708 QStringList rasterDataTypes = QStringList();
709 rasterDataTypes << QStringLiteral( "Integer16" )
710 << QStringLiteral( "Unsigned Integer16" )
711 << QStringLiteral( "Integer32" )
712 << QStringLiteral( "Unsigned Integer32" )
713 << QStringLiteral( "Float32" )
714 << QStringLiteral( "Float64" );
715
716 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
717 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
718 addParameter( rasterTypeParameter.release() );
719
720 auto probabilityParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "PROBABILITY" ), QStringLiteral( "Probability" ), Qgis::ProcessingNumberParameterType::Double, 0.5, true, 0.00001 );
721 probabilityParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
722 addParameter( probabilityParameter.release() );
723}
724
725Qgis::DataType QgsRandomGeometricRasterAlgorithm::getRasterDataType( int typeId )
726{
727 switch ( typeId )
728 {
729 case 0:
731 case 1:
733 case 2:
735 case 3:
737 case 4:
739 case 5:
741 default:
743 }
744}
745
746bool QgsRandomGeometricRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
747{
748 const double probability = parameterAsDouble( parameters, QStringLiteral( "PROBABILITY" ), context );
749 mRandomGeometricDistribution = std::geometric_distribution<long>( probability );
750 return true;
751}
752
753long QgsRandomGeometricRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
754{
755 return mRandomGeometricDistribution( mersenneTwister );
756}
757
758double QgsRandomGeometricRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
759{
760 return static_cast<double>( mRandomGeometricDistribution( mersenneTwister ) );
761}
762
763//
764// QgsRandomNegativeBinomialRasterAlgorithm
765//
766QString QgsRandomNegativeBinomialRasterAlgorithm::name() const
767{
768 return QStringLiteral( "createrandomnegativebinomialrasterlayer" );
769}
770
771QString QgsRandomNegativeBinomialRasterAlgorithm::displayName() const
772{
773 return QObject::tr( "Create random raster layer (negative binomial distribution)" );
774}
775
776QStringList QgsRandomNegativeBinomialRasterAlgorithm::tags() const
777{
778 return QObject::tr( "raster,create,random,negative,binomial,negative-binomial" ).split( ',' );
779}
780
781QString QgsRandomNegativeBinomialRasterAlgorithm::shortHelpString() const
782{
783 return QObject::tr( "Generates a raster layer for given extent and cell size "
784 "filled with negative binomially distributed random values.\n"
785 "By default, the values will be chosen given a distribution parameter k of 10.0 "
786 "and a probability of 0.5. "
787 "This can be overridden by using the advanced parameters for k and probability. "
788 "The raster data type is set to Integer types (Integer 16 by default). "
789 "The negative binomial distribution random values are defined as positive integer numbers. "
790 "A floating point raster will represent a cast of "
791 "integer values to floating point." );
792}
793
794QgsRandomNegativeBinomialRasterAlgorithm *QgsRandomNegativeBinomialRasterAlgorithm::createInstance() const
795{
796 return new QgsRandomNegativeBinomialRasterAlgorithm();
797}
798
799
800void QgsRandomNegativeBinomialRasterAlgorithm::addAlgorithmParams()
801{
802 QStringList rasterDataTypes = QStringList();
803 rasterDataTypes << QStringLiteral( "Integer16" )
804 << QStringLiteral( "Unsigned Integer16" )
805 << QStringLiteral( "Integer32" )
806 << QStringLiteral( "Unsigned Integer32" )
807 << QStringLiteral( "Float32" )
808 << QStringLiteral( "Float64" );
809
810 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
811 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
812 addParameter( rasterTypeParameter.release() );
813
814 auto kParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "K_PARAMETER" ), QStringLiteral( "Distribution parameter k" ), Qgis::ProcessingNumberParameterType::Integer, 10, true, 0.00001 );
815 kParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
816 addParameter( kParameter.release() );
817
818 auto probabilityParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "PROBABILITY" ), QStringLiteral( "Probability" ), Qgis::ProcessingNumberParameterType::Double, 0.5, true, 0.00001 );
819 probabilityParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
820 addParameter( probabilityParameter.release() );
821}
822
823Qgis::DataType QgsRandomNegativeBinomialRasterAlgorithm::getRasterDataType( int typeId )
824{
825 switch ( typeId )
826 {
827 case 0:
829 case 1:
831 case 2:
833 case 3:
835 case 4:
837 case 5:
839 default:
841 }
842}
843
844bool QgsRandomNegativeBinomialRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
845{
846 const int k = parameterAsInt( parameters, QStringLiteral( "K_PARAMETER" ), context );
847 const double probability = parameterAsDouble( parameters, QStringLiteral( "PROBABILITY" ), context );
848 mRandomNegativeBinomialDistribution = std::negative_binomial_distribution<long>( k, probability );
849 return true;
850}
851
852long QgsRandomNegativeBinomialRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
853{
854 return mRandomNegativeBinomialDistribution( mersenneTwister );
855}
856
857double QgsRandomNegativeBinomialRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
858{
859 return static_cast<double>( mRandomNegativeBinomialDistribution( mersenneTwister ) );
860}
861
862//
863// QgsRandomNormalRasterAlgorithm
864//
865QString QgsRandomNormalRasterAlgorithm::name() const
866{
867 return QStringLiteral( "createrandomnormalrasterlayer" );
868}
869
870QString QgsRandomNormalRasterAlgorithm::displayName() const
871{
872 return QObject::tr( "Create random raster layer (normal distribution)" );
873}
874
875QStringList QgsRandomNormalRasterAlgorithm::tags() const
876{
877 return QObject::tr( "raster,create,normal,distribution,random" ).split( ',' );
878}
879
880QString QgsRandomNormalRasterAlgorithm::shortHelpString() const
881{
882 return QObject::tr( "Generates a raster layer for given extent and cell size "
883 "filled with normally distributed random values.\n"
884 "By default, the values will be chosen given a mean of 0.0 and "
885 "a standard deviation of 1.0. This can be overridden by "
886 "using the advanced parameters for mean and standard deviation "
887 "value. The raster data type is set to Float32 by default "
888 "as the normal distribution random values are floating point numbers." );
889}
890
891QgsRandomNormalRasterAlgorithm *QgsRandomNormalRasterAlgorithm::createInstance() const
892{
893 return new QgsRandomNormalRasterAlgorithm();
894}
895
896void QgsRandomNormalRasterAlgorithm::addAlgorithmParams()
897{
898 QStringList rasterDataTypes = QStringList();
899 rasterDataTypes << QStringLiteral( "Float32" )
900 << QStringLiteral( "Float64" );
901
902 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
903 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
904 addParameter( rasterTypeParameter.release() );
905
906 auto meanParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "MEAN" ), QStringLiteral( "Mean of normal distribution" ), Qgis::ProcessingNumberParameterType::Double, 0, true );
907 meanParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
908 addParameter( meanParameter.release() );
909
910 auto stdevParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "STDDEV" ), QStringLiteral( "Standard deviation of normal distribution" ), Qgis::ProcessingNumberParameterType::Double, 1, true, 0 );
911 stdevParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
912 addParameter( stdevParameter.release() );
913}
914
915Qgis::DataType QgsRandomNormalRasterAlgorithm::getRasterDataType( int typeId )
916{
917 switch ( typeId )
918 {
919 case 0:
921 case 1:
923 default:
925 }
926}
927
928bool QgsRandomNormalRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
929{
930 const double mean = parameterAsDouble( parameters, QStringLiteral( "MEAN" ), context );
931 const double stddev = parameterAsDouble( parameters, QStringLiteral( "STDDEV" ), context );
932 mRandomNormalDistribution = std::normal_distribution<double>( mean, stddev );
933 return true;
934}
935
936long QgsRandomNormalRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
937{
938 return static_cast<long>( mRandomNormalDistribution( mersenneTwister ) );
939}
940
941double QgsRandomNormalRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
942{
943 return mRandomNormalDistribution( mersenneTwister );
944}
945
946//
947// QgsRandomPoissonRasterAlgorithm
948//
949QString QgsRandomPoissonRasterAlgorithm::name() const
950{
951 return QStringLiteral( "createrandompoissonrasterlayer" );
952}
953
954QString QgsRandomPoissonRasterAlgorithm::displayName() const
955{
956 return QObject::tr( "Create random raster layer (poisson distribution)" );
957}
958
959QStringList QgsRandomPoissonRasterAlgorithm::tags() const
960{
961 return QObject::tr( "raster,create,random,poisson" ).split( ',' );
962}
963
964QString QgsRandomPoissonRasterAlgorithm::shortHelpString() const
965{
966 return QObject::tr( "Generates a raster layer for given extent and cell size "
967 "filled with poisson distributed random values.\n"
968 "By default, the values will be chosen given a mean of 1.0. "
969 "This can be overridden by using the advanced parameter for mean "
970 "value. The raster data type is set to Integer types (Integer16 by default). "
971 "The poisson distribution random values are positive integer numbers. "
972 "A floating point raster will represent a cast of integer values to floating point." );
973}
974
975QgsRandomPoissonRasterAlgorithm *QgsRandomPoissonRasterAlgorithm::createInstance() const
976{
977 return new QgsRandomPoissonRasterAlgorithm();
978}
979
980
981void QgsRandomPoissonRasterAlgorithm::addAlgorithmParams()
982{
983 QStringList rasterDataTypes = QStringList();
984 rasterDataTypes << QStringLiteral( "Integer16" )
985 << QStringLiteral( "Unsigned Integer16" )
986 << QStringLiteral( "Integer32" )
987 << QStringLiteral( "Unsigned Integer32" )
988 << QStringLiteral( "Float32" )
989 << QStringLiteral( "Float64" );
990
991 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
992 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
993 addParameter( rasterTypeParameter.release() );
994
995 auto upperBoundParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "MEAN" ), QStringLiteral( "Mean" ), Qgis::ProcessingNumberParameterType::Double, 1.0, true, 0 );
996 upperBoundParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
997 addParameter( upperBoundParameter.release() );
998}
999
1000Qgis::DataType QgsRandomPoissonRasterAlgorithm::getRasterDataType( int typeId )
1001{
1002 switch ( typeId )
1003 {
1004 case 0:
1005 return Qgis::DataType::Int16;
1006 case 1:
1008 case 2:
1009 return Qgis::DataType::Int32;
1010 case 3:
1012 case 4:
1014 case 5:
1016 default:
1018 }
1019}
1020
1021bool QgsRandomPoissonRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
1022{
1023 const double mean = parameterAsDouble( parameters, QStringLiteral( "MEAN" ), context );
1024 mRandomPoissonDistribution = std::poisson_distribution<long>( mean );
1025 return true;
1026}
1027
1028long QgsRandomPoissonRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
1029{
1030 return mRandomPoissonDistribution( mersenneTwister );
1031}
1032
1033double QgsRandomPoissonRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
1034{
1035 return static_cast<double>( mRandomPoissonDistribution( mersenneTwister ) );
1036}
1037
DataType
Raster data types.
Definition qgis.h:351
@ CInt32
Complex Int32.
@ Float32
Thirty two bit floating point (float)
@ CFloat64
Complex Float64.
@ Int16
Sixteen bit signed integer (qint16)
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30)
@ UInt16
Sixteen bit unsigned integer (quint16)
@ Byte
Eight bit unsigned integer (quint8)
@ UnknownDataType
Unknown or unspecified type.
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
@ Int32
Thirty two bit signed integer (qint32)
@ Float64
Sixty four bit floating point (double)
@ CFloat32
Complex Float32.
@ CInt16
Complex Int16.
@ UInt32
Thirty two bit unsigned integer (quint32)
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:53
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:61
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 rectangular map extent parameter for processing algorithms.
A numeric parameter for processing algorithms.
A raster layer destination parameter, for specifying the destination path for a raster layer created ...
Raster data container.
static int typeSize(Qgis::DataType dataType)
Returns the size in bytes for the specified dataType.
static QString driverForExtension(const QString &extension)
Returns the GDAL driver name for a specified file extension.
A rectangle specified with double values.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:6206