29QString QgsRasterStackPositionAlgorithmBase::group()
const
31 return QObject::tr(
"Raster analysis" );
34QString QgsRasterStackPositionAlgorithmBase::groupId()
const
36 return QStringLiteral(
"rasteranalysis" );
39void QgsRasterStackPositionAlgorithmBase::initAlgorithm(
const QVariantMap & )
47 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 );
49 addParameter( output_nodata_parameter.release() );
51 std::unique_ptr<QgsProcessingParameterString> createOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATE_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
52 createOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
54 addParameter( createOptsParam.release() );
66 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, QStringLiteral(
"REFERENCE_LAYER" ), context );
67 if ( !referenceLayer )
70 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
71 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
73 mCrs = referenceLayer->
crs();
76 mLayerWidth = referenceLayer->
width();
77 mLayerHeight = referenceLayer->
height();
78 mExtent = referenceLayer->
extent();
80 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT_RASTERS" ), context );
81 QList<QgsRasterLayer *> rasterLayers;
82 rasterLayers.reserve( layers.count() );
91 QgsRasterAnalysisUtils::RasterLogicInput input;
95 input.interface = input.sourceDataProvider.get();
97 if ( layer->
crs() != mCrs )
99 input.projector = std::make_unique<QgsRasterProjector>();
100 input.projector->setInput( input.sourceDataProvider.get() );
102 input.interface = input.projector.get();
104 mInputs.emplace_back( std::move( input ) );
113 const QString createOptions = parameterAsString( parameters, QStringLiteral(
"CREATE_OPTIONS" ), context ).trimmed();
114 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
115 const QFileInfo fi( outputFile );
118 std::unique_ptr<QgsRasterFileWriter> writer = std::make_unique<QgsRasterFileWriter>( outputFile );
119 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
120 if ( !createOptions.isEmpty() )
122 writer->setCreateOptions( createOptions.split(
'|' ) );
124 writer->setOutputFormat( outputFormat );
125 std::unique_ptr<QgsRasterDataProvider> provider( writer->createOneBandRaster(
Qgis::DataType::Int32, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
128 if ( !provider->isValid() )
131 provider->setNoDataValue( 1, mNoDataValue );
132 const qgssize layerSize =
static_cast<qgssize>( mLayerWidth ) *
static_cast<qgssize>( mLayerHeight );
136 const int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
137 const int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
138 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
139 provider->setEditable(
true );
142 iter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
149 std::unique_ptr<QgsRasterBlock> outputBlock;
150 while ( iter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
152 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
153 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : mInputs )
157 for (
const int band : i.bands )
161 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
162 inputBlocks.emplace_back( std::move( b ) );
166 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
167 for (
int row = 0; row < iterRows; row++ )
172 for (
int col = 0; col < iterCols; col++ )
174 bool noDataInStack =
false;
176 if ( !inputBlocks.empty() )
178 const int position = findPosition( inputBlocks, row, col, noDataInStack );
180 if ( position == -1 || ( noDataInStack && !mIgnoreNoData ) )
185 outputBlock->setValue( row, col, mNoDataValue );
189 outputBlock->setValue( row, col, position );
194 outputBlock->setValue( row, col, mNoDataValue );
198 provider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
200 provider->setEditable(
false );
203 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
204 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
205 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
206 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
207 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
208 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
216QString QgsRasterStackLowestPositionAlgorithm::displayName()
const
218 return QObject::tr(
"Lowest position in raster stack" );
221QString QgsRasterStackLowestPositionAlgorithm::name()
const
223 return QStringLiteral(
"lowestpositioninrasterstack" );
226QStringList QgsRasterStackLowestPositionAlgorithm::tags()
const
228 return QObject::tr(
"cell,lowest,position,pixel,stack" ).split(
',' );
231QString QgsRasterStackLowestPositionAlgorithm::shortHelpString()
const
233 return QObject::tr(
"The lowest position algorithm evaluates on a cell-by-cell basis the position "
234 "of the raster with the lowest value in a stack of rasters. Position counts start "
235 "with 1 and range to the total number of input rasters. The order of the input "
236 "rasters is relevant for the algorithm. If multiple rasters feature the lowest value, "
237 "the first raster will be used for the position value.\n "
238 "If multiband rasters are used in the data raster stack, the algorithm will always "
239 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
240 "Any NoData cells in the raster layer stack will result in a NoData cell "
241 "in the output raster unless the \"ignore NoData\" parameter is checked. "
242 "The output NoData value can be set manually. The output rasters extent and resolution "
243 "is defined by a reference raster layer and is always of int32 type." );
246QgsRasterStackLowestPositionAlgorithm *QgsRasterStackLowestPositionAlgorithm::createInstance()
const
248 return new QgsRasterStackLowestPositionAlgorithm();
251int QgsRasterStackLowestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
253 int lowestPosition = 0;
256 const int inputBlocksCount = inputBlocks.size();
257 int currentPosition = 0;
259 double firstValue = mNoDataValue;
260 bool firstValueIsNoData =
true;
262 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
265 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
266 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
268 if ( !firstBlock->isValid() || firstValueIsNoData )
270 noDataInRasterBlockStack =
true;
275 lowestPosition = currentPosition;
280 if ( noDataCount == inputBlocksCount )
282 noDataInRasterBlockStack =
true;
288 while ( currentPosition < inputBlocksCount )
290 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
292 bool currentValueIsNoData =
false;
293 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
295 if ( !currentBlock->isValid() || currentValueIsNoData )
297 noDataInRasterBlockStack =
true;
302 if ( currentValue < firstValue )
304 firstValue = currentValue;
305 lowestPosition = currentPosition;
312 return ++lowestPosition;
319QString QgsRasterStackHighestPositionAlgorithm::displayName()
const
321 return QObject::tr(
"Highest position in raster stack" );
324QString QgsRasterStackHighestPositionAlgorithm::name()
const
326 return QStringLiteral(
"highestpositioninrasterstack" );
329QStringList QgsRasterStackHighestPositionAlgorithm::tags()
const
331 return QObject::tr(
"cell,highest,position,pixel,stack" ).split(
',' );
334QString QgsRasterStackHighestPositionAlgorithm::shortHelpString()
const
336 return QObject::tr(
"The highest position algorithm evaluates on a cell-by-cell basis the position "
337 "of the raster with the highest value in a stack of rasters. Position counts start "
338 "with 1 and range to the total number of input rasters. The order of the input "
339 "rasters is relevant for the algorithm. If multiple rasters feature the highest value, "
340 "the first raster will be used for the position value.\n "
341 "If multiband rasters are used in the data raster stack, the algorithm will always "
342 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
343 "Any NoData cells in the raster layer stack will result in a NoData cell "
344 "in the output raster unless the \"ignore NoData\" parameter is checked. "
345 "The output NoData value can be set manually. The output rasters extent and resolution "
346 "is defined by a reference raster layer and is always of int32 type." );
349QgsRasterStackHighestPositionAlgorithm *QgsRasterStackHighestPositionAlgorithm::createInstance()
const
351 return new QgsRasterStackHighestPositionAlgorithm();
354int QgsRasterStackHighestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
356 int highestPosition = 0;
359 const int inputBlocksCount = inputBlocks.size();
360 int currentPosition = 0;
362 double firstValue = mNoDataValue;
363 bool firstValueIsNoData =
true;
365 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
368 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
369 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
371 if ( !firstBlock->isValid() || firstValueIsNoData )
373 noDataInRasterBlockStack =
true;
378 highestPosition = currentPosition;
384 if ( noDataCount == inputBlocksCount )
386 noDataInRasterBlockStack =
true;
392 while ( currentPosition < inputBlocksCount )
394 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
396 bool currentValueIsNoData =
false;
397 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
399 if ( !currentBlock->isValid() || currentValueIsNoData )
401 noDataInRasterBlockStack =
true;
406 if ( currentValue > firstValue )
408 firstValue = currentValue;
409 highestPosition = currentPosition;
416 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...