23 QString QgsRasterSurfaceVolumeAlgorithm::name()
const 25 return QStringLiteral(
"rastersurfacevolume" );
28 QString QgsRasterSurfaceVolumeAlgorithm::displayName()
const 30 return QObject::tr(
"Raster surface volume" );
33 QStringList QgsRasterSurfaceVolumeAlgorithm::tags()
const 35 return QObject::tr(
"sum,volume,area,height,terrain,dem,elevation" ).split(
',' );
38 QString QgsRasterSurfaceVolumeAlgorithm::group()
const 40 return QObject::tr(
"Raster analysis" );
43 QString QgsRasterSurfaceVolumeAlgorithm::groupId()
const 45 return QStringLiteral(
"rasteranalysis" );
48 void QgsRasterSurfaceVolumeAlgorithm::initAlgorithm(
const QVariantMap & )
51 QObject::tr(
"Input layer" ) ) );
53 QObject::tr(
"Band number" ), 1, QStringLiteral(
"INPUT" ) ) );
57 QObject::tr(
"Method" ), QStringList()
58 << QObject::tr(
"Count Only Above Base Level" )
59 << QObject::tr(
"Count Only Below Base Level" )
60 << QObject::tr(
"Subtract Volumes Below Base Level" )
61 << QObject::tr(
"Add Volumes Below Base Level" ) ) );
64 QObject::tr(
"Surface volume report" ), QObject::tr(
"HTML files (*.html)" ), QVariant(),
true ) );
73 QString QgsRasterSurfaceVolumeAlgorithm::shortHelpString()
const 75 return QObject::tr(
"This algorithm calculates the volume under a raster grid's surface.\n\n" 76 "Several methods of volume calculation are available, which control whether " 77 "only values above or below the specified base level are considered, or " 78 "whether volumes below the base level should be added or subtracted from the total volume.\n\n" 79 "The algorithm outputs the calculated volume, the total area, and the total number of pixels analysed. " 80 "If the 'Count Only Above Base Level' or 'Count Only Below Base Level' methods are used, " 81 "then the calculated area and pixel count only includes pixels which are above or below the " 82 "specified base level respectively.\n\n" 83 "Units of the calculated volume are dependent on the coordinate reference system of " 84 "the input raster file. For a CRS in meters, with a DEM height in meters, the calculated " 85 "value will be in meters³. If instead the input raster is in a geographic coordinate system " 86 "(e.g. latitude/longitude values), then the result will be in degrees² × meters, and an " 87 "appropriate scaling factor will need to be applied in order to convert to meters³." );
90 QString QgsRasterSurfaceVolumeAlgorithm::shortDescription()
const 92 return QObject::tr(
"Calculates the volume under a raster grid's surface." );
95 QgsRasterSurfaceVolumeAlgorithm *QgsRasterSurfaceVolumeAlgorithm::createInstance()
const 97 return new QgsRasterSurfaceVolumeAlgorithm();
102 QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT" ), context );
103 int band = parameterAsInt( parameters, QStringLiteral(
"BAND" ), context );
108 mBand = parameterAsInt( parameters, QStringLiteral(
"BAND" ), context );
109 if ( mBand < 1 || mBand > layer->
bandCount() )
110 throw QgsProcessingException( QObject::tr(
"Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand )
115 mLayerWidth = layer->
width();
116 mLayerHeight = layer->
height();
117 mExtent = layer->
extent();
121 mSource = layer->
source();
123 mLevel = parameterAsDouble( parameters, QStringLiteral(
"LEVEL" ), context );
124 mMethod =
static_cast< Method
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
130 QString outputFile = parameterAsFileOutput( parameters, QStringLiteral(
"OUTPUT_HTML_FILE" ), context );
134 std::unique_ptr< QgsFeatureSink > sink;
135 if ( parameters.contains( QStringLiteral(
"OUTPUT_TABLE" ) ) && parameters.value( QStringLiteral(
"OUTPUT_TABLE" ) ).isValid() )
138 outFields.
append(
QgsField( QStringLiteral(
"volume" ), QVariant::Double, QString(), 20, 8 ) );
139 outFields.
append(
QgsField( areaUnit.replace( QStringLiteral(
"²" ), QStringLiteral(
"2" ) ), QVariant::Double, QString(), 20, 8 ) );
140 outFields.
append(
QgsField( QStringLiteral(
"pixel_count" ), QVariant::LongLong ) );
151 int nbBlocksWidth =
static_cast< int >( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
152 int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
153 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
162 std::unique_ptr< QgsRasterBlock > rasterBlock;
163 while ( iter.readNextRasterPart( mBand, iterCols, iterRows, rasterBlock, iterLeft, iterTop ) )
165 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
166 for (
int row = 0; row < iterRows; row++ )
170 for (
int column = 0; column < iterCols; column++ )
172 if ( mHasNoDataValue && rasterBlock->isNoData( row, column ) )
177 const double z = rasterBlock->value( row, column ) - mLevel;
181 case CountOnlyAboveBaseLevel:
189 case CountOnlyBelowBaseLevel:
197 case SubtractVolumesBelowBaseLevel:
202 case AddVolumesBelowBaseLevel:
203 volume += std::fabs( z );
212 double pixelArea = mRasterUnitsPerPixelX * mRasterUnitsPerPixelY;
213 double area = count * pixelArea;
215 if ( !outputFile.isEmpty() )
217 QFile file( outputFile );
218 if ( file.open( QIODevice::WriteOnly | QIODevice::Text ) )
222 QTextStream out( &file );
223 out << QStringLiteral(
"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
224 out << QStringLiteral(
"<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr(
"Analyzed file" ), mSource, QObject::tr(
"band" ) ).arg( mBand );
225 out << QObject::tr(
"<p>%1: %2</p>\n" ).arg( QObject::tr(
"Volume" ), QString::number( volume,
'g', 16 ) );
226 out << QObject::tr(
"<p>%1: %2</p>\n" ).arg( QObject::tr(
"Pixel count" ) ).arg( count );
227 out << QObject::tr(
"<p>%1: %2 %3</p>\n" ).arg( QObject::tr(
"Area" ), QString::number( area,
'g', 16 ), encodedAreaUnit );
228 out << QStringLiteral(
"</body></html>" );
229 outputs.insert( QStringLiteral(
"OUTPUT_HTML_FILE" ), outputFile );
238 outputs.insert( QStringLiteral(
"OUTPUT_TABLE" ), tableDest );
240 outputs.insert( QStringLiteral(
"VOLUME" ), volume );
241 outputs.insert( QStringLiteral(
"AREA" ), area );
242 outputs.insert( QStringLiteral(
"PIXEL_COUNT" ), count );
int width() const
Returns the width of the (unclipped) raster.
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
Base class for providing feedback from a processing algorithm.
Iterator for sequentially processing raster cells.
int bandCount() const
Returns the number of bands in this layer.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis.
QgsRasterInterface * clone() const override=0
Clone itself, create deep copy.
void setProgress(double progress)
Sets the current progress for the feedback object.
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis.
Container of fields for a vector layer.
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
A numeric output for processing algorithms.
A raster band parameter for Processing algorithms.
int height() const
Returns the height of the (unclipped) raster.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
A feature sink output for processing algorithms.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsRasterDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
A raster layer parameter for processing algorithms.
static Q_INVOKABLE QString toAbbreviatedString(QgsUnitTypes::DistanceUnit unit)
Returns a translated abbreviation representing a distance unit.
An enum based parameter for processing algorithms, allowing for selection from predefined values...
static const int DEFAULT_MAXIMUM_TILE_HEIGHT
Default maximum tile height.
Custom exception class for processing related exceptions.
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false) ...
Encapsulate a field in an attribute table or data source.
A numeric parameter for processing algorithms.
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
static QString ampersandEncode(const QString &string)
Makes a raw string safe for inclusion as a HTML/XML string literal.
bool isCanceled() const
Tells whether the operation has been canceled already.
QString source() const
Returns the source for the layer.
This class represents a coordinate reference system (CRS).
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Contains information about the context in which a processing algorithm is executed.
static const int DEFAULT_MAXIMUM_TILE_WIDTH
Default maximum tile width.
static Q_INVOKABLE QgsUnitTypes::AreaUnit distanceToAreaUnit(QgsUnitTypes::DistanceUnit distanceUnit)
Converts a distance unit to its corresponding area unit, e.g., meters to square meters.
void startRasterRead(int bandNumber, int nCols, int nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
QgsCoordinateReferenceSystem crs