29QString QgsRasterStackPositionAlgorithmBase::group()
const
31 return QObject::tr(
"Raster analysis" );
34QString QgsRasterStackPositionAlgorithmBase::groupId()
const
36 return QStringLiteral(
"rasteranalysis" );
39void QgsRasterStackPositionAlgorithmBase::initAlgorithm(
const QVariantMap & )
47 auto output_nodata_parameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral(
"OUTPUT_NODATA_VALUE" ), QObject::tr(
"Output NoData value" ),
Qgis::ProcessingNumberParameterType::Double, -9999,
true );
49 addParameter( output_nodata_parameter.release() );
53 auto createOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATE_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
54 createOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
56 addParameter( createOptsParam.release() );
58 auto creationOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATION_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
59 creationOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
61 addParameter( creationOptsParam.release() );
73 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, QStringLiteral(
"REFERENCE_LAYER" ), context );
74 if ( !referenceLayer )
77 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
78 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
80 mCrs = referenceLayer->
crs();
83 mLayerWidth = referenceLayer->
width();
84 mLayerHeight = referenceLayer->
height();
85 mExtent = referenceLayer->
extent();
87 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT_RASTERS" ), context );
88 QList<QgsRasterLayer *> rasterLayers;
89 rasterLayers.reserve( layers.count() );
98 QgsRasterAnalysisUtils::RasterLogicInput input;
102 input.interface = input.sourceDataProvider.get();
104 if ( layer->
crs() != mCrs )
106 input.projector = std::make_unique<QgsRasterProjector>();
107 input.projector->setInput( input.sourceDataProvider.get() );
109 input.interface = input.projector.get();
111 mInputs.emplace_back( std::move( input ) );
120 QString creationOptions = parameterAsString( parameters, QStringLiteral(
"CREATION_OPTIONS" ), context ).trimmed();
122 const QString optionsString = parameterAsString( parameters, QStringLiteral(
"CREATE_OPTIONS" ), context );
123 if ( !optionsString.isEmpty() )
124 creationOptions = optionsString;
126 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
127 const QFileInfo fi( outputFile );
130 auto writer = std::make_unique<QgsRasterFileWriter>( outputFile );
131 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
132 if ( !creationOptions.isEmpty() )
134 writer->setCreationOptions( creationOptions.split(
'|' ) );
136 writer->setOutputFormat( outputFormat );
137 std::unique_ptr<QgsRasterDataProvider> provider( writer->createOneBandRaster(
Qgis::DataType::Int32, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
140 if ( !provider->isValid() )
143 provider->setNoDataValue( 1, mNoDataValue );
144 const qgssize layerSize =
static_cast<qgssize>( mLayerWidth ) *
static_cast<qgssize>( mLayerHeight );
148 const int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
149 const int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
150 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
151 provider->setEditable(
true );
154 iter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
161 std::unique_ptr<QgsRasterBlock> outputBlock;
162 while ( iter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
164 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
165 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : mInputs )
169 for (
const int band : i.bands )
173 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
174 inputBlocks.emplace_back( std::move( b ) );
178 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
179 for (
int row = 0; row < iterRows; row++ )
184 for (
int col = 0; col < iterCols; col++ )
186 bool noDataInStack =
false;
188 if ( !inputBlocks.empty() )
190 const int position = findPosition( inputBlocks, row, col, noDataInStack );
192 if ( position == -1 || ( noDataInStack && !mIgnoreNoData ) )
197 outputBlock->setValue( row, col, mNoDataValue );
201 outputBlock->setValue( row, col, position );
206 outputBlock->setValue( row, col, mNoDataValue );
210 if ( !provider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
212 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( provider->error().summary() ) );
215 provider->setEditable(
false );
218 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
219 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
220 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
221 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
222 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
223 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
231QString QgsRasterStackLowestPositionAlgorithm::displayName()
const
233 return QObject::tr(
"Lowest position in raster stack" );
236QString QgsRasterStackLowestPositionAlgorithm::name()
const
238 return QStringLiteral(
"lowestpositioninrasterstack" );
241QStringList QgsRasterStackLowestPositionAlgorithm::tags()
const
243 return QObject::tr(
"cell,lowest,position,pixel,stack" ).split(
',' );
246QString QgsRasterStackLowestPositionAlgorithm::shortDescription()
const
248 return QObject::tr(
"Evaluates on a cell-by-cell basis the position "
249 "of the raster with the lowest value in a stack of rasters." );
252QString QgsRasterStackLowestPositionAlgorithm::shortHelpString()
const
254 return QObject::tr(
"This algorithm evaluates on a cell-by-cell basis the position "
255 "of the raster with the lowest value in a stack of rasters. Position counts start "
256 "with 1 and range to the total number of input rasters. The order of the input "
257 "rasters is relevant for the algorithm. If multiple rasters feature the lowest value, "
258 "the first raster will be used for the position value.\n "
259 "If multiband rasters are used in the data raster stack, the algorithm will always "
260 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
261 "Any NoData cells in the raster layer stack will result in a NoData cell "
262 "in the output raster unless the \"ignore NoData\" parameter is checked. "
263 "The output NoData value can be set manually. The output rasters extent and resolution "
264 "is defined by a reference raster layer and is always of int32 type." );
267QgsRasterStackLowestPositionAlgorithm *QgsRasterStackLowestPositionAlgorithm::createInstance()
const
269 return new QgsRasterStackLowestPositionAlgorithm();
272int QgsRasterStackLowestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
274 int lowestPosition = 0;
277 const int inputBlocksCount = inputBlocks.size();
278 int currentPosition = 0;
280 double firstValue = mNoDataValue;
281 bool firstValueIsNoData =
true;
283 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
286 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
287 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
289 if ( !firstBlock->isValid() || firstValueIsNoData )
291 noDataInRasterBlockStack =
true;
296 lowestPosition = currentPosition;
301 if ( noDataCount == inputBlocksCount )
303 noDataInRasterBlockStack =
true;
309 while ( currentPosition < inputBlocksCount )
311 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
313 bool currentValueIsNoData =
false;
314 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
316 if ( !currentBlock->isValid() || currentValueIsNoData )
318 noDataInRasterBlockStack =
true;
323 if ( currentValue < firstValue )
325 firstValue = currentValue;
326 lowestPosition = currentPosition;
333 return ++lowestPosition;
340QString QgsRasterStackHighestPositionAlgorithm::displayName()
const
342 return QObject::tr(
"Highest position in raster stack" );
345QString QgsRasterStackHighestPositionAlgorithm::name()
const
347 return QStringLiteral(
"highestpositioninrasterstack" );
350QStringList QgsRasterStackHighestPositionAlgorithm::tags()
const
352 return QObject::tr(
"cell,highest,position,pixel,stack" ).split(
',' );
355QString QgsRasterStackHighestPositionAlgorithm::shortDescription()
const
357 return QObject::tr(
"Evaluates on a cell-by-cell basis the position "
358 "of the raster with the highest value in a stack of rasters." );
361QString QgsRasterStackHighestPositionAlgorithm::shortHelpString()
const
363 return QObject::tr(
"This algorithm evaluates on a cell-by-cell basis the position "
364 "of the raster with the highest value in a stack of rasters. Position counts start "
365 "with 1 and range to the total number of input rasters. The order of the input "
366 "rasters is relevant for the algorithm. If multiple rasters feature the highest value, "
367 "the first raster will be used for the position value.\n "
368 "If multiband rasters are used in the data raster stack, the algorithm will always "
369 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
370 "Any NoData cells in the raster layer stack will result in a NoData cell "
371 "in the output raster unless the \"ignore NoData\" parameter is checked. "
372 "The output NoData value can be set manually. The output rasters extent and resolution "
373 "is defined by a reference raster layer and is always of int32 type." );
376QgsRasterStackHighestPositionAlgorithm *QgsRasterStackHighestPositionAlgorithm::createInstance()
const
378 return new QgsRasterStackHighestPositionAlgorithm();
381int QgsRasterStackHighestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
383 int highestPosition = 0;
386 const int inputBlocksCount = inputBlocks.size();
387 int currentPosition = 0;
389 double firstValue = mNoDataValue;
390 bool firstValueIsNoData =
true;
392 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
395 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
396 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
398 if ( !firstBlock->isValid() || firstValueIsNoData )
400 noDataInRasterBlockStack =
true;
405 highestPosition = currentPosition;
411 if ( noDataCount == inputBlocksCount )
413 noDataInRasterBlockStack =
true;
419 while ( currentPosition < inputBlocksCount )
421 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
423 bool currentValueIsNoData =
false;
424 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
426 if ( !currentBlock->isValid() || currentValueIsNoData )
428 noDataInRasterBlockStack =
true;
433 if ( currentValue > firstValue )
435 firstValue = currentValue;
436 highestPosition = currentPosition;
443 return ++highestPosition;
@ Int32
Thirty two bit signed integer (qint32)
@ 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.
@ Double
Double/float values.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Base class for all map layer types.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
A numeric output for processing algorithms.
A string output for processing algorithms.
A boolean parameter for processing algorithms.
A parameter for processing algorithms which accepts multiple map layers.
A raster layer destination parameter, for specifying the destination path for a raster layer created ...
A raster layer parameter for processing algorithms.
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
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.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis.
int width() const
Returns the width of the (unclipped) raster.
A rectangle specified with double values.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...