24QString QgsRoundRasterValuesAlgorithm::name()
const
26 return QStringLiteral(
"roundrastervalues" );
29QString QgsRoundRasterValuesAlgorithm::displayName()
const
31 return QObject::tr(
"Round raster" );
34QStringList QgsRoundRasterValuesAlgorithm::tags()
const
36 return QObject::tr(
"data,cells,round,truncate" ).split(
',' );
39QString QgsRoundRasterValuesAlgorithm::group()
const
41 return QObject::tr(
"Raster analysis" );
44QString QgsRoundRasterValuesAlgorithm::groupId()
const
46 return QStringLiteral(
"rasteranalysis" );
49void QgsRoundRasterValuesAlgorithm::initAlgorithm(
const QVariantMap & )
52 addParameter(
new QgsProcessingParameterBand( QStringLiteral(
"BAND" ), QObject::tr(
"Band number" ), 1, QStringLiteral(
"INPUT" ) ) );
53 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" ),
Qgis::ProcessingNumberParameterType::Integer, 10,
true, 1 );
57 addParameter( baseParameter.release() );
61 auto createOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATE_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
62 createOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
64 addParameter( createOptsParam.release() );
66 auto creationOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATION_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
67 creationOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
69 addParameter( creationOptsParam.release() );
74QString QgsRoundRasterValuesAlgorithm::shortHelpString()
const
76 return QObject::tr(
"This algorithm rounds the cell values of a raster dataset to the specified number of decimals.\n "
77 "Alternatively, a negative number of decimal places may be used to round values to powers of a base n "
78 "(specified in the advanced parameter Base n). For example, with a Base value n of 10 and Decimal places of -1 "
79 "the algorithm rounds cell values to multiples of 10, -2 rounds to multiples of 100, and so on. Arbitrary base values "
80 "may be chosen, the algorithm applies the same multiplicative principle. Rounding cell values to multiples of "
81 "a base n may be used to generalize raster layers.\n"
82 "The algorithm preserves the data type of the input raster. Therefore byte/integer rasters can only be rounded "
83 "to multiples of a base n, otherwise a warning is raised and the raster gets copied as byte/integer raster." );
86QString QgsRoundRasterValuesAlgorithm::shortDescription()
const
88 return QObject::tr(
"Rounds the cell values of a raster dataset to a specified number of decimals." );
91QgsRoundRasterValuesAlgorithm *QgsRoundRasterValuesAlgorithm::createInstance()
const
93 return new QgsRoundRasterValuesAlgorithm();
99 QgsRasterLayer *inputRaster = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT" ), context );
100 mDecimalPrecision = parameterAsInt( parameters, QStringLiteral(
"DECIMAL_PLACES" ), context );
101 mBaseN = parameterAsInt( parameters, QStringLiteral(
"BASE_N" ), context );
102 mMultipleOfBaseN = pow( mBaseN, abs( mDecimalPrecision ) );
103 mScaleFactor = std::pow( 10.0, mDecimalPrecision );
108 mBand = parameterAsInt( parameters, QStringLiteral(
"BAND" ), context );
109 if ( mBand < 1 || mBand > inputRaster->
bandCount() )
110 throw QgsProcessingException( QObject::tr(
"Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand ).arg( inputRaster->
bandCount() ) );
112 mRoundingDirection = parameterAsEnum( parameters, QStringLiteral(
"ROUNDING_DIRECTION" ), context );
115 mDataType = mInterface->dataType( mBand );
125 if ( mDecimalPrecision > -1 )
126 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 );
134 mExtent = inputRaster->
extent();
135 mLayerWidth = inputRaster->
width();
136 mLayerHeight = inputRaster->
height();
137 mCrs = inputRaster->
crs();
138 mNbCellsXProvider = mInterface->xSize();
139 mNbCellsYProvider = mInterface->ySize();
146 QString creationOptions = parameterAsString( parameters, QStringLiteral(
"CREATION_OPTIONS" ), context ).trimmed();
148 const QString optionsString = parameterAsString( parameters, QStringLiteral(
"CREATE_OPTIONS" ), context );
149 if ( !optionsString.isEmpty() )
150 creationOptions = optionsString;
152 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
153 const QFileInfo fi( outputFile );
155 auto writer = std::make_unique<QgsRasterFileWriter>( outputFile );
156 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
157 if ( !creationOptions.isEmpty() )
159 writer->setCreationOptions( creationOptions.split(
'|' ) );
161 writer->setOutputFormat( outputFormat );
162 std::unique_ptr<QgsRasterDataProvider> provider( writer->createOneBandRaster( mInterface->dataType( mBand ), mNbCellsXProvider, mNbCellsYProvider, mExtent, mCrs ) );
165 if ( !provider->isValid() )
170 destinationRasterProvider = provider.get();
172 destinationRasterProvider->
setNoDataValue( 1, mInputNoDataValue );
176 const int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
177 const int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
178 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
181 iter.startRasterRead( mBand, mLayerWidth, mLayerHeight, mExtent );
186 std::unique_ptr<QgsRasterBlock> analysisRasterBlock;
187 while ( iter.readNextRasterPart( mBand, iterCols, iterRows, analysisRasterBlock, iterLeft, iterTop ) )
190 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
191 if ( mIsInteger && mDecimalPrecision > -1 )
194 analysisRasterBlock->setNoDataValue( mInputNoDataValue );
195 if ( !destinationRasterProvider->
writeBlock( analysisRasterBlock.get(), mBand, iterLeft, iterTop ) )
202 for (
int row = 0; row < iterRows; row++ )
206 for (
int column = 0; column < iterCols; column++ )
208 bool isNoData =
false;
209 const double val = analysisRasterBlock->valueAndNoData( row, column, isNoData );
212 analysisRasterBlock->setValue( row, column, mInputNoDataValue );
216 double roundedVal = mInputNoDataValue;
217 if ( mRoundingDirection == 0 && mDecimalPrecision < 0 )
219 roundedVal = roundUpBaseN( val );
221 else if ( mRoundingDirection == 0 && mDecimalPrecision > -1 )
223 const double m = ( val < 0.0 ) ? -1.0 : 1.0;
224 roundedVal = roundUp( val, m );
226 else if ( mRoundingDirection == 1 && mDecimalPrecision < 0 )
228 roundedVal = roundNearestBaseN( val );
230 else if ( mRoundingDirection == 1 && mDecimalPrecision > -1 )
232 const double m = ( val < 0.0 ) ? -1.0 : 1.0;
233 roundedVal = roundNearest( val, m );
235 else if ( mRoundingDirection == 2 && mDecimalPrecision < 0 )
237 roundedVal = roundDownBaseN( val );
241 const double m = ( val < 0.0 ) ? -1.0 : 1.0;
242 roundedVal = roundDown( val, m );
245 analysisRasterBlock->setValue( row, column, roundedVal );
249 if ( !destinationRasterProvider->
writeBlock( analysisRasterBlock.get(), mBand, iterLeft, iterTop ) )
258 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
262double QgsRoundRasterValuesAlgorithm::roundNearest(
double value,
double m )
264 return ( std::round( value * m * mScaleFactor ) / mScaleFactor ) * m;
267double QgsRoundRasterValuesAlgorithm::roundUp(
double value,
double m )
269 return ( std::ceil( value * m * mScaleFactor ) / mScaleFactor ) * m;
272double QgsRoundRasterValuesAlgorithm::roundDown(
double value,
double m )
274 return ( std::floor( value * m * mScaleFactor ) / mScaleFactor ) * m;
277double QgsRoundRasterValuesAlgorithm::roundNearestBaseN(
double value )
279 return static_cast<double>( mMultipleOfBaseN * round( value / mMultipleOfBaseN ) );
282double QgsRoundRasterValuesAlgorithm::roundUpBaseN(
double value )
284 return static_cast<double>( mMultipleOfBaseN * ceil( value / mMultipleOfBaseN ) );
287double QgsRoundRasterValuesAlgorithm::roundDownBaseN(
double value )
289 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).
@ Hidden
Parameter is hidden and should not be shown to users.
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
virtual QgsError error() const
Gets current status error.
QString summary() const
Short error description, usually the first error in chain, the real error.
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.