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::shortHelpString()
const
248 return QObject::tr(
"The lowest position algorithm evaluates on a cell-by-cell basis the position "
249 "of the raster with the lowest value in a stack of rasters. Position counts start "
250 "with 1 and range to the total number of input rasters. The order of the input "
251 "rasters is relevant for the algorithm. If multiple rasters feature the lowest value, "
252 "the first raster will be used for the position value.\n "
253 "If multiband rasters are used in the data raster stack, the algorithm will always "
254 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
255 "Any NoData cells in the raster layer stack will result in a NoData cell "
256 "in the output raster unless the \"ignore NoData\" parameter is checked. "
257 "The output NoData value can be set manually. The output rasters extent and resolution "
258 "is defined by a reference raster layer and is always of int32 type." );
261QgsRasterStackLowestPositionAlgorithm *QgsRasterStackLowestPositionAlgorithm::createInstance()
const
263 return new QgsRasterStackLowestPositionAlgorithm();
266int QgsRasterStackLowestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
268 int lowestPosition = 0;
271 const int inputBlocksCount = inputBlocks.size();
272 int currentPosition = 0;
274 double firstValue = mNoDataValue;
275 bool firstValueIsNoData =
true;
277 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
280 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
281 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
283 if ( !firstBlock->isValid() || firstValueIsNoData )
285 noDataInRasterBlockStack =
true;
290 lowestPosition = currentPosition;
295 if ( noDataCount == inputBlocksCount )
297 noDataInRasterBlockStack =
true;
303 while ( currentPosition < inputBlocksCount )
305 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
307 bool currentValueIsNoData =
false;
308 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
310 if ( !currentBlock->isValid() || currentValueIsNoData )
312 noDataInRasterBlockStack =
true;
317 if ( currentValue < firstValue )
319 firstValue = currentValue;
320 lowestPosition = currentPosition;
327 return ++lowestPosition;
334QString QgsRasterStackHighestPositionAlgorithm::displayName()
const
336 return QObject::tr(
"Highest position in raster stack" );
339QString QgsRasterStackHighestPositionAlgorithm::name()
const
341 return QStringLiteral(
"highestpositioninrasterstack" );
344QStringList QgsRasterStackHighestPositionAlgorithm::tags()
const
346 return QObject::tr(
"cell,highest,position,pixel,stack" ).split(
',' );
349QString QgsRasterStackHighestPositionAlgorithm::shortHelpString()
const
351 return QObject::tr(
"The highest position algorithm evaluates on a cell-by-cell basis the position "
352 "of the raster with the highest value in a stack of rasters. Position counts start "
353 "with 1 and range to the total number of input rasters. The order of the input "
354 "rasters is relevant for the algorithm. If multiple rasters feature the highest value, "
355 "the first raster will be used for the position value.\n "
356 "If multiband rasters are used in the data raster stack, the algorithm will always "
357 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
358 "Any NoData cells in the raster layer stack will result in a NoData cell "
359 "in the output raster unless the \"ignore NoData\" parameter is checked. "
360 "The output NoData value can be set manually. The output rasters extent and resolution "
361 "is defined by a reference raster layer and is always of int32 type." );
364QgsRasterStackHighestPositionAlgorithm *QgsRasterStackHighestPositionAlgorithm::createInstance()
const
366 return new QgsRasterStackHighestPositionAlgorithm();
369int QgsRasterStackHighestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
371 int highestPosition = 0;
374 const int inputBlocksCount = inputBlocks.size();
375 int currentPosition = 0;
377 double firstValue = mNoDataValue;
378 bool firstValueIsNoData =
true;
380 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
383 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
384 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
386 if ( !firstBlock->isValid() || firstValueIsNoData )
388 noDataInRasterBlockStack =
true;
393 highestPosition = currentPosition;
399 if ( noDataCount == inputBlocksCount )
401 noDataInRasterBlockStack =
true;
407 while ( currentPosition < inputBlocksCount )
409 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
411 bool currentValueIsNoData =
false;
412 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
414 if ( !currentBlock->isValid() || currentValueIsNoData )
416 noDataInRasterBlockStack =
true;
421 if ( currentValue > firstValue )
423 firstValue = currentValue;
424 highestPosition = currentPosition;
431 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...