30QString QgsRasterStackPositionAlgorithmBase::group()
const
32 return QObject::tr(
"Raster analysis" );
35QString QgsRasterStackPositionAlgorithmBase::groupId()
const
37 return QStringLiteral(
"rasteranalysis" );
40void QgsRasterStackPositionAlgorithmBase::initAlgorithm(
const QVariantMap & )
48 auto 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() );
54 auto createOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATE_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
55 createOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
57 addParameter( createOptsParam.release() );
59 auto creationOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATION_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
60 creationOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
62 addParameter( creationOptsParam.release() );
74 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, QStringLiteral(
"REFERENCE_LAYER" ), context );
75 if ( !referenceLayer )
78 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
79 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
81 mCrs = referenceLayer->
crs();
84 mLayerWidth = referenceLayer->
width();
85 mLayerHeight = referenceLayer->
height();
86 mExtent = referenceLayer->
extent();
88 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT_RASTERS" ), context );
89 QList<QgsRasterLayer *> rasterLayers;
90 rasterLayers.reserve( layers.count() );
99 QgsRasterAnalysisUtils::RasterLogicInput input;
103 input.interface = input.sourceDataProvider.get();
105 if ( layer->
crs() != mCrs )
107 input.projector = std::make_unique<QgsRasterProjector>();
108 input.projector->setInput( input.sourceDataProvider.get() );
110 input.interface = input.projector.get();
112 mInputs.emplace_back( std::move( input ) );
121 QString creationOptions = parameterAsString( parameters, QStringLiteral(
"CREATION_OPTIONS" ), context ).trimmed();
123 const QString optionsString = parameterAsString( parameters, QStringLiteral(
"CREATE_OPTIONS" ), context );
124 if ( !optionsString.isEmpty() )
125 creationOptions = optionsString;
127 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
128 const QFileInfo fi( outputFile );
131 auto writer = std::make_unique<QgsRasterFileWriter>( outputFile );
132 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
133 if ( !creationOptions.isEmpty() )
135 writer->setCreationOptions( creationOptions.split(
'|' ) );
137 writer->setOutputFormat( outputFormat );
138 std::unique_ptr<QgsRasterDataProvider> provider( writer->createOneBandRaster(
Qgis::DataType::Int32, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
141 if ( !provider->isValid() )
144 provider->setNoDataValue( 1, mNoDataValue );
145 const qgssize layerSize =
static_cast<qgssize>( mLayerWidth ) *
static_cast<qgssize>( mLayerHeight );
149 const int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
150 const int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
151 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
152 provider->setEditable(
true );
155 iter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
162 std::unique_ptr<QgsRasterBlock> outputBlock;
163 while ( iter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
165 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
166 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : mInputs )
170 for (
const int band : i.bands )
174 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
175 inputBlocks.emplace_back( std::move( b ) );
179 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
180 for (
int row = 0; row < iterRows; row++ )
185 for (
int col = 0; col < iterCols; col++ )
187 bool noDataInStack =
false;
189 if ( !inputBlocks.empty() )
191 const int position = findPosition( inputBlocks, row, col, noDataInStack );
193 if ( position == -1 || ( noDataInStack && !mIgnoreNoData ) )
198 outputBlock->setValue( row, col, mNoDataValue );
202 outputBlock->setValue( row, col, position );
207 outputBlock->setValue( row, col, mNoDataValue );
211 if ( !provider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
213 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( provider->error().summary() ) );
216 provider->setEditable(
false );
219 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
220 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
221 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
222 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
223 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
224 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
232QString QgsRasterStackLowestPositionAlgorithm::displayName()
const
234 return QObject::tr(
"Lowest position in raster stack" );
237QString QgsRasterStackLowestPositionAlgorithm::name()
const
239 return QStringLiteral(
"lowestpositioninrasterstack" );
242QStringList QgsRasterStackLowestPositionAlgorithm::tags()
const
244 return QObject::tr(
"cell,lowest,position,pixel,stack" ).split(
',' );
247QString QgsRasterStackLowestPositionAlgorithm::shortDescription()
const
249 return QObject::tr(
"Evaluates on a cell-by-cell basis the position "
250 "of the raster with the lowest value in a stack of rasters." );
253QString QgsRasterStackLowestPositionAlgorithm::shortHelpString()
const
255 return QObject::tr(
"This algorithm evaluates on a cell-by-cell basis the position "
256 "of the raster with the lowest value in a stack of rasters. Position counts start "
257 "with 1 and range to the total number of input rasters. The order of the input "
258 "rasters is relevant for the algorithm. If multiple rasters feature the lowest value, "
259 "the first raster will be used for the position value.\n "
260 "If multiband rasters are used in the data raster stack, the algorithm will always "
261 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
262 "Any NoData cells in the raster layer stack will result in a NoData cell "
263 "in the output raster unless the \"ignore NoData\" parameter is checked. "
264 "The output NoData value can be set manually. The output rasters extent and resolution "
265 "is defined by a reference raster layer and is always of int32 type." );
268QgsRasterStackLowestPositionAlgorithm *QgsRasterStackLowestPositionAlgorithm::createInstance()
const
270 return new QgsRasterStackLowestPositionAlgorithm();
273int QgsRasterStackLowestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
275 int lowestPosition = 0;
278 const int inputBlocksCount = inputBlocks.size();
279 int currentPosition = 0;
281 double firstValue = mNoDataValue;
282 bool firstValueIsNoData =
true;
284 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
287 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
288 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
290 if ( !firstBlock->isValid() || firstValueIsNoData )
292 noDataInRasterBlockStack =
true;
297 lowestPosition = currentPosition;
302 if ( noDataCount == inputBlocksCount )
304 noDataInRasterBlockStack =
true;
310 while ( currentPosition < inputBlocksCount )
312 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
314 bool currentValueIsNoData =
false;
315 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
317 if ( !currentBlock->isValid() || currentValueIsNoData )
319 noDataInRasterBlockStack =
true;
324 if ( currentValue < firstValue )
326 firstValue = currentValue;
327 lowestPosition = currentPosition;
334 return ++lowestPosition;
341QString QgsRasterStackHighestPositionAlgorithm::displayName()
const
343 return QObject::tr(
"Highest position in raster stack" );
346QString QgsRasterStackHighestPositionAlgorithm::name()
const
348 return QStringLiteral(
"highestpositioninrasterstack" );
351QStringList QgsRasterStackHighestPositionAlgorithm::tags()
const
353 return QObject::tr(
"cell,highest,position,pixel,stack" ).split(
',' );
356QString QgsRasterStackHighestPositionAlgorithm::shortDescription()
const
358 return QObject::tr(
"Evaluates on a cell-by-cell basis the position "
359 "of the raster with the highest value in a stack of rasters." );
362QString QgsRasterStackHighestPositionAlgorithm::shortHelpString()
const
364 return QObject::tr(
"This algorithm evaluates on a cell-by-cell basis the position "
365 "of the raster with the highest value in a stack of rasters. Position counts start "
366 "with 1 and range to the total number of input rasters. The order of the input "
367 "rasters is relevant for the algorithm. If multiple rasters feature the highest value, "
368 "the first raster will be used for the position value.\n "
369 "If multiband rasters are used in the data raster stack, the algorithm will always "
370 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
371 "Any NoData cells in the raster layer stack will result in a NoData cell "
372 "in the output raster unless the \"ignore NoData\" parameter is checked. "
373 "The output NoData value can be set manually. The output rasters extent and resolution "
374 "is defined by a reference raster layer and is always of int32 type." );
377QgsRasterStackHighestPositionAlgorithm *QgsRasterStackHighestPositionAlgorithm::createInstance()
const
379 return new QgsRasterStackHighestPositionAlgorithm();
382int QgsRasterStackHighestPositionAlgorithm::findPosition( std::vector<std::unique_ptr<QgsRasterBlock>> &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
384 int highestPosition = 0;
387 const int inputBlocksCount = inputBlocks.size();
388 int currentPosition = 0;
390 double firstValue = mNoDataValue;
391 bool firstValueIsNoData =
true;
393 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
396 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
397 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
399 if ( !firstBlock->isValid() || firstValueIsNoData )
401 noDataInRasterBlockStack =
true;
406 highestPosition = currentPosition;
412 if ( noDataCount == inputBlocksCount )
414 noDataInRasterBlockStack =
true;
420 while ( currentPosition < inputBlocksCount )
422 std::unique_ptr<QgsRasterBlock> ¤tBlock = inputBlocks.at( currentPosition );
424 bool currentValueIsNoData =
false;
425 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
427 if ( !currentBlock->isValid() || currentValueIsNoData )
429 noDataInRasterBlockStack =
true;
434 if ( currentValue > firstValue )
436 firstValue = currentValue;
437 highestPosition = currentPosition;
444 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...