23QString QgsRoundRasterValuesAlgorithm::name()
const
25 return QStringLiteral(
"roundrastervalues" );
28QString QgsRoundRasterValuesAlgorithm::displayName()
const
30 return QObject::tr(
"Round raster" );
33QStringList QgsRoundRasterValuesAlgorithm::tags()
const
35 return QObject::tr(
"data,cells,round,truncate" ).split(
',' );
38QString QgsRoundRasterValuesAlgorithm::group()
const
40 return QObject::tr(
"Raster analysis" );
43QString QgsRoundRasterValuesAlgorithm::groupId()
const
45 return QStringLiteral(
"rasteranalysis" );
48void QgsRoundRasterValuesAlgorithm::initAlgorithm(
const QVariantMap & )
51 addParameter(
new QgsProcessingParameterBand( QStringLiteral(
"BAND" ), QObject::tr(
"Band number" ), 1, QStringLiteral(
"INPUT" ) ) );
52 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"ROUNDING_DIRECTION" ), QObject::tr(
"Rounding direction" ), QStringList() << QObject::tr(
"Round up" ) << QObject::tr(
"Round to nearest" ) << QObject::tr(
"Round down" ),
false, 1 ) );
54 std::unique_ptr<QgsProcessingParameterDefinition> baseParameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral(
"BASE_N" ), QObject::tr(
"Base n for rounding to multiples of n" ),
Qgis::ProcessingNumberParameterType::Integer, 10,
true, 1 );
56 addParameter( baseParameter.release() );
57 std::unique_ptr<QgsProcessingParameterString> createOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATE_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
58 createOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
60 addParameter( createOptsParam.release() );
65QString QgsRoundRasterValuesAlgorithm::shortHelpString()
const
67 return QObject::tr(
"This algorithm rounds the cell values of a raster dataset according to the specified number of decimals.\n "
68 "Alternatively, a negative number of decimal places may be used to round values to powers of a base n "
69 "(specified in the advanced parameter Base n). For example, with a Base value n of 10 and Decimal places of -1 "
70 "the algorithm rounds cell values to multiples of 10, -2 rounds to multiples of 100, and so on. Arbitrary base values "
71 "may be chosen, the algorithm applies the same multiplicative principle. Rounding cell values to multiples of "
72 "a base n may be used to generalize raster layers.\n"
73 "The algorithm preserves the data type of the input raster. Therefore byte/integer rasters can only be rounded "
74 "to multiples of a base n, otherwise a warning is raised and the raster gets copied as byte/integer raster" );
77QgsRoundRasterValuesAlgorithm *QgsRoundRasterValuesAlgorithm::createInstance()
const
79 return new QgsRoundRasterValuesAlgorithm();
85 QgsRasterLayer *inputRaster = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT" ), context );
86 mDecimalPrecision = parameterAsInt( parameters, QStringLiteral(
"DECIMAL_PLACES" ), context );
87 mBaseN = parameterAsInt( parameters, QStringLiteral(
"BASE_N" ), context );
88 mMultipleOfBaseN = pow( mBaseN, abs( mDecimalPrecision ) );
89 mScaleFactor = std::pow( 10.0, mDecimalPrecision );
94 mBand = parameterAsInt( parameters, QStringLiteral(
"BAND" ), context );
95 if ( mBand < 1 || mBand > inputRaster->
bandCount() )
96 throw QgsProcessingException( QObject::tr(
"Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand ).arg( inputRaster->
bandCount() ) );
98 mRoundingDirection = parameterAsEnum( parameters, QStringLiteral(
"ROUNDING_DIRECTION" ), context );
101 mDataType = mInterface->dataType( mBand );
111 if ( mDecimalPrecision > -1 )
112 feedback->
reportError( QObject::tr(
"Input raster is of byte or integer type. The cell values cannot be rounded and will be output using the same data type." ),
false );
120 mExtent = inputRaster->
extent();
121 mLayerWidth = inputRaster->
width();
122 mLayerHeight = inputRaster->
height();
123 mCrs = inputRaster->
crs();
124 mNbCellsXProvider = mInterface->xSize();
125 mNbCellsYProvider = mInterface->ySize();
132 const QString createOptions = parameterAsString( parameters, QStringLiteral(
"CREATE_OPTIONS" ), context ).trimmed();
133 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
134 const QFileInfo fi( outputFile );
136 std::unique_ptr<QgsRasterFileWriter> writer = std::make_unique<QgsRasterFileWriter>( outputFile );
137 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
138 if ( !createOptions.isEmpty() )
140 writer->setCreateOptions( createOptions.split(
'|' ) );
142 writer->setOutputFormat( outputFormat );
143 std::unique_ptr<QgsRasterDataProvider> provider( writer->createOneBandRaster( mInterface->dataType( mBand ), mNbCellsXProvider, mNbCellsYProvider, mExtent, mCrs ) );
146 if ( !provider->isValid() )
151 destinationRasterProvider = provider.get();
153 destinationRasterProvider->
setNoDataValue( 1, mInputNoDataValue );
157 const int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
158 const int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
159 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
162 iter.startRasterRead( mBand, mLayerWidth, mLayerHeight, mExtent );
167 std::unique_ptr<QgsRasterBlock> analysisRasterBlock;
168 while ( iter.readNextRasterPart( mBand, iterCols, iterRows, analysisRasterBlock, iterLeft, iterTop ) )
171 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
172 if ( mIsInteger && mDecimalPrecision > -1 )
175 analysisRasterBlock->setNoDataValue( mInputNoDataValue );
176 destinationRasterProvider->
writeBlock( analysisRasterBlock.get(), mBand, iterLeft, iterTop );
180 for (
int row = 0; row < iterRows; row++ )
184 for (
int column = 0; column < iterCols; column++ )
186 bool isNoData =
false;
187 const double val = analysisRasterBlock->valueAndNoData( row, column, isNoData );
190 analysisRasterBlock->setValue( row, column, mInputNoDataValue );
194 double roundedVal = mInputNoDataValue;
195 if ( mRoundingDirection == 0 && mDecimalPrecision < 0 )
197 roundedVal = roundUpBaseN( val );
199 else if ( mRoundingDirection == 0 && mDecimalPrecision > -1 )
201 const double m = ( val < 0.0 ) ? -1.0 : 1.0;
202 roundedVal = roundUp( val, m );
204 else if ( mRoundingDirection == 1 && mDecimalPrecision < 0 )
206 roundedVal = roundNearestBaseN( val );
208 else if ( mRoundingDirection == 1 && mDecimalPrecision > -1 )
210 const double m = ( val < 0.0 ) ? -1.0 : 1.0;
211 roundedVal = roundNearest( val, m );
213 else if ( mRoundingDirection == 2 && mDecimalPrecision < 0 )
215 roundedVal = roundDownBaseN( val );
219 const double m = ( val < 0.0 ) ? -1.0 : 1.0;
220 roundedVal = roundDown( val, m );
223 analysisRasterBlock->setValue( row, column, roundedVal );
227 destinationRasterProvider->
writeBlock( analysisRasterBlock.get(), mBand, iterLeft, iterTop );
233 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
237double QgsRoundRasterValuesAlgorithm::roundNearest(
double value,
double m )
239 return ( std::round( value * m * mScaleFactor ) / mScaleFactor ) * m;
242double QgsRoundRasterValuesAlgorithm::roundUp(
double value,
double m )
244 return ( std::ceil( value * m * mScaleFactor ) / mScaleFactor ) * m;
247double QgsRoundRasterValuesAlgorithm::roundDown(
double value,
double m )
249 return ( std::floor( value * m * mScaleFactor ) / mScaleFactor ) * m;
252double QgsRoundRasterValuesAlgorithm::roundNearestBaseN(
double value )
254 return static_cast<double>( mMultipleOfBaseN * round( value / mMultipleOfBaseN ) );
257double QgsRoundRasterValuesAlgorithm::roundUpBaseN(
double value )
259 return static_cast<double>( mMultipleOfBaseN * ceil( value / mMultipleOfBaseN ) );
262double QgsRoundRasterValuesAlgorithm::roundDownBaseN(
double value )
264 return static_cast<double>( mMultipleOfBaseN * floor( value / mMultipleOfBaseN ) );
@ Int16
Sixteen bit signed integer (qint16)
@ UInt16
Sixteen bit unsigned integer (quint16)
@ Byte
Eight bit unsigned integer (quint8)
@ Int32
Thirty two bit signed integer (qint32)
@ 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.
void setProgress(double progress)
Sets the current progress for the feedback object.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
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.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A raster band parameter for Processing algorithms.
An enum based parameter for processing algorithms, allowing for selection from predefined values.
A numeric parameter for processing algorithms.
A raster layer destination parameter, for specifying the destination path for a raster layer created ...
A raster layer parameter for processing algorithms.
Base class for raster data providers.
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
virtual bool setNoDataValue(int bandNo, double noDataValue)
Set no data value on created dataset.
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
bool writeBlock(QgsRasterBlock *block, int band, int xOffset=0, int yOffset=0)
Writes pixel data from a raster block into the provider data source.
virtual bool setEditable(bool enabled)
Turns on/off editing mode of the provider.
static QString driverForExtension(const QString &extension)
Returns the GDAL driver name for a specified file extension.
Iterator for sequentially processing raster cells.
static const int DEFAULT_MAXIMUM_TILE_WIDTH
Default maximum tile width.
static const int DEFAULT_MAXIMUM_TILE_HEIGHT
Default maximum tile height.
Represents a raster layer.
int height() const
Returns the height of the (unclipped) raster.
int bandCount() const
Returns the number of bands in this layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
int width() const
Returns the width of the (unclipped) raster.