29QString QgsRasterStackPositionAlgorithmBase::group()
const
31 return QObject::tr(
"Raster analysis" );
34QString QgsRasterStackPositionAlgorithmBase::groupId()
const
36 return QStringLiteral(
"rasteranalysis" );
39void QgsRasterStackPositionAlgorithmBase::initAlgorithm(
const QVariantMap & )
48 std::unique_ptr< QgsProcessingParameterNumber > output_nodata_parameter = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral(
"OUTPUT_NODATA_VALUE" ), QObject::tr(
"Output NoData value" ),
Qgis::ProcessingNumberParameterType::Double, -9999,
true );
50 addParameter( output_nodata_parameter.release() );
53 QObject::tr(
"Output layer" ) ) );
63 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, QStringLiteral(
"REFERENCE_LAYER" ), context );
64 if ( !referenceLayer )
67 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
68 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
70 mCrs = referenceLayer->
crs();
73 mLayerWidth = referenceLayer->
width();
74 mLayerHeight = referenceLayer->
height();
75 mExtent = referenceLayer->
extent();
77 const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT_RASTERS" ), context );
78 QList< QgsRasterLayer * > rasterLayers;
79 rasterLayers.reserve( layers.count() );
88 QgsRasterAnalysisUtils::RasterLogicInput input;
92 input.interface = input.sourceDataProvider.get();
94 if ( layer->
crs() != mCrs )
96 input.projector = std::make_unique< QgsRasterProjector >();
97 input.projector->setInput( input.sourceDataProvider.get() );
99 input.interface = input.projector.get();
101 mInputs.emplace_back( std::move( input ) );
110 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
111 const QFileInfo fi( outputFile );
114 std::unique_ptr< QgsRasterFileWriter > writer = std::make_unique< QgsRasterFileWriter >( outputFile );
115 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
116 writer->setOutputFormat( outputFormat );
117 std::unique_ptr<QgsRasterDataProvider > provider( writer->createOneBandRaster(
Qgis::DataType::Int32, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
120 if ( !provider->isValid() )
123 provider->setNoDataValue( 1, mNoDataValue );
124 const qgssize layerSize =
static_cast< qgssize >( mLayerWidth ) *
static_cast< qgssize >( mLayerHeight );
128 const int nbBlocksWidth =
static_cast< int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
129 const int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
130 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
131 provider->setEditable(
true );
134 iter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
141 std::unique_ptr< QgsRasterBlock > outputBlock;
142 while ( iter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
144 std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
145 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : mInputs )
149 for (
const int band : i.bands )
153 std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
154 inputBlocks.emplace_back( std::move( b ) );
158 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
159 for (
int row = 0; row < iterRows; row++ )
164 for (
int col = 0; col < iterCols; col++ )
166 bool noDataInStack =
false;
168 if ( !inputBlocks.empty() )
170 const int position = findPosition( inputBlocks, row, col, noDataInStack );
172 if ( position == -1 || ( noDataInStack && !mIgnoreNoData ) )
177 outputBlock->setValue( row, col, mNoDataValue );
181 outputBlock->setValue( row, col, position );
186 outputBlock->setValue( row, col, mNoDataValue );
190 provider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
192 provider->setEditable(
false );
195 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
196 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
197 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
198 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
199 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
200 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
208QString QgsRasterStackLowestPositionAlgorithm::displayName()
const
210 return QObject::tr(
"Lowest position in raster stack" );
213QString QgsRasterStackLowestPositionAlgorithm::name()
const
215 return QStringLiteral(
"lowestpositioninrasterstack" );
218QStringList QgsRasterStackLowestPositionAlgorithm::tags()
const
220 return QObject::tr(
"cell,lowest,position,pixel,stack" ).split(
',' );
223QString QgsRasterStackLowestPositionAlgorithm::shortHelpString()
const
225 return QObject::tr(
"The lowest position algorithm evaluates on a cell-by-cell basis the position "
226 "of the raster with the lowest value in a stack of rasters. Position counts start "
227 "with 1 and range to the total number of input rasters. The order of the input "
228 "rasters is relevant for the algorithm. If multiple rasters feature the lowest value, "
229 "the first raster will be used for the position value.\n "
230 "If multiband rasters are used in the data raster stack, the algorithm will always "
231 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
232 "Any NoData cells in the raster layer stack will result in a NoData cell "
233 "in the output raster unless the \"ignore NoData\" parameter is checked. "
234 "The output NoData value can be set manually. The output rasters extent and resolution "
235 "is defined by a reference raster layer and is always of int32 type." );
238QgsRasterStackLowestPositionAlgorithm *QgsRasterStackLowestPositionAlgorithm::createInstance()
const
240 return new QgsRasterStackLowestPositionAlgorithm();
243int QgsRasterStackLowestPositionAlgorithm::findPosition( std::vector< std::unique_ptr<QgsRasterBlock> > &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
245 int lowestPosition = 0;
248 const int inputBlocksCount = inputBlocks.size();
249 int currentPosition = 0;
251 double firstValue = mNoDataValue;
252 bool firstValueIsNoData =
true;
254 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
257 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
258 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
260 if ( !firstBlock->isValid() || firstValueIsNoData )
262 noDataInRasterBlockStack =
true;
267 lowestPosition = currentPosition;
272 if ( noDataCount == inputBlocksCount )
274 noDataInRasterBlockStack =
true;
280 while ( currentPosition < inputBlocksCount )
282 std::unique_ptr< QgsRasterBlock > ¤tBlock = inputBlocks.at( currentPosition );
284 bool currentValueIsNoData =
false;
285 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
287 if ( !currentBlock->isValid() || currentValueIsNoData )
289 noDataInRasterBlockStack =
true;
294 if ( currentValue < firstValue )
296 firstValue = currentValue;
297 lowestPosition = currentPosition;
304 return ++lowestPosition;
311QString QgsRasterStackHighestPositionAlgorithm::displayName()
const
313 return QObject::tr(
"Highest position in raster stack" );
316QString QgsRasterStackHighestPositionAlgorithm::name()
const
318 return QStringLiteral(
"highestpositioninrasterstack" );
321QStringList QgsRasterStackHighestPositionAlgorithm::tags()
const
323 return QObject::tr(
"cell,highest,position,pixel,stack" ).split(
',' );
326QString QgsRasterStackHighestPositionAlgorithm::shortHelpString()
const
328 return QObject::tr(
"The highest position algorithm evaluates on a cell-by-cell basis the position "
329 "of the raster with the highest value in a stack of rasters. Position counts start "
330 "with 1 and range to the total number of input rasters. The order of the input "
331 "rasters is relevant for the algorithm. If multiple rasters feature the highest value, "
332 "the first raster will be used for the position value.\n "
333 "If multiband rasters are used in the data raster stack, the algorithm will always "
334 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
335 "Any NoData cells in the raster layer stack will result in a NoData cell "
336 "in the output raster unless the \"ignore NoData\" parameter is checked. "
337 "The output NoData value can be set manually. The output rasters extent and resolution "
338 "is defined by a reference raster layer and is always of int32 type." );
341QgsRasterStackHighestPositionAlgorithm *QgsRasterStackHighestPositionAlgorithm::createInstance()
const
343 return new QgsRasterStackHighestPositionAlgorithm();
346int QgsRasterStackHighestPositionAlgorithm::findPosition( std::vector< std::unique_ptr< QgsRasterBlock> > &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
348 int highestPosition = 0;
351 const int inputBlocksCount = inputBlocks.size();
352 int currentPosition = 0;
354 double firstValue = mNoDataValue;
355 bool firstValueIsNoData =
true;
357 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
360 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
361 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
363 if ( !firstBlock->isValid() || firstValueIsNoData )
365 noDataInRasterBlockStack =
true;
370 highestPosition = currentPosition;
376 if ( noDataCount == inputBlocksCount )
378 noDataInRasterBlockStack =
true;
384 while ( currentPosition < inputBlocksCount )
386 std::unique_ptr< QgsRasterBlock > ¤tBlock = inputBlocks.at( currentPosition );
388 bool currentValueIsNoData =
false;
389 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
391 if ( !currentBlock->isValid() || currentValueIsNoData )
393 noDataInRasterBlockStack =
true;
398 if ( currentValue > firstValue )
400 firstValue = currentValue;
401 highestPosition = currentPosition;
408 return ++highestPosition;
@ Int32
Thirty two bit signed integer (qint32)
@ 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...