22#include <ogrsf_frmts.h>
30using namespace Qt::StringLiterals;
34QStringList QgsChannelNetworkAlgorithmBase::tags()
const
36 return QObject::tr(
"dem,channels,network,basins,drainage,junctions,strahler,hydrology" ).split(
',' );
39void QgsChannelNetworkAlgorithmBase::addCommonParameters()
42 thresholdParam->setHelp(
44 "Minimum Strahler stream order required to initiate a channel segment. Cells with a Strahler order equal to or greater than this threshold will be extracted as channel networks. Output stream "
45 "orders on extracted vector features will be shifted so that the threshold order equals order 1."
48 addParameter( thresholdParam.release() );
50 auto subbasinsParam = std::make_unique<QgsProcessingParameterBoolean>( u
"SUBBASINS"_s, QObject::tr(
"Delineate subbasins" ),
true );
51 subbasinsParam->setHelp(
52 QObject::tr(
"If checked, individual subbasins will be delineated for every channel junction and tributary confluence. If unchecked, only major drainage basins for outer outlet nodes will be generated." )
54 addParameter( subbasinsParam.release() );
61void QgsChannelNetworkAlgorithmBase::extractChannelNetwork(
63 const std::vector<int8_t> &d8Directions,
64 const std::vector<int16_t> &strahlerOrders,
75 const QVariantMap ¶meters
78 const std::size_t totalCells =
static_cast<std::size_t
>( width ) * height;
79 const double cellWidth = extent.
width() / width;
80 const double cellHeight = extent.
height() / height;
82 std::vector<int32_t> nodesGrid( totalCells, 0 );
83 std::vector<int32_t> basinsGrid( totalCells, 0 );
86 multiStepFeedback.setStepWeights( { 1, 1, 1, 0.5, 4 } );
88 for (
int row = 0; row < height; ++row )
90 for (
int col = 0; col < width; ++col )
93 basinsGrid[idx] = demBlock->
isNoData( row, col ) ? 0 : -1;
99 QHash<int, int> basinToOrderMap;
101 auto setNode = [&](
int column,
int row,
int id, NodeType type,
int rawOrder,
int basinId ) {
102 if ( type != NodeType::Mouth )
104 nodesGrid[
static_cast<qgssize>( row ) * width + column] =
id;
107 const int shiftedOrder = rawOrder + 1 - threshold;
108 if ( type == NodeType::Outlet || type == NodeType::Mouth )
110 basinToOrderMap[basinId] = shiftedOrder;
117 QgsRasterAnalysisUtils::pixelToMap( column, row, extent, cellWidth, cellHeight, xWorld, yWorld );
118 const double z = demBlock->
value( row, column );
123 case NodeType::Spring:
124 typeStr = u
"Spring"_s;
126 case NodeType::Junction:
127 typeStr = u
"Junction"_s;
129 case NodeType::Outlet:
130 typeStr = u
"Outlet"_s;
132 case NodeType::Mouth:
133 typeStr = u
"Mouth"_s;
151 multiStepFeedback.setProgressText( QObject::tr(
"Calculating junction nodes and seeding basins" ) );
152 multiStepFeedback.setCurrentStep( 0 );
153 for (
int row = 0; row < height; ++row )
158 multiStepFeedback.setProgress(
static_cast<double>( row ) / height );
160 for (
int col = 0; col < width; ++col )
163 const int order = strahlerOrders[idx];
164 if ( order >= threshold )
166 const int dir = d8Directions[idx];
169 int neighborColumn = 0;
171 if ( QgsRasterAnalysisUtils::neighborCellCoordinates( dir, row, col, neighborRow, neighborColumn, height, width ) )
173 const qgssize neighborIdx =
static_cast<qgssize>( neighborRow ) * width + neighborColumn;
174 if ( nodesGrid[neighborIdx] == 0 && strahlerOrders[neighborIdx] > order && d8Directions[neighborIdx] >= 0 )
176 setNode( neighborColumn, neighborRow, ++nNodes, NodeType::Junction, strahlerOrders[neighborIdx], 0 );
180 for (
int j = 0; j < 8; ++j )
182 const int oppositeJ = ( j + 4 ) % 8;
185 if ( QgsRasterAnalysisUtils::neighborCellCoordinates( oppositeJ, neighborRow, neighborColumn, jRow, jColumn, height, width ) )
187 const qgssize jIdx =
static_cast<qgssize>( jRow ) * width + jColumn;
188 if ( d8Directions[jIdx] == j && strahlerOrders[jIdx] >= threshold )
190 basinsGrid[jIdx] = ++nBasins;
191 setNode( jColumn, jRow, 0, NodeType::Mouth, strahlerOrders[jIdx], nBasins );
199 if ( order == threshold )
201 bool isSpring =
true;
202 for (
int j = 0; j < 8 && isSpring; ++j )
204 const int oppositeJ = ( j + 4 ) % 8;
207 if ( QgsRasterAnalysisUtils::neighborCellCoordinates( oppositeJ, row, col, jRow, jColumn, height, width ) )
209 const qgssize jIdx =
static_cast<qgssize>( jRow ) * width + jColumn;
210 if ( d8Directions[jIdx] == j )
212 isSpring = strahlerOrders[jIdx] < threshold;
219 setNode( col, row, ++nNodes, NodeType::Spring, order, 0 );
225 basinsGrid[idx] = ++nBasins;
226 setNode( col, row, ++nNodes, NodeType::Outlet, order, nBasins );
232 multiStepFeedback.setProgressText( QObject::tr(
"Calculating drainage basins" ) );
233 multiStepFeedback.setCurrentStep( 1 );
234 auto getBasin = [&](
int startColumn,
int startRow ) {
235 int currentColumn = startColumn;
236 int currentRow = startRow;
237 qgssize currentIdx =
static_cast<qgssize>( currentRow ) * width + currentColumn;
238 int basin = basinsGrid[currentIdx];
242 std::vector<std::size_t> stack;
245 const int dir = d8Directions[currentIdx];
249 stack.push_back( currentIdx );
251 int neighborColumn = 0;
253 if ( !QgsRasterAnalysisUtils::neighborCellCoordinates( dir, currentRow, currentColumn, neighborRow, neighborColumn, height, width ) )
256 currentColumn = neighborColumn;
257 currentRow = neighborRow;
258 currentIdx =
static_cast<qgssize>( currentRow ) * width + currentColumn;
259 basin = basinsGrid[currentIdx];
270 basinsGrid[currentIdx] = basin;
272 for (
const std::size_t idx : stack )
274 basinsGrid[idx] = basin;
280 for (
int row = 0; row < height; ++row )
285 multiStepFeedback.setProgress(
static_cast<double>( row ) / height );
287 for (
int col = 0; col < width; ++col )
289 getBasin( col, row );
296 multiStepFeedback.setProgressText( QObject::tr(
"Extracting basins as polygons" ) );
297 multiStepFeedback.setCurrentStep( 2 );
301 GDALDriverH hMemDriver = GDALGetDriverByName(
"MEM" );
305 GDALDatasetH hMemDS = GDALCreate( hMemDriver,
"", width, height, 1, GDT_Int32,
nullptr );
307 throw QgsProcessingException( QObject::tr(
"Could not create in-memory GDAL dataset for basin polygonization." ) );
309 double adfGeoTransform[6] = { extent.
xMinimum(), cellWidth, 0.0, extent.
yMaximum(), 0.0, -cellHeight };
310 GDALSetGeoTransform( hMemDS, adfGeoTransform );
312 GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, 1 );
313 GDALSetRasterNoDataValue( hBand, 0 );
315 const CPLErr writeErr = GDALRasterIO( hBand, GF_Write, 0, 0, width, height,
const_cast<int32_t *
>( basinsGrid.data() ), width, height, GDT_Int32, 0, 0 );
316 if ( writeErr != CE_None )
323 GDALDriverH hOgrMemDriver = GDALGetDriverByName(
"Memory" );
324 if ( !hOgrMemDriver )
330 GDALDatasetH hOgrDS = GDALCreate( hOgrMemDriver,
"", 0, 0, 0, GDT_Unknown,
nullptr );
331 OGRLayerH hLayer = GDALDatasetCreateLayer( hOgrDS,
"basins",
nullptr, wkbPolygon,
nullptr );
334 OGRFieldDefnH hFieldDefn = OGR_Fld_Create(
"VALUE", OFTInteger );
335 OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
336 OGR_Fld_Destroy( hFieldDefn );
340 struct GdalProgressData
342 QgsProcessingFeedback *feedback =
nullptr;
343 } progressData { &multiStepFeedback };
345 auto gdalProgressCallback = [](
double dfComplete,
const char *,
void *pProgressArg ) ->
int CPL_STDCALL {
348 GdalProgressData *data =
static_cast<GdalProgressData *
>( pProgressArg );
349 if ( data->feedback )
351 if ( data->feedback->isCanceled() )
354 data->feedback->setProgress( dfComplete );
360 char **papszOptions =
nullptr;
361 papszOptions = CSLSetNameValue( papszOptions,
"8CONNECTED",
"8" );
363 const CPLErr polyErr = GDALPolygonize( hBand,
nullptr, hLayer, 0, papszOptions, gdalProgressCallback, &progressData );
364 CSLDestroy( papszOptions );
366 if ( polyErr != CE_None || feedback->
isCanceled() )
373 const GIntBig totalFeatures = OGR_L_GetFeatureCount( hLayer, TRUE );
374 GIntBig featureIdx = 0;
377 OGR_L_ResetReading( hLayer );
378 OGRFeatureH hFeat =
nullptr;
379 multiStepFeedback.setCurrentStep( 3 );
380 while ( ( hFeat = OGR_L_GetNextFeature( hLayer ) ) !=
nullptr )
385 OGR_F_Destroy( hFeat );
391 multiStepFeedback.setProgress(
static_cast<double>( featureIdx ) / totalFeatures );
393 const int basinId = OGR_F_GetFieldAsInteger( hFeat, 0 );
397 OGRGeometryH hGeom = OGR_F_GetGeometryRef( hFeat );
403 const double area = qGeom.
area();
404 const double perimeter = qGeom.
length();
405 const int basinOrder = basinToOrderMap.value( basinId, 0 );
414 OGR_F_Destroy( hFeat );
421 multiStepFeedback.setProgressText( QObject::tr(
"Vectorizing channel lines" ) );
422 multiStepFeedback.setCurrentStep( 4 );
425 int segmentCount = 0;
426 for (
int row = 0; row < height; ++row )
431 multiStepFeedback.setProgress(
static_cast<double>( row ) / height );
433 for (
int column = 0; column < width; ++column )
436 if ( nodesGrid[idx] > 0 )
438 int currentColumn = column;
439 int currentRow = row;
440 std::size_t currentIdx = idx;
441 int dir = d8Directions[currentIdx];
444 const int nodeA = nodesGrid[idx];
445 const int basin = basinsGrid[idx];
446 const int rawOrder = strahlerOrders[idx];
447 const int shiftedOrder = rawOrder + 1 - threshold;
449 auto line = std::make_unique<QgsLineString>();
453 QgsRasterAnalysisUtils::pixelToMap( currentColumn, currentRow, extent, cellWidth, cellHeight, xWorld, yWorld );
454 double z = demBlock->
value( currentRow, currentColumn );
455 line->addVertex(
QgsPoint( xWorld, yWorld, z ) );
460 int neighborColumn = 0;
462 if ( !QgsRasterAnalysisUtils::neighborCellCoordinates( dir, currentRow, currentColumn, neighborRow, neighborColumn, height, width ) )
465 currentColumn = neighborColumn;
466 currentRow = neighborRow;
467 currentIdx =
static_cast<qgssize>( currentRow ) * width + currentColumn;
469 QgsRasterAnalysisUtils::pixelToMap( currentColumn, currentRow, extent, cellWidth, cellHeight, xWorld, yWorld );
470 z = demBlock->
value( currentRow, currentColumn );
471 line->addVertex(
QgsPoint( xWorld, yWorld, z ) );
473 if ( nodesGrid[currentIdx] > 0 )
475 nodeB = nodesGrid[currentIdx];
479 dir = d8Directions[currentIdx];
483 const double length = lineGeom.length();
503QgsFields QgsChannelNetworkAlgorithmBase::channelFields()
506 channelFields.
append(
QgsField( u
"SEGMENT_ID"_s, QMetaType::Type::Int ) );
507 channelFields.
append(
QgsField( u
"NODE_A"_s, QMetaType::Type::Int ) );
508 channelFields.
append(
QgsField( u
"NODE_B"_s, QMetaType::Type::Int ) );
509 channelFields.
append(
QgsField( u
"BASIN"_s, QMetaType::Type::Int ) );
510 channelFields.
append(
QgsField( u
"ORDER"_s, QMetaType::Type::Int ) );
511 channelFields.
append(
QgsField( u
"ORDER_CELL"_s, QMetaType::Type::Int ) );
512 channelFields.
append(
QgsField( u
"LENGTH"_s, QMetaType::Type::Double ) );
513 return channelFields;
516QgsFields QgsChannelNetworkAlgorithmBase::basinFields()
519 basinFields.
append(
QgsField( u
"VALUE"_s, QMetaType::Type::Int ) );
520 basinFields.
append(
QgsField( u
"AREA"_s, QMetaType::Type::Double ) );
521 basinFields.
append(
QgsField( u
"PERIMETER"_s, QMetaType::Type::Double ) );
522 basinFields.
append(
QgsField( u
"ORDER"_s, QMetaType::Type::Int ) );
526QgsFields QgsChannelNetworkAlgorithmBase::junctionFields()
529 junctionFields.
append(
QgsField( u
"ID"_s, QMetaType::Type::Int ) );
530 junctionFields.
append(
QgsField( u
"TYPE"_s, QMetaType::Type::QString ) );
531 junctionFields.
append(
QgsField( u
"ORDER"_s, QMetaType::Type::Int ) );
532 junctionFields.
append(
QgsField( u
"BASIN"_s, QMetaType::Type::Int ) );
533 return junctionFields;
540QString QgsChannelNetworkFromDemAlgorithm::name()
const
542 return u
"channelnetworkfromdem"_s;
545QString QgsChannelNetworkFromDemAlgorithm::displayName()
const
547 return QObject::tr(
"Channel network and drainage basins from DEM" );
550QString QgsChannelNetworkFromDemAlgorithm::shortDescription()
const
552 return QObject::tr(
"Calculates channel network lines, drainage basin polygons, and junction nodes directly from an elevation raster (DEM)." );
555QString QgsChannelNetworkFromDemAlgorithm::shortHelpString()
const
558 "This algorithm extracts vector channel network lines, drainage basin polygons, and topological junction node points directly from an elevation raster (DEM).\n\n"
559 "The analysis executes a 3-step pipeline:\n"
560 "1. D8 Flow Routing: Computes single-direction steepest descent flow directions.\n"
561 "2. Strahler Stream Ordering: Calculates topological stream orders.\n"
562 "3. Vector Network Extraction: Traces vector channels, delineates catchments, and identifies key topological junction nodes.\n\n"
563 "The output Junctions layer contains topological nodes from the channel network. These are classified according to type:\n"
564 "• Spring: Channel headwater initiation point matching the stream order threshold.\n"
565 "• Junction: Tributary confluence point where two or more stream channels meet.\n"
566 "• Outlet: Terminal discharge node exiting the raster boundary or draining into a terrain sink.\n"
567 "• Mouth: Confluence pour point entering a higher-order stream segment (delineated when subbasins are enabled).\n\n"
568 "This algorithm is a port of SAGA's 'Channel Network and Drainage Basins' tool."
572void QgsChannelNetworkFromDemAlgorithm::initAlgorithm(
const QVariantMap & )
575 addCommonParameters();
580 return new QgsChannelNetworkFromDemAlgorithm();
585 QgsRasterLayer *layer = parameterAsRasterLayer( parameters, u
"INPUT"_s, context );
590 mLayerWidth = layer->
width();
591 mLayerHeight = layer->
height();
592 mExtent = layer->
extent();
602 QGS_MARK_ALGORITHM_SOURCE
604 const int threshold = parameterAsInt( parameters, u
"THRESHOLD"_s, context );
605 const bool subbasins = parameterAsBool( parameters, u
"SUBBASINS"_s, context );
607 std::unique_ptr<QgsRasterBlock> demBlock( mDemInterface->block( 1, mExtent, mLayerWidth, mLayerHeight ) );
611 const qgssize totalCells =
static_cast<qgssize>( mLayerWidth ) * mLayerHeight;
613 multiStepFeedback.setStepWeights( { 1, 1, 10 } );
615 multiStepFeedback.setCurrentStep( 0 );
616 multiStepFeedback.setProgressText( QObject::tr(
"Calculating flow direction" ) );
617 std::vector<int8_t> d8Directions( totalCells, -1 );
618 for (
int row = 0; row < mLayerHeight; ++row )
620 if ( multiStepFeedback.isCanceled() )
623 multiStepFeedback.setProgress( 100.0 *
static_cast<double>( row ) / mLayerHeight );
624 const qgssize rowOffset =
static_cast<qgssize>( row ) * mLayerWidth;
625 for (
int col = 0; col < mLayerWidth; ++col )
627 const int dir = QgsRasterAnalysisUtils::steepestGradientDirection( demBlock.get(), row, col, mCellSizeX, mCellSizeY,
true,
true );
628 d8Directions[rowOffset + col] =
static_cast<int8_t
>( dir );
632 multiStepFeedback.setProgressText( QObject::tr(
"Calculating Strahler stream orders" ) );
633 multiStepFeedback.setCurrentStep( 1 );
634 std::vector<int16_t> strahlerOrders( totalCells, 0 );
635 computeStrahlerOrder( demBlock.get(), d8Directions, mLayerWidth, mLayerHeight, 1, strahlerOrders.
data(), &multiStepFeedback, -1 );
636 if ( multiStepFeedback.isCanceled() )
639 multiStepFeedback.setCurrentStep( 2 );
641 QString channelsDest;
642 std::unique_ptr<QgsFeatureSink> channelSink;
645 channelSink.reset( parameterAsSink( parameters, u
"CHANNELS"_s, context, channelsDest, channelFields(),
Qgis::WkbType::LineStringZ, mCrs ) );
653 std::unique_ptr<QgsFeatureSink> basinSink;
656 basinSink.reset( parameterAsSink( parameters, u
"BASINS"_s, context, basinsDest, basinFields(),
Qgis::WkbType::Polygon, mCrs ) );
663 QString junctionsDest;
664 std::unique_ptr<QgsFeatureSink> junctionSink;
667 junctionSink.reset( parameterAsSink( parameters, u
"JUNCTIONS"_s, context, junctionsDest, junctionFields(),
Qgis::WkbType::PointZ, mCrs ) );
674 extractChannelNetwork( demBlock.get(), d8Directions, strahlerOrders, mLayerWidth, mLayerHeight, mExtent, mCrs, threshold, subbasins, channelSink.get(), basinSink.get(), junctionSink.get(), &multiStepFeedback, parameters );
678 channelSink->finalize();
683 basinSink->finalize();
688 junctionSink->finalize();
694 outputs.insert( u
"CHANNELS"_s, channelsDest );
696 outputs.insert( u
"BASINS"_s, basinsDest );
698 outputs.insert( u
"JUNCTIONS"_s, junctionsDest );
706QString QgsChannelNetworkFromFlowDirAndOrderAlgorithm::name()
const
708 return u
"channelnetworkfromflowdirandorder"_s;
711QString QgsChannelNetworkFromFlowDirAndOrderAlgorithm::displayName()
const
713 return QObject::tr(
"Channel network and drainage basins from multiple inputs" );
716QString QgsChannelNetworkFromFlowDirAndOrderAlgorithm::shortDescription()
const
718 return QObject::tr(
"Calculates channel network lines, drainage basin polygons, and junction nodes using DEM, flow direction, and Strahler order rasters." );
721QString QgsChannelNetworkFromFlowDirAndOrderAlgorithm::shortHelpString()
const
724 "This algorithm extracts vector channel network lines, drainage basin polygons, and topological junction node points using pre-computed elevation (DEM), D8 flow direction, and Strahler stream "
726 "This variant bypasses internal raster flow routing and stream order generation, making it ideal when flow direction and Strahler order rasters have already been computed in prior processing "
728 "The output Junctions layer contains topological nodes from the channel network. These are classified according to type:\n"
729 "• Spring: Channel headwater initiation point matching the stream order threshold.\n"
730 "• Junction: Tributary confluence point where two or more stream channels meet.\n"
731 "• Outlet: Terminal discharge node exiting the raster boundary or draining into a terrain sink.\n"
732 "• Mouth: Confluence pour point entering a higher-order stream segment (delineated when subbasins are enabled).\n\n"
733 "This algorithm is a port of SAGA's 'Channel Network and Drainage Basins' tool."
737void QgsChannelNetworkFromFlowDirAndOrderAlgorithm::initAlgorithm(
const QVariantMap & )
742 addCommonParameters();
747 return new QgsChannelNetworkFromFlowDirAndOrderAlgorithm();
752 QgsRasterLayer *demLayer = parameterAsRasterLayer( parameters, u
"INPUT_DEM"_s, context );
756 QgsRasterLayer *flowDirLayer = parameterAsRasterLayer( parameters, u
"INPUT_FLOW_DIR"_s, context );
760 QgsRasterLayer *strahlerLayer = parameterAsRasterLayer( parameters, u
"INPUT_STRAHLER"_s, context );
767 mLayerWidth = demLayer->
width();
768 mLayerHeight = demLayer->
height();
769 mExtent = demLayer->
extent();
770 mCrs = demLayer->
crs();
777 QGS_MARK_ALGORITHM_SOURCE
779 const int threshold = parameterAsInt( parameters, u
"THRESHOLD"_s, context );
780 const bool subbasins = parameterAsBool( parameters, u
"SUBBASINS"_s, context );
782 std::unique_ptr<QgsRasterBlock> demBlock( mDemInterface->block( 1, mExtent, mLayerWidth, mLayerHeight ) );
786 std::unique_ptr<QgsRasterBlock> flowDirBlock( mFlowDirInterface->block( 1, mExtent, mLayerWidth, mLayerHeight ) );
790 std::unique_ptr<QgsRasterBlock> strahlerBlock( mStrahlerInterface->block( 1, mExtent, mLayerWidth, mLayerHeight ) );
791 if ( !strahlerBlock )
794 const qgssize totalCells =
static_cast<qgssize>( mLayerWidth ) * mLayerHeight;
796 std::vector<int8_t> d8Directions( totalCells, -1 );
797 std::vector<int16_t> strahlerOrders( totalCells, 0 );
799 for (
int row = 0; row < mLayerHeight; ++row )
804 const qgssize rowOffset =
static_cast<qgssize>( row ) * mLayerWidth;
805 for (
int col = 0; col < mLayerWidth; ++col )
807 const std::size_t idx = rowOffset + col;
808 if ( !flowDirBlock->isNoData( row, col ) )
810 d8Directions[idx] =
static_cast<int8_t
>( flowDirBlock->value( row, col ) );
812 if ( !strahlerBlock->isNoData( row, col ) )
814 strahlerOrders[idx] =
static_cast<int16_t
>( strahlerBlock->value( row, col ) );
819 QString channelsDest;
820 std::unique_ptr<QgsFeatureSink> channelSink;
823 channelSink.reset( parameterAsSink( parameters, u
"CHANNELS"_s, context, channelsDest, channelFields(),
Qgis::WkbType::LineStringZ, mCrs ) );
831 std::unique_ptr<QgsFeatureSink> basinSink;
834 basinSink.reset( parameterAsSink( parameters, u
"BASINS"_s, context, basinsDest, basinFields(),
Qgis::WkbType::Polygon, mCrs ) );
841 QString junctionsDest;
842 std::unique_ptr<QgsFeatureSink> junctionSink;
845 junctionSink.reset( parameterAsSink( parameters, u
"JUNCTIONS"_s, context, junctionsDest, junctionFields(),
Qgis::WkbType::PointZ, mCrs ) );
852 extractChannelNetwork( demBlock.get(), d8Directions, strahlerOrders, mLayerWidth, mLayerHeight, mExtent, mCrs, threshold, subbasins, channelSink.get(), basinSink.get(), junctionSink.get(), feedback, parameters );
856 channelSink->finalize();
861 basinSink->finalize();
866 junctionSink->finalize();
872 outputs.insert( u
"CHANNELS"_s, channelsDest );
874 outputs.insert( u
"BASINS"_s, basinsDest );
876 outputs.insert( u
"JUNCTIONS"_s, junctionsDest );
@ VectorPoint
Vector point layers.
@ VectorPolygon
Vector polygon layers.
@ VectorLine
Vector line layers.
@ LineStringZ
LineStringZ.
Represents a coordinate reference system (CRS).
An interface for objects which accept features via addFeature(s) methods.
virtual bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags())
Adds a single feature to the sink.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
A geometry is the spatial representation of a feature.
double length() const
Returns the planar, 2-dimensional length of geometry.
double area() const
Returns the planar, 2-dimensional area of the geometry.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
virtual Q_INVOKABLE QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
static QgsGeometry ogrGeometryToQgsGeometry(OGRGeometryH geom)
Converts an OGR geometry representation to a QgsGeometry object.
Point geometry type, with support for z-dimension and m-values.
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.
void featureAddedToSink(const QString &output)
Reports that a feature was added to the the sink associated with the specified algorithm output.
void featureSinkFinalized(const QString &output)
Reports that a feature sink has been finalized.
Processing feedback object for multi-step operations.
A raster layer parameter for processing algorithms.
A vector layer destination parameter, for specifying the destination path for a vector layer created ...
double value(int row, int column) const
Read a single value if type of block is numeric.
QByteArray data() const
Gets access to raw data.
bool isNoData(int row, int column) const
Checks if value at position is no data.
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.
A rectangle specified with double values.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
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...