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() );
51 auto 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 auto 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 if ( !provider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
200 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( provider->error().summary() ) );
203 provider->setEditable(
false );
206 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
207 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
208 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
209 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
210 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
211 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
219QString QgsRasterStackLowestPositionAlgorithm::displayName()
const
221 return QObject::tr(
"Lowest position in raster stack" );
224QString QgsRasterStackLowestPositionAlgorithm::name()
const
226 return QStringLiteral(
"lowestpositioninrasterstack" );
229QStringList QgsRasterStackLowestPositionAlgorithm::tags()
const
231 return QObject::tr(
"cell,lowest,position,pixel,stack" ).split(
',' );
234QString QgsRasterStackLowestPositionAlgorithm::shortHelpString()
const
236 return QObject::tr(
"The lowest position algorithm evaluates on a cell-by-cell basis the position "
237 "of the raster with the lowest value in a stack of rasters. Position counts start "
238 "with 1 and range to the total number of input rasters. The order of the input "
239 "rasters is relevant for the algorithm. If multiple rasters feature the lowest value, "
240 "the first raster will be used for the position value.\n "
241 "If multiband rasters are used in the data raster stack, the algorithm will always "
242 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
243 "Any NoData cells in the raster layer stack will result in a NoData cell "
244 "in the output raster unless the \"ignore NoData\" parameter is checked. "
245 "The output NoData value can be set manually. The output rasters extent and resolution "
246 "is defined by a reference raster layer and is always of int32 type." );
249QgsRasterStackLowestPositionAlgorithm *QgsRasterStackLowestPositionAlgorithm::createInstance()
const
251 return new QgsRasterStackLowestPositionAlgorithm();
254int QgsRasterStackLowestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
256 int lowestPosition = 0;
259 const int inputBlocksCount = inputBlocks.size();
260 int currentPosition = 0;
262 double firstValue = mNoDataValue;
263 bool firstValueIsNoData =
true;
265 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
268 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
269 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
271 if ( !firstBlock->isValid() || firstValueIsNoData )
273 noDataInRasterBlockStack =
true;
278 lowestPosition = currentPosition;
283 if ( noDataCount == inputBlocksCount )
285 noDataInRasterBlockStack =
true;
291 while ( currentPosition < inputBlocksCount )
293 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
295 bool currentValueIsNoData =
false;
296 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
298 if ( !currentBlock->isValid() || currentValueIsNoData )
300 noDataInRasterBlockStack =
true;
305 if ( currentValue < firstValue )
307 firstValue = currentValue;
308 lowestPosition = currentPosition;
315 return ++lowestPosition;
322QString QgsRasterStackHighestPositionAlgorithm::displayName()
const
324 return QObject::tr(
"Highest position in raster stack" );
327QString QgsRasterStackHighestPositionAlgorithm::name()
const
329 return QStringLiteral(
"highestpositioninrasterstack" );
332QStringList QgsRasterStackHighestPositionAlgorithm::tags()
const
334 return QObject::tr(
"cell,highest,position,pixel,stack" ).split(
',' );
337QString QgsRasterStackHighestPositionAlgorithm::shortHelpString()
const
339 return QObject::tr(
"The highest position algorithm evaluates on a cell-by-cell basis the position "
340 "of the raster with the highest value in a stack of rasters. Position counts start "
341 "with 1 and range to the total number of input rasters. The order of the input "
342 "rasters is relevant for the algorithm. If multiple rasters feature the highest value, "
343 "the first raster will be used for the position value.\n "
344 "If multiband rasters are used in the data raster stack, the algorithm will always "
345 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
346 "Any NoData cells in the raster layer stack will result in a NoData cell "
347 "in the output raster unless the \"ignore NoData\" parameter is checked. "
348 "The output NoData value can be set manually. The output rasters extent and resolution "
349 "is defined by a reference raster layer and is always of int32 type." );
352QgsRasterStackHighestPositionAlgorithm *QgsRasterStackHighestPositionAlgorithm::createInstance()
const
354 return new QgsRasterStackHighestPositionAlgorithm();
357int QgsRasterStackHighestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
359 int highestPosition = 0;
362 const int inputBlocksCount = inputBlocks.size();
363 int currentPosition = 0;
365 double firstValue = mNoDataValue;
366 bool firstValueIsNoData =
true;
368 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
371 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
372 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
374 if ( !firstBlock->isValid() || firstValueIsNoData )
376 noDataInRasterBlockStack =
true;
381 highestPosition = currentPosition;
387 if ( noDataCount == inputBlocksCount )
389 noDataInRasterBlockStack =
true;
395 while ( currentPosition < inputBlocksCount )
397 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
399 bool currentValueIsNoData =
false;
400 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
402 if ( !currentBlock->isValid() || currentValueIsNoData )
404 noDataInRasterBlockStack =
true;
409 if ( currentValue > firstValue )
411 firstValue = currentValue;
412 highestPosition = currentPosition;
419 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...