23 QString QgsRoundRasterValuesAlgorithm::name()
const
25 return QStringLiteral(
"roundrastervalues" );
28 QString QgsRoundRasterValuesAlgorithm::displayName()
const
30 return QObject::tr(
"Round raster" );
33 QStringList QgsRoundRasterValuesAlgorithm::tags()
const
35 return QObject::tr(
"data,cells,round,truncate" ).split(
',' );
38 QString QgsRoundRasterValuesAlgorithm::group()
const
40 return QObject::tr(
"Raster analysis" );
43 QString QgsRoundRasterValuesAlgorithm::groupId()
const
45 return QStringLiteral(
"rasteranalysis" );
48 void 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 ) );
55 std::unique_ptr< QgsProcessingParameterDefinition > baseParameter = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral(
"BASE_N" ), QObject::tr(
"Base n for rounding to multiples of n" ),
QgsProcessingParameterNumber::Integer, 10,
true, 1 );
57 addParameter( baseParameter.release() );
60 QString QgsRoundRasterValuesAlgorithm::shortHelpString()
const
62 return QObject::tr(
"This algorithm rounds the cell values of a raster dataset according to the specified number of decimals.\n "
63 "Alternatively, a negative number of decimal places may be used to round values to powers of a base n "
64 "(specified in the advanced parameter Base n). For example, with a Base value n of 10 and Decimal places of -1 "
65 "the algorithm rounds cell values to multiples of 10, -2 rounds to multiples of 100, and so on. Arbitrary base values "
66 "may be chosen, the algorithm applies the same multiplicative principle. Rounding cell values to multiples of "
67 "a base n may be used to generalize raster layers.\n"
68 "The algorithm preserves the data type of the input raster. Therefore byte/integer rasters can only be rounded "
69 "to multiples of a base n, otherwise a warning is raised and the raster gets copied as byte/integer raster" );
72 QgsRoundRasterValuesAlgorithm *QgsRoundRasterValuesAlgorithm::createInstance()
const
74 return new QgsRoundRasterValuesAlgorithm();
80 QgsRasterLayer *inputRaster = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT" ), context );
81 mDecimalPrecision = parameterAsInt( parameters, QStringLiteral(
"DECIMAL_PLACES" ), context );
82 mBaseN = parameterAsInt( parameters, QStringLiteral(
"BASE_N" ), context );
83 mMultipleOfBaseN = pow( mBaseN, abs( mDecimalPrecision ) );
84 mScaleFactor = std::pow( 10.0, mDecimalPrecision );
89 mBand = parameterAsInt( parameters, QStringLiteral(
"BAND" ), context );
90 if ( mBand < 1 || mBand > inputRaster->
bandCount() )
91 throw QgsProcessingException( QObject::tr(
"Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand ).arg( inputRaster->
bandCount() ) );
93 mRoundingDirection = parameterAsEnum( parameters, QStringLiteral(
"ROUNDING_DIRECTION" ), context );
96 mDataType = mInterface->dataType( mBand );
106 if ( mDecimalPrecision > -1 )
107 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 );
115 mExtent = inputRaster->
extent();
116 mLayerWidth = inputRaster->
width();
117 mLayerHeight = inputRaster->
height();
118 mCrs = inputRaster->
crs();
119 mNbCellsXProvider = mInterface->xSize();
120 mNbCellsYProvider = mInterface->ySize();
127 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
128 const QFileInfo fi( outputFile );
130 std::unique_ptr< QgsRasterFileWriter > writer = std::make_unique< QgsRasterFileWriter >( outputFile );
131 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
132 writer->setOutputFormat( outputFormat );
133 std::unique_ptr<QgsRasterDataProvider > provider( writer->createOneBandRaster( mInterface->dataType( mBand ), mNbCellsXProvider, mNbCellsYProvider, mExtent, mCrs ) );
136 if ( !provider->isValid() )
141 destinationRasterProvider = provider.get();
143 destinationRasterProvider->
setNoDataValue( 1, mInputNoDataValue );
147 const int nbBlocksWidth =
static_cast< int >( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
148 const int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
149 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
152 iter.startRasterRead( mBand, mLayerWidth, mLayerHeight, mExtent );
157 std::unique_ptr< QgsRasterBlock > analysisRasterBlock;
158 while ( iter.readNextRasterPart( mBand, iterCols, iterRows, analysisRasterBlock, iterLeft, iterTop ) )
161 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
162 if ( mIsInteger && mDecimalPrecision > -1 )
165 analysisRasterBlock->setNoDataValue( mInputNoDataValue );
166 destinationRasterProvider->
writeBlock( analysisRasterBlock.get(), mBand, iterLeft, iterTop );
170 for (
int row = 0; row < iterRows; row++ )
174 for (
int column = 0; column < iterCols; column++ )
176 bool isNoData =
false;
177 const double val = analysisRasterBlock->valueAndNoData( row, column, isNoData );
180 analysisRasterBlock->setValue( row, column, mInputNoDataValue );
184 double roundedVal = mInputNoDataValue;
185 if ( mRoundingDirection == 0 && mDecimalPrecision < 0 )
187 roundedVal = roundUpBaseN( val );
189 else if ( mRoundingDirection == 0 && mDecimalPrecision > -1 )
191 const double m = ( val < 0.0 ) ? -1.0 : 1.0;
192 roundedVal = roundUp( val, m );
194 else if ( mRoundingDirection == 1 && mDecimalPrecision < 0 )
196 roundedVal = roundNearestBaseN( val );
198 else if ( mRoundingDirection == 1 && mDecimalPrecision > -1 )
200 const double m = ( val < 0.0 ) ? -1.0 : 1.0;
201 roundedVal = roundNearest( val, m );
203 else if ( mRoundingDirection == 2 && mDecimalPrecision < 0 )
205 roundedVal = roundDownBaseN( val );
209 const double m = ( val < 0.0 ) ? -1.0 : 1.0;
210 roundedVal = roundDown( val, m );
213 analysisRasterBlock->setValue( row, column, roundedVal );
217 destinationRasterProvider->
writeBlock( analysisRasterBlock.get(), mBand, iterLeft, iterTop );
223 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
227 double QgsRoundRasterValuesAlgorithm::roundNearest(
double value,
double m )
229 return ( std::round( value * m * mScaleFactor ) / mScaleFactor ) * m;
232 double QgsRoundRasterValuesAlgorithm::roundUp(
double value,
double m )
234 return ( std::ceil( value * m * mScaleFactor ) / mScaleFactor ) * m;
237 double QgsRoundRasterValuesAlgorithm::roundDown(
double value,
double m )
239 return ( std::floor( value * m * mScaleFactor ) / mScaleFactor ) * m;
243 double QgsRoundRasterValuesAlgorithm::roundNearestBaseN(
double value )
245 return static_cast<double>( mMultipleOfBaseN * round( value / mMultipleOfBaseN ) );
248 double QgsRoundRasterValuesAlgorithm::roundUpBaseN(
double value )
250 return static_cast<double>( mMultipleOfBaseN * ceil( value / mMultipleOfBaseN ) );
253 double QgsRoundRasterValuesAlgorithm::roundDownBaseN(
double value )
255 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)
bool isCanceled() const SIP_HOLDGIL
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.
@ FlagAdvanced
Parameter is an advanced parameter which should be hidden from users by default.
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.
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.
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
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.