mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
[FEATURE][processing] raster layer unique values count algorithm (#5308)
This commit is contained in:
parent
6b418decd6
commit
201091ea3e
25
python/plugins/processing/tests/testdata/expected/raster_unique_values_count.html
vendored
Normal file
25
python/plugins/processing/tests/testdata/expected/raster_unique_values_count.html
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
|
||||
<p>Analyzed file: /home/webmaster/dev/cpp/QGIS/python/plugins/processing/tests/testdata/raster.tif (band 1)</p>
|
||||
<p>Total cell count: 224</p>
|
||||
<p>NODATA count: 104</p>
|
||||
<table><tr><td>Value</td><td>Count</td></tr>
|
||||
<tr><td>826</td><td>4</td></tr>
|
||||
<tr><td>837</td><td>6</td></tr>
|
||||
<tr><td>843</td><td>6</td></tr>
|
||||
<tr><td>845</td><td>4</td></tr>
|
||||
<tr><td>851</td><td>9</td></tr>
|
||||
<tr><td>853</td><td>6</td></tr>
|
||||
<tr><td>859</td><td>10</td></tr>
|
||||
<tr><td>861</td><td>4</td></tr>
|
||||
<tr><td>864</td><td>6</td></tr>
|
||||
<tr><td>866</td><td>9</td></tr>
|
||||
<tr><td>868</td><td>6</td></tr>
|
||||
<tr><td>872</td><td>4</td></tr>
|
||||
<tr><td>873</td><td>9</td></tr>
|
||||
<tr><td>878</td><td>6</td></tr>
|
||||
<tr><td>880</td><td>6</td></tr>
|
||||
<tr><td>881</td><td>6</td></tr>
|
||||
<tr><td>890</td><td>13</td></tr>
|
||||
<tr><td>899</td><td>6</td></tr>
|
||||
</table>
|
||||
</body></html>
|
@ -3236,6 +3236,39 @@ tests:
|
||||
- 'Standard deviation: 43.9618116337985'
|
||||
- 'Sum of the squares: 252304334.52061242'
|
||||
|
||||
- algorithm: qgis:rasterlayeruniquevaluescount
|
||||
name: Raster layer unique values count
|
||||
params:
|
||||
INPUT:
|
||||
name: raster.tif
|
||||
type: raster
|
||||
BAND: 1
|
||||
results:
|
||||
OUTPUT_HTML_FILE:
|
||||
name: raster_unique_values_count.html
|
||||
type: regex
|
||||
rules:
|
||||
- 'Total cell count: 224'
|
||||
- 'NODATA count: 104'
|
||||
- '826</td><td>4</td>'
|
||||
- '837</td><td>6</td>'
|
||||
- '843</td><td>6</td>'
|
||||
- '845</td><td>4</td>'
|
||||
- '851</td><td>9</td>'
|
||||
- '853</td><td>6</td>'
|
||||
- '859</td><td>10</td>'
|
||||
- '861</td><td>4</td>'
|
||||
- '864</td><td>6</td>'
|
||||
- '866</td><td>9</td>'
|
||||
- '868</td><td>6</td>'
|
||||
- '872</td><td>4</td>'
|
||||
- '873</td><td>9</td>'
|
||||
- '878</td><td>6</td>'
|
||||
- '880</td><td>6</td>'
|
||||
- '881</td><td>6</td>'
|
||||
- '890</td><td>13</td>'
|
||||
- '899</td><td>6</td>'
|
||||
|
||||
- algorithm: qgis:pointsdisplacement
|
||||
name: Point displacement
|
||||
params:
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qgsprocessingfeedback.h"
|
||||
#include "qgsprocessingutils.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsrasterlayer.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgsgeometryengine.h"
|
||||
#include "qgswkbtypes.h"
|
||||
@ -88,6 +89,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
|
||||
addAlgorithm( new QgsLineIntersectionAlgorithm() );
|
||||
addAlgorithm( new QgsSplitWithLinesAlgorithm() );
|
||||
addAlgorithm( new QgsMeanCoordinatesAlgorithm() );
|
||||
addAlgorithm( new QgsRasterLayerUniqueValuesCountAlgorithm() );
|
||||
}
|
||||
|
||||
void QgsSaveSelectedFeatures::initAlgorithm( const QVariantMap & )
|
||||
@ -2586,6 +2588,95 @@ QVariantMap QgsMeanCoordinatesAlgorithm::processAlgorithm( const QVariantMap &pa
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
void QgsRasterLayerUniqueValuesCountAlgorithm::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" ) ) );
|
||||
}
|
||||
|
||||
QString QgsRasterLayerUniqueValuesCountAlgorithm::shortHelpString() const
|
||||
{
|
||||
return QObject::tr( "This algorithm returns the count of each unique value in a given raster layer." );
|
||||
}
|
||||
|
||||
QgsRasterLayerUniqueValuesCountAlgorithm *QgsRasterLayerUniqueValuesCountAlgorithm::createInstance() const
|
||||
{
|
||||
return new QgsRasterLayerUniqueValuesCountAlgorithm();
|
||||
}
|
||||
|
||||
QVariantMap QgsRasterLayerUniqueValuesCountAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT" ), context );
|
||||
int band = parameterAsInt( parameters, QStringLiteral( "BAND" ), context );
|
||||
QString outputFile = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT_HTML_FILE" ), context );
|
||||
|
||||
|
||||
QHash< double, int > uniqueValues;
|
||||
int width = layer->width();
|
||||
int height = layer->height();
|
||||
|
||||
QgsRasterBlock *rasterBlock = layer->dataProvider()->block( band, layer->extent(), width, height );
|
||||
int noDataCount = -1;
|
||||
if ( rasterBlock->hasNoDataValue() )
|
||||
noDataCount = 0;
|
||||
|
||||
for ( int row = 0; row < height; row++ )
|
||||
{
|
||||
feedback->setProgress( 100 * row / height );
|
||||
for ( int column = 0; column < width; column++ )
|
||||
{
|
||||
if ( feedback->isCanceled() )
|
||||
break;
|
||||
if ( noDataCount > -1 && rasterBlock->isNoData( row, column ) )
|
||||
{
|
||||
noDataCount += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
double value = rasterBlock->value( row, column );
|
||||
uniqueValues[ value ]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QMap< double, int > sortedUniqueValues;
|
||||
for ( auto it = uniqueValues.constBegin(); it != uniqueValues.constEnd(); ++it )
|
||||
{
|
||||
sortedUniqueValues.insert( it.key(), it.value() );
|
||||
}
|
||||
|
||||
QVariantMap outputs;
|
||||
if ( !outputFile.isEmpty() )
|
||||
{
|
||||
QFile file( outputFile );
|
||||
if ( file.open( QIODevice::WriteOnly | QIODevice::Text ) )
|
||||
{
|
||||
QTextStream out( &file );
|
||||
out << QString( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
|
||||
out << QObject::tr( "<p>Analyzed file: %1 (band %2)</p>\n" ).arg( layer->source() ).arg( band );
|
||||
out << QObject::tr( "<p>Total cell count: %1</p>\n" ).arg( width * height );
|
||||
if ( noDataCount > -1 )
|
||||
out << QObject::tr( "<p>NODATA count: %1</p>\n" ).arg( noDataCount );
|
||||
out << QString( "<table><tr><td>%1</td><td>%2</td></tr>\n" ).arg( QObject::tr( "Value" ) ).arg( QObject::tr( "Count" ) );
|
||||
|
||||
for ( double key : sortedUniqueValues.keys() )
|
||||
{
|
||||
out << QString( "<tr><td>%1</td><td>%2</td></tr>\n" ).arg( key ).arg( sortedUniqueValues[key] );
|
||||
}
|
||||
out << QString( "</table>\n</body></html>" );
|
||||
outputs.insert( QStringLiteral( "OUTPUT_HTML_FILE" ), outputFile );
|
||||
}
|
||||
}
|
||||
|
||||
return outputs;
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
||||
|
||||
|
@ -810,6 +810,29 @@ class QgsMeanCoordinatesAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Native raster layer unique values count algorithm.
|
||||
*/
|
||||
class QgsRasterLayerUniqueValuesCountAlgorithm : public QgsProcessingAlgorithm
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
QgsRasterLayerUniqueValuesCountAlgorithm() = 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 group() const override { return QObject::tr( "Raster analysis" ); }
|
||||
QString shortHelpString() const override;
|
||||
QgsRasterLayerUniqueValuesCountAlgorithm *createInstance() const override SIP_FACTORY;
|
||||
|
||||
protected:
|
||||
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
};
|
||||
|
||||
///@endcond PRIVATE
|
||||
|
||||
#endif // QGSNATIVEALGORITHMS_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user