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() );
52 std::unique_ptr< QgsProcessingParameterString > createOptsParam = std::make_unique< QgsProcessingParameterString >( QStringLiteral(
"CREATE_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
53 createOptsParam->setMetadata( QVariantMap( {{QStringLiteral(
"widget_wrapper" ), QVariantMap( {{QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) }} ) }} ) );
55 addParameter( createOptsParam.release() );
58 QObject::tr(
"Output layer" ) ) );
68 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, QStringLiteral(
"REFERENCE_LAYER" ), context );
69 if ( !referenceLayer )
72 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
73 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
75 mCrs = referenceLayer->
crs();
78 mLayerWidth = referenceLayer->
width();
79 mLayerHeight = referenceLayer->
height();
80 mExtent = referenceLayer->
extent();
82 const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT_RASTERS" ), context );
83 QList< QgsRasterLayer * > rasterLayers;
84 rasterLayers.reserve( layers.count() );
93 QgsRasterAnalysisUtils::RasterLogicInput input;
97 input.interface = input.sourceDataProvider.get();
99 if ( layer->
crs() != mCrs )
101 input.projector = std::make_unique< QgsRasterProjector >();
102 input.projector->setInput( input.sourceDataProvider.get() );
104 input.interface = input.projector.get();
106 mInputs.emplace_back( std::move( input ) );
115 const QString createOptions = parameterAsString( parameters, QStringLiteral(
"CREATE_OPTIONS" ), context ).trimmed();
116 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
117 const QFileInfo fi( outputFile );
120 std::unique_ptr< QgsRasterFileWriter > writer = std::make_unique< QgsRasterFileWriter >( outputFile );
121 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
122 if ( !createOptions.isEmpty() )
124 writer->setCreateOptions( createOptions.split(
'|' ) );
126 writer->setOutputFormat( outputFormat );
127 std::unique_ptr<QgsRasterDataProvider > provider( writer->createOneBandRaster(
Qgis::DataType::Int32, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
130 if ( !provider->isValid() )
133 provider->setNoDataValue( 1, mNoDataValue );
134 const qgssize layerSize =
static_cast< qgssize >( mLayerWidth ) *
static_cast< qgssize >( mLayerHeight );
138 const int nbBlocksWidth =
static_cast< int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
139 const int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
140 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
141 provider->setEditable(
true );
144 iter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
151 std::unique_ptr< QgsRasterBlock > outputBlock;
152 while ( iter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
154 std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
155 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : mInputs )
159 for (
const int band : i.bands )
163 std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
164 inputBlocks.emplace_back( std::move( b ) );
168 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
169 for (
int row = 0; row < iterRows; row++ )
174 for (
int col = 0; col < iterCols; col++ )
176 bool noDataInStack =
false;
178 if ( !inputBlocks.empty() )
180 const int position = findPosition( inputBlocks, row, col, noDataInStack );
182 if ( position == -1 || ( noDataInStack && !mIgnoreNoData ) )
187 outputBlock->setValue( row, col, mNoDataValue );
191 outputBlock->setValue( row, col, position );
196 outputBlock->setValue( row, col, mNoDataValue );
200 provider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
202 provider->setEditable(
false );
205 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
206 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
207 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
208 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
209 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
210 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
218QString QgsRasterStackLowestPositionAlgorithm::displayName()
const
220 return QObject::tr(
"Lowest position in raster stack" );
223QString QgsRasterStackLowestPositionAlgorithm::name()
const
225 return QStringLiteral(
"lowestpositioninrasterstack" );
228QStringList QgsRasterStackLowestPositionAlgorithm::tags()
const
230 return QObject::tr(
"cell,lowest,position,pixel,stack" ).split(
',' );
233QString QgsRasterStackLowestPositionAlgorithm::shortHelpString()
const
235 return QObject::tr(
"The lowest position algorithm evaluates on a cell-by-cell basis the position "
236 "of the raster with the lowest value in a stack of rasters. Position counts start "
237 "with 1 and range to the total number of input rasters. The order of the input "
238 "rasters is relevant for the algorithm. If multiple rasters feature the lowest value, "
239 "the first raster will be used for the position value.\n "
240 "If multiband rasters are used in the data raster stack, the algorithm will always "
241 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
242 "Any NoData cells in the raster layer stack will result in a NoData cell "
243 "in the output raster unless the \"ignore NoData\" parameter is checked. "
244 "The output NoData value can be set manually. The output rasters extent and resolution "
245 "is defined by a reference raster layer and is always of int32 type." );
248QgsRasterStackLowestPositionAlgorithm *QgsRasterStackLowestPositionAlgorithm::createInstance()
const
250 return new QgsRasterStackLowestPositionAlgorithm();
253int QgsRasterStackLowestPositionAlgorithm::findPosition( std::vector< std::unique_ptr<QgsRasterBlock> > &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
255 int lowestPosition = 0;
258 const int inputBlocksCount = inputBlocks.size();
259 int currentPosition = 0;
261 double firstValue = mNoDataValue;
262 bool firstValueIsNoData =
true;
264 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
267 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
268 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
270 if ( !firstBlock->isValid() || firstValueIsNoData )
272 noDataInRasterBlockStack =
true;
277 lowestPosition = currentPosition;
282 if ( noDataCount == inputBlocksCount )
284 noDataInRasterBlockStack =
true;
290 while ( currentPosition < inputBlocksCount )
292 std::unique_ptr< QgsRasterBlock > ¤tBlock = inputBlocks.at( currentPosition );
294 bool currentValueIsNoData =
false;
295 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
297 if ( !currentBlock->isValid() || currentValueIsNoData )
299 noDataInRasterBlockStack =
true;
304 if ( currentValue < firstValue )
306 firstValue = currentValue;
307 lowestPosition = currentPosition;
314 return ++lowestPosition;
321QString QgsRasterStackHighestPositionAlgorithm::displayName()
const
323 return QObject::tr(
"Highest position in raster stack" );
326QString QgsRasterStackHighestPositionAlgorithm::name()
const
328 return QStringLiteral(
"highestpositioninrasterstack" );
331QStringList QgsRasterStackHighestPositionAlgorithm::tags()
const
333 return QObject::tr(
"cell,highest,position,pixel,stack" ).split(
',' );
336QString QgsRasterStackHighestPositionAlgorithm::shortHelpString()
const
338 return QObject::tr(
"The highest position algorithm evaluates on a cell-by-cell basis the position "
339 "of the raster with the highest value in a stack of rasters. Position counts start "
340 "with 1 and range to the total number of input rasters. The order of the input "
341 "rasters is relevant for the algorithm. If multiple rasters feature the highest value, "
342 "the first raster will be used for the position value.\n "
343 "If multiband rasters are used in the data raster stack, the algorithm will always "
344 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
345 "Any NoData cells in the raster layer stack will result in a NoData cell "
346 "in the output raster unless the \"ignore NoData\" parameter is checked. "
347 "The output NoData value can be set manually. The output rasters extent and resolution "
348 "is defined by a reference raster layer and is always of int32 type." );
351QgsRasterStackHighestPositionAlgorithm *QgsRasterStackHighestPositionAlgorithm::createInstance()
const
353 return new QgsRasterStackHighestPositionAlgorithm();
356int QgsRasterStackHighestPositionAlgorithm::findPosition( std::vector< std::unique_ptr< QgsRasterBlock> > &inputBlocks,
int &row,
int &col,
bool &noDataInRasterBlockStack )
358 int highestPosition = 0;
361 const int inputBlocksCount = inputBlocks.size();
362 int currentPosition = 0;
364 double firstValue = mNoDataValue;
365 bool firstValueIsNoData =
true;
367 while ( firstValueIsNoData && ( currentPosition < inputBlocksCount ) )
370 std::unique_ptr<QgsRasterBlock> &firstBlock = inputBlocks.at( currentPosition );
371 firstValue = firstBlock->valueAndNoData( row, col, firstValueIsNoData );
373 if ( !firstBlock->isValid() || firstValueIsNoData )
375 noDataInRasterBlockStack =
true;
380 highestPosition = currentPosition;
386 if ( noDataCount == inputBlocksCount )
388 noDataInRasterBlockStack =
true;
394 while ( currentPosition < inputBlocksCount )
396 std::unique_ptr< QgsRasterBlock > ¤tBlock = inputBlocks.at( currentPosition );
398 bool currentValueIsNoData =
false;
399 const double currentValue = currentBlock->valueAndNoData( row, col, currentValueIsNoData );
401 if ( !currentBlock->isValid() || currentValueIsNoData )
403 noDataInRasterBlockStack =
true;
408 if ( currentValue > firstValue )
410 firstValue = currentValue;
411 highestPosition = currentPosition;
418 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...