QGIS API Documentation 3.41.0-Master (88383c3d16f)
Loading...
Searching...
No Matches
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 provider->writeBlock( &block, 1, 0, row );
205 feedback->setProgress( row * step );
206 }
207
208 QVariantMap outputs;
209 outputs.insert( QStringLiteral( "OUTPUT" ), outputFile );
210 return outputs;
211}
212
213//
214//QgsRandomUniformRasterAlgorithm
215//
216QString QgsRandomUniformRasterAlgorithm::name() const
217{
218 return QStringLiteral( "createrandomuniformrasterlayer" );
219}
220
221QString QgsRandomUniformRasterAlgorithm::displayName() const
222{
223 return QObject::tr( "Create random raster layer (uniform distribution)" );
224}
225
226QStringList QgsRandomUniformRasterAlgorithm::tags() const
227{
228 return QObject::tr( "raster,create,random" ).split( ',' );
229}
230
231QString QgsRandomUniformRasterAlgorithm::shortHelpString() const
232{
233 return QObject::tr( "Generates a raster layer for given extent and cell size "
234 "filled with random values.\n"
235 "By default, the values will range between the minimum and "
236 "maximum value of the specified output raster type. This can "
237 "be overridden by using the advanced parameters for lower and "
238 "upper bound value. If the bounds have the same value or both "
239 "are zero (default) the algorithm will create random values in "
240 "the full value range of the chosen raster data type. "
241 "Choosing bounds outside the acceptable range of the output "
242 "raster type will abort the algorithm." );
243}
244
245QgsRandomUniformRasterAlgorithm *QgsRandomUniformRasterAlgorithm::createInstance() const
246{
247 return new QgsRandomUniformRasterAlgorithm();
248}
249
250void QgsRandomUniformRasterAlgorithm::addAlgorithmParams()
251{
252 QStringList rasterDataTypes = QStringList();
253 rasterDataTypes << QStringLiteral( "Byte" )
254 << QStringLiteral( "Integer16" )
255 << QStringLiteral( "Unsigned Integer16" )
256 << QStringLiteral( "Integer32" )
257 << QStringLiteral( "Unsigned Integer32" )
258 << QStringLiteral( "Float32" )
259 << QStringLiteral( "Float64" );
260
261 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 5, false );
262 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
263 addParameter( rasterTypeParameter.release() );
264
265 auto lowerBoundParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "LOWER_BOUND" ), QStringLiteral( "Lower bound for random number range" ), Qgis::ProcessingNumberParameterType::Double, QVariant(), true );
266 lowerBoundParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
267 addParameter( lowerBoundParameter.release() );
268
269 auto upperBoundParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "UPPER_BOUND" ), QStringLiteral( "Upper bound for random number range" ), Qgis::ProcessingNumberParameterType::Double, QVariant(), true );
270 upperBoundParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
271 addParameter( upperBoundParameter.release() );
272}
273
274Qgis::DataType QgsRandomUniformRasterAlgorithm::getRasterDataType( int typeId )
275{
276 switch ( typeId )
277 {
278 case 0:
280 case 1:
282 case 2:
284 case 3:
286 case 4:
288 case 5:
290 case 6:
292 default:
294 }
295}
296
297bool QgsRandomUniformRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
298{
299 mRandomUpperBound = parameterAsDouble( parameters, QStringLiteral( "UPPER_BOUND" ), context );
300 mRandomLowerBound = parameterAsDouble( parameters, QStringLiteral( "LOWER_BOUND" ), context );
301
302 if ( mRandomLowerBound > mRandomUpperBound )
303 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." ) );
304
305 const int typeId = parameterAsInt( parameters, QStringLiteral( "OUTPUT_TYPE" ), context );
306 const Qgis::DataType rasterDataType = getRasterDataType( typeId );
307
308 switch ( rasterDataType )
309 {
311 if ( mRandomLowerBound < std::numeric_limits<quint8>::min() || mRandomUpperBound > std::numeric_limits<quint8>::max() )
312 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" ) ) );
313 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
314 {
315 //if parameters unset (=both are 0 or equal) --> use the whole value range
316 mRandomUpperBound = std::numeric_limits<quint8>::max();
317 mRandomLowerBound = std::numeric_limits<quint8>::min();
318 }
319 break;
321 if ( mRandomLowerBound < std::numeric_limits<qint8>::min() || mRandomUpperBound > std::numeric_limits<qint8>::max() )
322 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" ) ) );
323 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
324 {
325 //if parameters unset (=both are 0 or equal) --> use the whole value range
326 mRandomUpperBound = std::numeric_limits<qint8>::max();
327 mRandomLowerBound = std::numeric_limits<qint8>::min();
328 }
329 break;
331 if ( mRandomLowerBound < std::numeric_limits<qint16>::min() || mRandomUpperBound > std::numeric_limits<qint16>::max() )
332 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" ) ) );
333 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
334 {
335 mRandomUpperBound = std::numeric_limits<qint16>::max();
336 mRandomLowerBound = std::numeric_limits<qint16>::min();
337 }
338 break;
340 if ( mRandomLowerBound < std::numeric_limits<quint16>::min() || mRandomUpperBound > std::numeric_limits<quint16>::max() )
341 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" ) ) );
342 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
343 {
344 mRandomUpperBound = std::numeric_limits<quint16>::max();
345 mRandomLowerBound = std::numeric_limits<quint16>::min();
346 }
347 break;
349 if ( mRandomLowerBound < std::numeric_limits<qint32>::min() || mRandomUpperBound > std::numeric_limits<qint32>::max() )
350 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" ) ) );
351 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
352 {
353 mRandomUpperBound = std::numeric_limits<qint32>::max();
354 mRandomLowerBound = std::numeric_limits<qint32>::min();
355 }
356 break;
358 if ( mRandomLowerBound < std::numeric_limits<quint32>::min() || mRandomUpperBound > std::numeric_limits<quint32>::max() )
359 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" ) ) );
360 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
361 {
362 mRandomUpperBound = std::numeric_limits<quint32>::max();
363 mRandomLowerBound = std::numeric_limits<quint32>::min();
364 }
365 break;
367 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
368 {
369 mRandomUpperBound = std::numeric_limits<float>::max();
370 mRandomLowerBound = std::numeric_limits<float>::min();
371 }
372 break;
374 if ( ( qgsDoubleNear( mRandomLowerBound, 0.0 ) && qgsDoubleNear( mRandomUpperBound, 0.0 ) ) || qgsDoubleNear( mRandomUpperBound, mRandomLowerBound ) )
375 {
376 mRandomUpperBound = std::numeric_limits<double>::max();
377 mRandomLowerBound = std::numeric_limits<double>::min();
378 }
379 break;
387 break;
388 }
389
390 mRandomUniformIntDistribution = std::uniform_int_distribution<long>( mRandomLowerBound, mRandomUpperBound );
391 mRandomUniformDoubleDistribution = std::uniform_real_distribution<double>( mRandomLowerBound, mRandomUpperBound );
392
393 return true;
394}
395
396long QgsRandomUniformRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
397{
398 return mRandomUniformIntDistribution( mersenneTwister );
399}
400
401double QgsRandomUniformRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
402{
403 return mRandomUniformDoubleDistribution( mersenneTwister );
404}
405
406//
407// QgsRandomBinomialRasterAlgorithm
408//
409QString QgsRandomBinomialRasterAlgorithm::name() const
410{
411 return QStringLiteral( "createrandombinomialrasterlayer" );
412}
413
414QString QgsRandomBinomialRasterAlgorithm::displayName() const
415{
416 return QObject::tr( "Create random raster layer (binomial distribution)" );
417}
418
419QStringList QgsRandomBinomialRasterAlgorithm::tags() const
420{
421 return QObject::tr( "raster,create,binomial,random" ).split( ',' );
422}
423
424QString QgsRandomBinomialRasterAlgorithm::shortHelpString() const
425{
426 return QObject::tr( "Generates a raster layer for given extent and cell size "
427 "filled with binomially distributed random values.\n"
428 "By default, the values will be chosen given an N of 10 and a probability of 0.5. "
429 "This can be overridden by using the advanced parameter for N and probability. "
430 "The raster data type is set to Integer types (Integer16 by default). "
431 "The binomial distribution random values are defined as positive integer numbers. "
432 "A floating point raster will represent a cast of integer values "
433 "to floating point." );
434}
435
436QgsRandomBinomialRasterAlgorithm *QgsRandomBinomialRasterAlgorithm::createInstance() const
437{
438 return new QgsRandomBinomialRasterAlgorithm();
439}
440
441
442void QgsRandomBinomialRasterAlgorithm::addAlgorithmParams()
443{
444 QStringList rasterDataTypes = QStringList();
445 rasterDataTypes << QStringLiteral( "Integer16" )
446 << QStringLiteral( "Unsigned Integer16" )
447 << QStringLiteral( "Integer32" )
448 << QStringLiteral( "Unsigned Integer32" )
449 << QStringLiteral( "Float32" )
450 << QStringLiteral( "Float64" );
451
452 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
453 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
454 addParameter( rasterTypeParameter.release() );
455
456 auto nParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "N" ), QStringLiteral( "N" ), Qgis::ProcessingNumberParameterType::Integer, 10, true, 0 );
457 nParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
458 addParameter( nParameter.release() );
459
460 auto probabilityParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "PROBABILITY" ), QStringLiteral( "Probability" ), Qgis::ProcessingNumberParameterType::Double, 0.5, true, 0 );
461 probabilityParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
462 addParameter( probabilityParameter.release() );
463}
464
465Qgis::DataType QgsRandomBinomialRasterAlgorithm::getRasterDataType( int typeId )
466{
467 switch ( typeId )
468 {
469 case 0:
471 case 1:
473 case 2:
475 case 3:
477 case 4:
479 case 5:
481 default:
483 }
484}
485
486bool QgsRandomBinomialRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
487{
488 const int n = parameterAsInt( parameters, QStringLiteral( "N" ), context );
489 const double probability = parameterAsDouble( parameters, QStringLiteral( "PROBABILITY" ), context );
490 mRandombinomialDistribution = std::binomial_distribution<long>( n, probability );
491 return true;
492}
493
494long QgsRandomBinomialRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
495{
496 return mRandombinomialDistribution( mersenneTwister );
497}
498
499double QgsRandomBinomialRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
500{
501 return static_cast<double>( mRandombinomialDistribution( mersenneTwister ) );
502}
503
504//
505// QgsRandomExponentialRasterAlgorithm
506//
507QString QgsRandomExponentialRasterAlgorithm::name() const
508{
509 return QStringLiteral( "createrandomexponentialrasterlayer" );
510}
511
512QString QgsRandomExponentialRasterAlgorithm::displayName() const
513{
514 return QObject::tr( "Create random raster layer (exponential distribution)" );
515}
516
517QStringList QgsRandomExponentialRasterAlgorithm::tags() const
518{
519 return QObject::tr( "raster,create,random,exponential" ).split( ',' );
520}
521
522QString QgsRandomExponentialRasterAlgorithm::shortHelpString() const
523{
524 return QObject::tr( "Generates a raster layer for given extent and cell size "
525 "filled with exponentially distributed random values.\n"
526 "By default, the values will be chosen given a lambda of 1.0. "
527 "This can be overridden by using the advanced parameter for lambda. "
528 "The raster data type is set to Float32 by default as "
529 "the exponential distribution random values are floating point numbers." );
530}
531
532QgsRandomExponentialRasterAlgorithm *QgsRandomExponentialRasterAlgorithm::createInstance() const
533{
534 return new QgsRandomExponentialRasterAlgorithm();
535}
536
537
538void QgsRandomExponentialRasterAlgorithm::addAlgorithmParams()
539{
540 QStringList rasterDataTypes = QStringList();
541 rasterDataTypes << QStringLiteral( "Float32" )
542 << QStringLiteral( "Float64" );
543
544 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
545 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
546 addParameter( rasterTypeParameter.release() );
547
548 auto lambdaParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "LAMBDA" ), QStringLiteral( "Lambda" ), Qgis::ProcessingNumberParameterType::Double, 1.0, true, 0.000001 );
549 lambdaParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
550 addParameter( lambdaParameter.release() );
551}
552
553Qgis::DataType QgsRandomExponentialRasterAlgorithm::getRasterDataType( int typeId )
554{
555 switch ( typeId )
556 {
557 case 0:
559 case 1:
561 default:
563 }
564}
565
566bool QgsRandomExponentialRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
567{
568 const double lambda = parameterAsDouble( parameters, QStringLiteral( "LAMBDA" ), context );
569 mRandomExponentialDistribution = std::exponential_distribution<double>( lambda );
570 return true;
571}
572
573long QgsRandomExponentialRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
574{
575 return static_cast<long>( mRandomExponentialDistribution( mersenneTwister ) );
576}
577
578double QgsRandomExponentialRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
579{
580 return mRandomExponentialDistribution( mersenneTwister );
581}
582
583//
584// QgsRandomGammaRasterAlgorithm
585//
586QString QgsRandomGammaRasterAlgorithm::name() const
587{
588 return QStringLiteral( "createrandomgammarasterlayer" );
589}
590
591QString QgsRandomGammaRasterAlgorithm::displayName() const
592{
593 return QObject::tr( "Create random raster layer (gamma distribution)" );
594}
595
596QStringList QgsRandomGammaRasterAlgorithm::tags() const
597{
598 return QObject::tr( "raster,create,random,gamma" ).split( ',' );
599}
600
601QString QgsRandomGammaRasterAlgorithm::shortHelpString() const
602{
603 return QObject::tr( "Generates a raster layer for given extent and cell size "
604 "filled with gamma distributed random values.\n"
605 "By default, the values will be chosen given an alpha and beta value of 1.0. "
606 "This can be overridden by using the advanced parameter for alpha and beta. "
607 "The raster data type is set to Float32 by default as "
608 "the gamma distribution random values are floating point numbers." );
609}
610
611QgsRandomGammaRasterAlgorithm *QgsRandomGammaRasterAlgorithm::createInstance() const
612{
613 return new QgsRandomGammaRasterAlgorithm();
614}
615
616
617void QgsRandomGammaRasterAlgorithm::addAlgorithmParams()
618{
619 QStringList rasterDataTypes = QStringList();
620 rasterDataTypes << QStringLiteral( "Float32" )
621 << QStringLiteral( "Float64" );
622
623 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
624 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
625 addParameter( rasterTypeParameter.release() );
626
627 auto alphaParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "ALPHA" ), QStringLiteral( "Alpha" ), Qgis::ProcessingNumberParameterType::Double, 1.0, true, 0.000001 );
628 alphaParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
629 addParameter( alphaParameter.release() );
630
631 auto betaParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "BETA" ), QStringLiteral( "Beta" ), Qgis::ProcessingNumberParameterType::Double, 1.0, true, 0.000001 );
632 betaParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
633 addParameter( betaParameter.release() );
634}
635
636Qgis::DataType QgsRandomGammaRasterAlgorithm::getRasterDataType( int typeId )
637{
638 switch ( typeId )
639 {
640 case 0:
642 case 1:
644 default:
646 }
647}
648
649bool QgsRandomGammaRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
650{
651 const double alpha = parameterAsDouble( parameters, QStringLiteral( "ALPHA" ), context );
652 const double beta = parameterAsDouble( parameters, QStringLiteral( "BETA" ), context );
653 mRandomGammaDistribution = std::gamma_distribution<double>( alpha, beta );
654 return true;
655}
656
657long QgsRandomGammaRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
658{
659 return static_cast<long>( mRandomGammaDistribution( mersenneTwister ) );
660}
661
662double QgsRandomGammaRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
663{
664 return mRandomGammaDistribution( mersenneTwister );
665}
666
667//
668// QgsRandomGeometricRasterAlgorithm
669//
670QString QgsRandomGeometricRasterAlgorithm::name() const
671{
672 return QStringLiteral( "createrandomgeometricrasterlayer" );
673}
674
675QString QgsRandomGeometricRasterAlgorithm::displayName() const
676{
677 return QObject::tr( "Create random raster layer (geometric distribution)" );
678}
679
680QStringList QgsRandomGeometricRasterAlgorithm::tags() const
681{
682 return QObject::tr( "raster,create,random,geometric" ).split( ',' );
683}
684
685QString QgsRandomGeometricRasterAlgorithm::shortHelpString() const
686{
687 return QObject::tr( "Generates a raster layer for given extent and cell size "
688 "filled with geometrically distributed random values.\n"
689 "By default, the values will be chosen given a probability of 0.5. "
690 "This can be overridden by using the advanced parameter for mean "
691 "value. The raster data type is set to Integer types (Integer16 by default). "
692 "The geometric distribution random values are defined as positive integer numbers. "
693 "A floating point raster will represent a cast of "
694 "integer values to floating point." );
695}
696
697QgsRandomGeometricRasterAlgorithm *QgsRandomGeometricRasterAlgorithm::createInstance() const
698{
699 return new QgsRandomGeometricRasterAlgorithm();
700}
701
702
703void QgsRandomGeometricRasterAlgorithm::addAlgorithmParams()
704{
705 QStringList rasterDataTypes = QStringList();
706 rasterDataTypes << QStringLiteral( "Integer16" )
707 << QStringLiteral( "Unsigned Integer16" )
708 << QStringLiteral( "Integer32" )
709 << QStringLiteral( "Unsigned Integer32" )
710 << QStringLiteral( "Float32" )
711 << QStringLiteral( "Float64" );
712
713 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
714 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
715 addParameter( rasterTypeParameter.release() );
716
717 auto probabilityParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "PROBABILITY" ), QStringLiteral( "Probability" ), Qgis::ProcessingNumberParameterType::Double, 0.5, true, 0.00001 );
718 probabilityParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
719 addParameter( probabilityParameter.release() );
720}
721
722Qgis::DataType QgsRandomGeometricRasterAlgorithm::getRasterDataType( int typeId )
723{
724 switch ( typeId )
725 {
726 case 0:
728 case 1:
730 case 2:
732 case 3:
734 case 4:
736 case 5:
738 default:
740 }
741}
742
743bool QgsRandomGeometricRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
744{
745 const double probability = parameterAsDouble( parameters, QStringLiteral( "PROBABILITY" ), context );
746 mRandomGeometricDistribution = std::geometric_distribution<long>( probability );
747 return true;
748}
749
750long QgsRandomGeometricRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
751{
752 return mRandomGeometricDistribution( mersenneTwister );
753}
754
755double QgsRandomGeometricRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
756{
757 return static_cast<double>( mRandomGeometricDistribution( mersenneTwister ) );
758}
759
760//
761// QgsRandomNegativeBinomialRasterAlgorithm
762//
763QString QgsRandomNegativeBinomialRasterAlgorithm::name() const
764{
765 return QStringLiteral( "createrandomnegativebinomialrasterlayer" );
766}
767
768QString QgsRandomNegativeBinomialRasterAlgorithm::displayName() const
769{
770 return QObject::tr( "Create random raster layer (negative binomial distribution)" );
771}
772
773QStringList QgsRandomNegativeBinomialRasterAlgorithm::tags() const
774{
775 return QObject::tr( "raster,create,random,negative,binomial,negative-binomial" ).split( ',' );
776}
777
778QString QgsRandomNegativeBinomialRasterAlgorithm::shortHelpString() const
779{
780 return QObject::tr( "Generates a raster layer for given extent and cell size "
781 "filled with negative binomially distributed random values.\n"
782 "By default, the values will be chosen given a distribution parameter k of 10.0 "
783 "and a probability of 0.5. "
784 "This can be overridden by using the advanced parameters for k and probability. "
785 "The raster data type is set to Integer types (Integer 16 by default). "
786 "The negative binomial distribution random values are defined as positive integer numbers. "
787 "A floating point raster will represent a cast of "
788 "integer values to floating point." );
789}
790
791QgsRandomNegativeBinomialRasterAlgorithm *QgsRandomNegativeBinomialRasterAlgorithm::createInstance() const
792{
793 return new QgsRandomNegativeBinomialRasterAlgorithm();
794}
795
796
797void QgsRandomNegativeBinomialRasterAlgorithm::addAlgorithmParams()
798{
799 QStringList rasterDataTypes = QStringList();
800 rasterDataTypes << QStringLiteral( "Integer16" )
801 << QStringLiteral( "Unsigned Integer16" )
802 << QStringLiteral( "Integer32" )
803 << QStringLiteral( "Unsigned Integer32" )
804 << QStringLiteral( "Float32" )
805 << QStringLiteral( "Float64" );
806
807 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
808 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
809 addParameter( rasterTypeParameter.release() );
810
811 auto kParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "K_PARAMETER" ), QStringLiteral( "Distribution parameter k" ), Qgis::ProcessingNumberParameterType::Integer, 10, true, 0.00001 );
812 kParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
813 addParameter( kParameter.release() );
814
815 auto probabilityParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "PROBABILITY" ), QStringLiteral( "Probability" ), Qgis::ProcessingNumberParameterType::Double, 0.5, true, 0.00001 );
816 probabilityParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
817 addParameter( probabilityParameter.release() );
818}
819
820Qgis::DataType QgsRandomNegativeBinomialRasterAlgorithm::getRasterDataType( int typeId )
821{
822 switch ( typeId )
823 {
824 case 0:
826 case 1:
828 case 2:
830 case 3:
832 case 4:
834 case 5:
836 default:
838 }
839}
840
841bool QgsRandomNegativeBinomialRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
842{
843 const int k = parameterAsInt( parameters, QStringLiteral( "K_PARAMETER" ), context );
844 const double probability = parameterAsDouble( parameters, QStringLiteral( "PROBABILITY" ), context );
845 mRandomNegativeBinomialDistribution = std::negative_binomial_distribution<long>( k, probability );
846 return true;
847}
848
849long QgsRandomNegativeBinomialRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
850{
851 return mRandomNegativeBinomialDistribution( mersenneTwister );
852}
853
854double QgsRandomNegativeBinomialRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
855{
856 return static_cast<double>( mRandomNegativeBinomialDistribution( mersenneTwister ) );
857}
858
859//
860// QgsRandomNormalRasterAlgorithm
861//
862QString QgsRandomNormalRasterAlgorithm::name() const
863{
864 return QStringLiteral( "createrandomnormalrasterlayer" );
865}
866
867QString QgsRandomNormalRasterAlgorithm::displayName() const
868{
869 return QObject::tr( "Create random raster layer (normal distribution)" );
870}
871
872QStringList QgsRandomNormalRasterAlgorithm::tags() const
873{
874 return QObject::tr( "raster,create,normal,distribution,random" ).split( ',' );
875}
876
877QString QgsRandomNormalRasterAlgorithm::shortHelpString() const
878{
879 return QObject::tr( "Generates a raster layer for given extent and cell size "
880 "filled with normally distributed random values.\n"
881 "By default, the values will be chosen given a mean of 0.0 and "
882 "a standard deviation of 1.0. This can be overridden by "
883 "using the advanced parameters for mean and standard deviation "
884 "value. The raster data type is set to Float32 by default "
885 "as the normal distribution random values are floating point numbers." );
886}
887
888QgsRandomNormalRasterAlgorithm *QgsRandomNormalRasterAlgorithm::createInstance() const
889{
890 return new QgsRandomNormalRasterAlgorithm();
891}
892
893void QgsRandomNormalRasterAlgorithm::addAlgorithmParams()
894{
895 QStringList rasterDataTypes = QStringList();
896 rasterDataTypes << QStringLiteral( "Float32" )
897 << QStringLiteral( "Float64" );
898
899 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
900 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
901 addParameter( rasterTypeParameter.release() );
902
903 auto meanParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "MEAN" ), QStringLiteral( "Mean of normal distribution" ), Qgis::ProcessingNumberParameterType::Double, 0, true );
904 meanParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
905 addParameter( meanParameter.release() );
906
907 auto stdevParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "STDDEV" ), QStringLiteral( "Standard deviation of normal distribution" ), Qgis::ProcessingNumberParameterType::Double, 1, true, 0 );
908 stdevParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
909 addParameter( stdevParameter.release() );
910}
911
912Qgis::DataType QgsRandomNormalRasterAlgorithm::getRasterDataType( int typeId )
913{
914 switch ( typeId )
915 {
916 case 0:
918 case 1:
920 default:
922 }
923}
924
925bool QgsRandomNormalRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
926{
927 const double mean = parameterAsDouble( parameters, QStringLiteral( "MEAN" ), context );
928 const double stddev = parameterAsDouble( parameters, QStringLiteral( "STDDEV" ), context );
929 mRandomNormalDistribution = std::normal_distribution<double>( mean, stddev );
930 return true;
931}
932
933long QgsRandomNormalRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
934{
935 return static_cast<long>( mRandomNormalDistribution( mersenneTwister ) );
936}
937
938double QgsRandomNormalRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
939{
940 return mRandomNormalDistribution( mersenneTwister );
941}
942
943//
944// QgsRandomPoissonRasterAlgorithm
945//
946QString QgsRandomPoissonRasterAlgorithm::name() const
947{
948 return QStringLiteral( "createrandompoissonrasterlayer" );
949}
950
951QString QgsRandomPoissonRasterAlgorithm::displayName() const
952{
953 return QObject::tr( "Create random raster layer (poisson distribution)" );
954}
955
956QStringList QgsRandomPoissonRasterAlgorithm::tags() const
957{
958 return QObject::tr( "raster,create,random,poisson" ).split( ',' );
959}
960
961QString QgsRandomPoissonRasterAlgorithm::shortHelpString() const
962{
963 return QObject::tr( "Generates a raster layer for given extent and cell size "
964 "filled with poisson distributed random values.\n"
965 "By default, the values will be chosen given a mean of 1.0. "
966 "This can be overridden by using the advanced parameter for mean "
967 "value. The raster data type is set to Integer types (Integer16 by default). "
968 "The poisson distribution random values are positive integer numbers. "
969 "A floating point raster will represent a cast of integer values to floating point." );
970}
971
972QgsRandomPoissonRasterAlgorithm *QgsRandomPoissonRasterAlgorithm::createInstance() const
973{
974 return new QgsRandomPoissonRasterAlgorithm();
975}
976
977
978void QgsRandomPoissonRasterAlgorithm::addAlgorithmParams()
979{
980 QStringList rasterDataTypes = QStringList();
981 rasterDataTypes << QStringLiteral( "Integer16" )
982 << QStringLiteral( "Unsigned Integer16" )
983 << QStringLiteral( "Integer32" )
984 << QStringLiteral( "Unsigned Integer32" )
985 << QStringLiteral( "Float32" )
986 << QStringLiteral( "Float64" );
987
988 std::unique_ptr<QgsProcessingParameterDefinition> rasterTypeParameter = std::make_unique<QgsProcessingParameterEnum>( QStringLiteral( "OUTPUT_TYPE" ), QObject::tr( "Output raster data type" ), rasterDataTypes, false, 0, false );
989 rasterTypeParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
990 addParameter( rasterTypeParameter.release() );
991
992 auto upperBoundParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "MEAN" ), QStringLiteral( "Mean" ), Qgis::ProcessingNumberParameterType::Double, 1.0, true, 0 );
993 upperBoundParameter->setFlags( Qgis::ProcessingParameterFlag::Advanced );
994 addParameter( upperBoundParameter.release() );
995}
996
997Qgis::DataType QgsRandomPoissonRasterAlgorithm::getRasterDataType( int typeId )
998{
999 switch ( typeId )
1000 {
1001 case 0:
1002 return Qgis::DataType::Int16;
1003 case 1:
1005 case 2:
1006 return Qgis::DataType::Int32;
1007 case 3:
1009 case 4:
1011 case 5:
1013 default:
1015 }
1016}
1017
1018bool QgsRandomPoissonRasterAlgorithm::prepareRandomParameters( const QVariantMap &parameters, QgsProcessingContext &context )
1019{
1020 const double mean = parameterAsDouble( parameters, QStringLiteral( "MEAN" ), context );
1021 mRandomPoissonDistribution = std::poisson_distribution<long>( mean );
1022 return true;
1023}
1024
1025long QgsRandomPoissonRasterAlgorithm::generateRandomLongValue( std::mt19937 &mersenneTwister )
1026{
1027 return mRandomPoissonDistribution( mersenneTwister );
1028}
1029
1030double QgsRandomPoissonRasterAlgorithm::generateRandomDoubleValue( std::mt19937 &mersenneTwister )
1031{
1032 return static_cast<double>( mRandomPoissonDistribution( mersenneTwister ) );
1033}
1034
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:6125