diff --git a/python/plugins/processing/tests/testdata/expected/raster_unique_values_count.html b/python/plugins/processing/tests/testdata/expected/raster_unique_values_count.html deleted file mode 100644 index 8f633e44d44..00000000000 --- a/python/plugins/processing/tests/testdata/expected/raster_unique_values_count.html +++ /dev/null @@ -1,25 +0,0 @@ - -

Analyzed file: /home/webmaster/dev/cpp/QGIS/python/plugins/processing/tests/testdata/raster.tif (band 1)

-

Total cell count: 224

-

NODATA count: 104

- - - - - - - - - - - - - - - - - - - -
ValueCount
8264
8376
8436
8454
8519
8536
85910
8614
8646
8669
8686
8724
8739
8786
8806
8816
89013
8996
- \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/raster_unique_values_report.html b/python/plugins/processing/tests/testdata/expected/raster_unique_values_report.html new file mode 100644 index 00000000000..953c9d7cbf3 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/raster_unique_values_report.html @@ -0,0 +1,29 @@ + +

Analyzed file: /home/webmaster/dev/cpp/QGIS/python/plugins/processing/tests/testdata/raster.tif (band 1)

+

Extent: 270736.0673250681720674,4458888.9563983473926783 : 270899.8544675338780507,4459029.5745217483490705

+

Projection: ED50 / UTM zone 30N (EPSG:23030)

+

Width in pixels: 16 (units per pixel 10.2367)

+

Height in pixels: 14 (units per pixel 10.0442)

+

Total pixel count: 224

+

NODATA pixel count: 104

