26using namespace Qt::StringLiterals;
30QString QgsFlowDirectionD8Algorithm::name()
const
32 return u
"flowdirection"_s;
35QString QgsFlowDirectionD8Algorithm::displayName()
const
37 return QObject::tr(
"Flow direction" );
40QStringList QgsFlowDirectionD8Algorithm::tags()
const
42 return QObject::tr(
"dem,flow,direction,d8,steepest,hydrology,catchment,drainage" ).split(
',' );
45QString QgsFlowDirectionD8Algorithm::group()
const
47 return QObject::tr(
"Raster terrain analysis" );
50QString QgsFlowDirectionD8Algorithm::groupId()
const
52 return u
"rasterterrainanalysis"_s;
55QString QgsFlowDirectionD8Algorithm::shortDescription()
const
57 return QObject::tr(
"Calculates single-direction D8 flow directions from a digital elevation model." );
60QString QgsFlowDirectionD8Algorithm::shortHelpString()
const
63 "This algorithm calculates deterministic 8 (D8) flow directions for each cell in an input elevation raster (DEM).\n\n"
64 "Flow direction values are output as 8-neighbor directional indices numbered clockwise starting from North:\n"
65 "0 = North, 1 = North-East, 2 = East, 3 = South-East, 4 = South, 5 = South-West, 6 = West, 7 = North-West.\n\n"
66 "Sink/pit cells are assigned a value of -1 in the output, and flat areas are assigned -2.\n\n"
67 "Cells with no downslope neighbor or NoData elevation values are assigned nodata in the output.\n\n"
68 "This algorithm is a port of the flow direction calculation from SAGA 'Channel Network and Drainage Basins' tool."
72QList<QgsAcademicReference> QgsFlowDirectionD8Algorithm::academicReferences()
const
75 createJournalArticle( { u
"O'Callaghan, J. F."_s, u
"Mark, D. M."_s }, 1984, u
"The extraction of drainage networks from digital elevation data"_s, u
"Computer Vision, Graphics and Image Processing"_s, u
"28"_s, QString(), u
"323-344"_s );
76 return { ocallaghanReference };
79QList<QgsProcessingAlgorithm::ExternalLink> QgsFlowDirectionD8Algorithm::externalLinks()
const
82 QgsProcessingAlgorithm::ExternalLink { QObject::tr(
"SAGA tool source code" ), u
"https://sourceforge.net/p/saga-gis/code/ci/33d1062b7120c696c9dd258378c48d86dc33560c/tree/saga-gis/src/tools/terrain_analysis/ta_channels/D8_Flow_Analysis.cpp"_s }
86void QgsFlowDirectionD8Algorithm::initAlgorithm(
const QVariantMap & )
91 outputNodataParam->setHelp( QObject::tr(
"The NODATA value to use in the output raster." ) );
93 addParameter( outputNodataParam.release() );
95 auto creationOptsParam = std::make_unique<QgsProcessingParameterString>( u
"CREATION_OPTIONS"_s, QObject::tr(
"Creation options" ), QVariant(),
false,
true );
96 creationOptsParam->setHelp( QObject::tr(
"The raster creation options for the output raster. These options control things like colorimetry, compression, etc." ) );
97 creationOptsParam->setMetadata( QVariantMap( { { u
"widget_wrapper"_s, QVariantMap( { { u
"widget_type"_s, u
"rasteroptions"_s } } ) } } ) );
99 addParameter( creationOptsParam.release() );
101 auto outputParam = std::make_unique<QgsProcessingParameterRasterDestination>( u
"OUTPUT"_s, QObject::tr(
"Flow direction" ) );
102 addParameter( outputParam.release() );
107 return new QgsFlowDirectionD8Algorithm();
112 QgsRasterLayer *layer = parameterAsRasterLayer( parameters, u
"INPUT"_s, context );
117 mLayerWidth = layer->
width();
118 mLayerHeight = layer->
height();
119 mExtent = layer->
extent();
129 QGS_MARK_ALGORITHM_SOURCE
131 const QString creationOptions = parameterAsString( parameters, u
"CREATION_OPTIONS"_s, context ).trimmed();
132 const QString outputPath = parameterAsOutputLayer( parameters, u
"OUTPUT"_s, context );
133 const QString outputFormat = parameterAsOutputRasterFormat( parameters, u
"OUTPUT"_s, context );
134 const int outputNoData = parameterAsInt( parameters, u
"NODATA"_s, context );
136 std::unique_ptr<QgsRasterBlock> inputBlock( mInterface->block( 1, mExtent, mLayerWidth, mLayerHeight ) );
140 auto outputBlock = std::make_unique<QgsRasterBlock>(
Qgis::DataType::Int16, mLayerWidth, mLayerHeight );
141 outputBlock->setNoDataValue( outputNoData );
143 int16_t *outData =
reinterpret_cast<int16_t *
>( outputBlock->bits() );
146 for (
int row = 0; row < mLayerHeight; ++row )
151 feedback->
setProgress( 100.0 *
static_cast<double>( row ) / mLayerHeight );
153 const std::size_t rowOffset =
static_cast<std::size_t
>( row ) * mLayerWidth;
154 for (
int col = 0; col < mLayerWidth; ++col )
156 const int dir = QgsRasterAnalysisUtils::steepestGradientDirection( inputBlock.get(), row, col, mCellSizeX, mCellSizeY,
true,
true );
157 outData[rowOffset + col] = dir == -3 ? outputNoData :
static_cast<int16_t
>( dir );
161 auto outputWriter = std::make_unique<QgsRasterFileWriter>( outputPath );
162 outputWriter->setOutputProviderKey( u
"gdal"_s );
163 if ( !creationOptions.isEmpty() )
165 outputWriter->setCreationOptions( creationOptions.split(
'|' ) );
167 outputWriter->setOutputFormat( outputFormat );
169 std::unique_ptr<QgsRasterDataProvider> destProvider( outputWriter->createOneBandRaster(
Qgis::DataType::Int16, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
172 if ( !destProvider->isValid() )
175 destProvider->setNoDataValue( 1, outputNoData );
176 destProvider->setEditable(
true );
178 if ( !destProvider->writeBlock( outputBlock.get(), 1 ) )
180 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( destProvider->error().summary() ) );
183 destProvider->setEditable(
false );
186 outputs.insert( u
"OUTPUT"_s, outputPath );
@ Int16
Sixteen bit signed integer (qint16).
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
Encapsulates an academic reference and formats it according to style guidelines.
static QgsAcademicReference createJournalArticle(const QStringList &authors, int year, const QString &title, const QString &journal, const QString &volume=QString(), const QString &issue=QString(), const QString &pages=QString())
Creates a journal article reference.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
virtual Q_INVOKABLE QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
Abstract base class for processing algorithms.
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
A raster layer parameter for processing algorithms.
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
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.
Encapsulates details of an external link describing an algorithm's behavior or source.