+ + + + + + + + + + + + + + + + + + + +
ValuePixel countArea (m²)
8264411.2757251916548
8376616.9135877874822
8436616.9135877874822
8454411.2757251916548
8519925.3703816812233
8536616.9135877874822
859101028.189312979137
8614411.2757251916548
8646616.9135877874822
8669925.3703816812233
8686616.9135877874822
8724411.2757251916548
8739925.3703816812233
8786616.9135877874822
8806616.9135877874822
8816616.9135877874822
890131336.646106872878
8996616.9135877874822
+ \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml index a148fb6cfba..168c36601c3 100755 --- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml +++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml @@ -3236,8 +3236,8 @@ tests: - 'Standard deviation: 43.9618116337985' - 'Sum of the squares: 252304334.52061242' - - algorithm: qgis:rasterlayeruniquevaluescount - name: Raster layer unique values count + - algorithm: qgis:rasterlayeruniquevaluesreport + name: Raster layer unique values report params: INPUT: name: raster.tif @@ -3248,26 +3248,26 @@ tests: name: raster_unique_values_count.html type: regex rules: - - 'Total cell count: 224' - - 'NODATA count: 104' - - '8264' - - '8376' - - '8436' - - '8454' - - '8519' - - '8536' - - '85910' - - '8614' - - '8646' - - '8669' - - '8686' - - '8724' - - '8739' - - '8786' - - '8806' - - '8816' - - '89013' - - '8996' + - 'Total pixel count: 224' + - 'NODATA pixel count: 104' + - '8264411.2757251916548' + - '8376616.9135877874822' + - '8436616.9135877874822' + - '8454411.2757251916548' + - '8519925.3703816812233' + - '8536616.9135877874822' + - '859101028.189312979137' + - '8614411.2757251916548' + - '8646616.9135877874822' + - '8669925.3703816812233' + - '8686616.9135877874822' + - '8724411.2757251916548' + - '8739925.3703816812233' + - '8786616.9135877874822' + - '8806616.9135877874822' + - '8816616.9135877874822' + - '890131336.646106872878' + - '8996616.9135877874822' - algorithm: qgis:pointsdisplacement name: Point displacement diff --git a/src/core/processing/qgsnativealgorithms.cpp b/src/core/processing/qgsnativealgorithms.cpp index 9bb9bbcc41c..755cd885243 100644 --- a/src/core/processing/qgsnativealgorithms.cpp +++ b/src/core/processing/qgsnativealgorithms.cpp @@ -89,7 +89,7 @@ void QgsNativeAlgorithms::loadAlgorithms() addAlgorithm( new QgsLineIntersectionAlgorithm() ); addAlgorithm( new QgsSplitWithLinesAlgorithm() ); addAlgorithm( new QgsMeanCoordinatesAlgorithm() ); - addAlgorithm( new QgsRasterLayerUniqueValuesCountAlgorithm() ); + addAlgorithm( new QgsRasterLayerUniqueValuesReportAlgorithm() ); } void QgsSaveSelectedFeatures::initAlgorithm( const QVariantMap & ) @@ -2589,28 +2589,36 @@ QVariantMap QgsMeanCoordinatesAlgorithm::processAlgorithm( const QVariantMap &pa } -void QgsRasterLayerUniqueValuesCountAlgorithm::initAlgorithm( const QVariantMap & ) +void QgsRasterLayerUniqueValuesReportAlgorithm::initAlgorithm( const QVariantMap & ) { addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) ); addParameter( new QgsProcessingParameterBand( QStringLiteral( "BAND" ), QObject::tr( "Band number" ), 1, QStringLiteral( "INPUT" ) ) ); addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT_HTML_FILE" ), - QObject::tr( "Unique values count" ), QObject::tr( "HTML files (*.html)" ), QVariant(), true ) ); - addOutput( new QgsProcessingOutputHtml( QStringLiteral( "OUTPUT_HTML_FILE" ), QObject::tr( "Unique values count" ) ) ); + QObject::tr( "Unique values report" ), QObject::tr( "HTML files (*.html)" ), QVariant(), true ) ); + + addOutput( new QgsProcessingOutputHtml( QStringLiteral( "OUTPUT_HTML_FILE" ), QObject::tr( "Unique values report" ) ) ); + + addOutput( new QgsProcessingOutputString( QStringLiteral( "EXTENT" ), QObject::tr( "Extent" ) ) ); + addOutput( new QgsProcessingOutputString( QStringLiteral( "CRS_AUTHID" ), QObject::tr( "CRS authority identifier" ) ) ); + addOutput( new QgsProcessingOutputNumber( QStringLiteral( "WIDTH_IN_PIXELS" ), QObject::tr( "Width in pixels" ) ) ); + addOutput( new QgsProcessingOutputNumber( QStringLiteral( "HEIGHT_IN_PIXELS" ), QObject::tr( "Height in pixels" ) ) ); + addOutput( new QgsProcessingOutputNumber( QStringLiteral( "TOTAL_PIXEL_COUNT" ), QObject::tr( "Total pixel count" ) ) ); + addOutput( new QgsProcessingOutputNumber( QStringLiteral( "NODATA_PIXEL_COUNT" ), QObject::tr( "NODATA pixel count" ) ) ); } -QString QgsRasterLayerUniqueValuesCountAlgorithm::shortHelpString() const +QString QgsRasterLayerUniqueValuesReportAlgorithm::shortHelpString() const { - return QObject::tr( "This algorithm returns the count of each unique value in a given raster layer." ); + return QObject::tr( "This algorithm returns the count and area of each unique value in a given raster layer." ); } -QgsRasterLayerUniqueValuesCountAlgorithm *QgsRasterLayerUniqueValuesCountAlgorithm::createInstance() const +QgsRasterLayerUniqueValuesReportAlgorithm *QgsRasterLayerUniqueValuesReportAlgorithm::createInstance() const { - return new QgsRasterLayerUniqueValuesCountAlgorithm(); + return new QgsRasterLayerUniqueValuesReportAlgorithm(); } -QVariantMap QgsRasterLayerUniqueValuesCountAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) +QVariantMap QgsRasterLayerUniqueValuesReportAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT" ), context ); int band = parameterAsInt( parameters, QStringLiteral( "BAND" ), context ); @@ -2652,22 +2660,37 @@ QVariantMap QgsRasterLayerUniqueValuesCountAlgorithm::processAlgorithm( const QV } QVariantMap outputs; + outputs.insert( QStringLiteral( "EXTENT" ), layer->extent().toString() ); + outputs.insert( QStringLiteral( "CRS_AUTHID" ), layer->crs().authid() ); + outputs.insert( QStringLiteral( "WIDTH_IN_PIXELS" ), width ); + outputs.insert( QStringLiteral( "HEIGHT_IN_PIXELS" ), height ); + outputs.insert( QStringLiteral( "TOTAL_PIXEL_COUNT" ), width * height ); + outputs.insert( QStringLiteral( "NODATA_PIXEL_COUNT" ), noDataCount ); + if ( !outputFile.isEmpty() ) { QFile file( outputFile ); if ( file.open( QIODevice::WriteOnly | QIODevice::Text ) ) { + QString areaUnit = QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::distanceToAreaUnit( layer->crs().mapUnits() ) ); + double cellArea = layer->rasterUnitsPerPixelX() * layer->rasterUnitsPerPixelY(); + QTextStream out( &file ); out << QString( "\n" ); - out << QObject::tr( "

Analyzed file: %1 (band %2)

\n" ).arg( layer->source() ).arg( band ); - out << QObject::tr( "

Total cell count: %1

\n" ).arg( width * height ); + out << QString( "

%1: %2 (%3 %4)

\n" ).arg( QObject::tr( "Analyzed file" ) ).arg( layer->source() ).arg( QObject::tr( "band" ) ).arg( band ); + out << QObject::tr( "

%1: %2

\n" ).arg( QObject::tr( "Extent" ) ).arg( layer->extent().toString() ); + out << QObject::tr( "

%1: %2 (%3)

\n" ).arg( QObject::tr( "Projection" ) ).arg( layer->crs().description() ).arg( layer->crs().authid() ); + out << QObject::tr( "

%1: %2 (%3 %4)

\n" ).arg( QObject::tr( "Width in pixels" ) ).arg( width ).arg( QObject::tr( "units per pixel" ) ).arg( layer->rasterUnitsPerPixelX() ); + out << QObject::tr( "

%1: %2 (%3 %4)

\n" ).arg( QObject::tr( "Height in pixels" ) ).arg( height ).arg( QObject::tr( "units per pixel" ) ).arg( layer->rasterUnitsPerPixelY() ); + out << QObject::tr( "

%1: %2

\n" ).arg( QObject::tr( "Total pixel count" ) ).arg( width * height ); if ( noDataCount > -1 ) - out << QObject::tr( "

NODATA count: %1

\n" ).arg( noDataCount ); - out << QString( "\n" ).arg( QObject::tr( "Value" ) ).arg( QObject::tr( "Count" ) ); + out << QObject::tr( "

%1: %2

\n" ).arg( QObject::tr( "NODATA pixel count" ) ).arg( noDataCount ); + out << QString( "
%1%2
\n" ).arg( QObject::tr( "Value" ) ).arg( QObject::tr( "Pixel count" ) ).arg( QObject::tr( "Area" ) ).arg( areaUnit ); for ( double key : sortedUniqueValues.keys() ) { - out << QString( "\n" ).arg( key ).arg( sortedUniqueValues[key] ); + double area = sortedUniqueValues[key] * cellArea; + out << QString( "\n" ).arg( key ).arg( sortedUniqueValues[key] ).arg( QString::number( area, 'g', 16 ) ); } out << QString( "
%1%2%3 (%4)
%1%2
%1%2%3
\n" ); outputs.insert( QStringLiteral( "OUTPUT_HTML_FILE" ), outputFile ); diff --git a/src/core/processing/qgsnativealgorithms.h b/src/core/processing/qgsnativealgorithms.h index 704bb540193..9b7280597cf 100644 --- a/src/core/processing/qgsnativealgorithms.h +++ b/src/core/processing/qgsnativealgorithms.h @@ -811,20 +811,21 @@ class QgsMeanCoordinatesAlgorithm : public QgsProcessingAlgorithm }; /** - * Native raster layer unique values count algorithm. + * Native raster layer unique values report algorithm. */ -class QgsRasterLayerUniqueValuesCountAlgorithm : public QgsProcessingAlgorithm +class QgsRasterLayerUniqueValuesReportAlgorithm : public QgsProcessingAlgorithm { public: - QgsRasterLayerUniqueValuesCountAlgorithm() = default; + QgsRasterLayerUniqueValuesReportAlgorithm() = default; void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override; - QString name() const override { return QStringLiteral( "rasterlayeruniquevaluescount" ); } - QString displayName() const override { return QObject::tr( "Raster layer unique values count" ); } + QString name() const override { return QStringLiteral( "rasterlayeruniquevaluesreport" ); } + QString displayName() const override { return QObject::tr( "Raster layer unique values report" ); } + virtual QStringList tags() const override { return QObject::tr( "count,area,statistics" ).split( ',' ); } QString group() const override { return QObject::tr( "Raster analysis" ); } QString shortHelpString() const override; - QgsRasterLayerUniqueValuesCountAlgorithm *createInstance() const override SIP_FACTORY; + QgsRasterLayerUniqueValuesReportAlgorithm *createInstance() const override SIP_FACTORY; protected: