Skip to content

Commit 201091e

Browse files
authoredOct 9, 2017
[FEATURE][processing] raster layer unique values count algorithm (#5308)
1 parent 6b418de commit 201091e

File tree

4 files changed

+172
-0
lines changed

4 files changed

+172
-0
lines changed
 
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
2+
<p>Analyzed file: /home/webmaster/dev/cpp/QGIS/python/plugins/processing/tests/testdata/raster.tif (band 1)</p>
3+
<p>Total cell count: 224</p>
4+
<p>NODATA count: 104</p>
5+
<table><tr><td>Value</td><td>Count</td></tr>
6+
<tr><td>826</td><td>4</td></tr>
7+
<tr><td>837</td><td>6</td></tr>
8+
<tr><td>843</td><td>6</td></tr>
9+
<tr><td>845</td><td>4</td></tr>
10+
<tr><td>851</td><td>9</td></tr>
11+
<tr><td>853</td><td>6</td></tr>
12+
<tr><td>859</td><td>10</td></tr>
13+
<tr><td>861</td><td>4</td></tr>
14+
<tr><td>864</td><td>6</td></tr>
15+
<tr><td>866</td><td>9</td></tr>
16+
<tr><td>868</td><td>6</td></tr>
17+
<tr><td>872</td><td>4</td></tr>
18+
<tr><td>873</td><td>9</td></tr>
19+
<tr><td>878</td><td>6</td></tr>
20+
<tr><td>880</td><td>6</td></tr>
21+
<tr><td>881</td><td>6</td></tr>
22+
<tr><td>890</td><td>13</td></tr>
23+
<tr><td>899</td><td>6</td></tr>
24+
</table>
25+
</body></html>

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3236,6 +3236,39 @@ tests:
32363236
- 'Standard deviation: 43.9618116337985'
32373237
- 'Sum of the squares: 252304334.52061242'
32383238

3239+
- algorithm: qgis:rasterlayeruniquevaluescount
3240+
name: Raster layer unique values count
3241+
params:
3242+
INPUT:
3243+
name: raster.tif
3244+
type: raster
3245+
BAND: 1
3246+
results:
3247+
OUTPUT_HTML_FILE:
3248+
name: raster_unique_values_count.html
3249+
type: regex
3250+
rules:
3251+
- 'Total cell count: 224'
3252+
- 'NODATA count: 104'
3253+
- '826</td><td>4</td>'
3254+
- '837</td><td>6</td>'
3255+
- '843</td><td>6</td>'
3256+
- '845</td><td>4</td>'
3257+
- '851</td><td>9</td>'
3258+
- '853</td><td>6</td>'
3259+
- '859</td><td>10</td>'
3260+
- '861</td><td>4</td>'
3261+
- '864</td><td>6</td>'
3262+
- '866</td><td>9</td>'
3263+
- '868</td><td>6</td>'
3264+
- '872</td><td>4</td>'
3265+
- '873</td><td>9</td>'
3266+
- '878</td><td>6</td>'
3267+
- '880</td><td>6</td>'
3268+
- '881</td><td>6</td>'
3269+
- '890</td><td>13</td>'
3270+
- '899</td><td>6</td>'
3271+
32393272
- algorithm: qgis:pointsdisplacement
32403273
name: Point displacement
32413274
params:

‎src/core/processing/qgsnativealgorithms.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "qgsprocessingfeedback.h"
2222
#include "qgsprocessingutils.h"
2323
#include "qgsvectorlayer.h"
24+
#include "qgsrasterlayer.h"
2425
#include "qgsgeometry.h"
2526
#include "qgsgeometryengine.h"
2627
#include "qgswkbtypes.h"
@@ -88,6 +89,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
8889
addAlgorithm( new QgsLineIntersectionAlgorithm() );
8990
addAlgorithm( new QgsSplitWithLinesAlgorithm() );
9091
addAlgorithm( new QgsMeanCoordinatesAlgorithm() );
92+
addAlgorithm( new QgsRasterLayerUniqueValuesCountAlgorithm() );
9193
}
9294

9395
void QgsSaveSelectedFeatures::initAlgorithm( const QVariantMap & )
@@ -2586,6 +2588,95 @@ QVariantMap QgsMeanCoordinatesAlgorithm::processAlgorithm( const QVariantMap &pa
25862588
return outputs;
25872589
}
25882590

2591+
2592+
void QgsRasterLayerUniqueValuesCountAlgorithm::initAlgorithm( const QVariantMap & )
2593+
{
2594+
addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "INPUT" ),
2595+
QObject::tr( "Input layer" ) ) );
2596+
addParameter( new QgsProcessingParameterBand( QStringLiteral( "BAND" ),
2597+
QObject::tr( "Band number" ), 1, QStringLiteral( "INPUT" ) ) );
2598+
addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT_HTML_FILE" ),
2599+
QObject::tr( "Unique values count" ), QObject::tr( "HTML files (*.html)" ), QVariant(), true ) );
2600+
addOutput( new QgsProcessingOutputHtml( QStringLiteral( "OUTPUT_HTML_FILE" ), QObject::tr( "Unique values count" ) ) );
2601+
}
2602+
2603+
QString QgsRasterLayerUniqueValuesCountAlgorithm::shortHelpString() const
2604+
{
2605+
return QObject::tr( "This algorithm returns the count of each unique value in a given raster layer." );
2606+
}
2607+
2608+
QgsRasterLayerUniqueValuesCountAlgorithm *QgsRasterLayerUniqueValuesCountAlgorithm::createInstance() const
2609+
{
2610+
return new QgsRasterLayerUniqueValuesCountAlgorithm();
2611+
}
2612+
2613+
QVariantMap QgsRasterLayerUniqueValuesCountAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
2614+
{
2615+
QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT" ), context );
2616+
int band = parameterAsInt( parameters, QStringLiteral( "BAND" ), context );
2617+
QString outputFile = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT_HTML_FILE" ), context );
2618+
2619+
2620+
QHash< double, int > uniqueValues;
2621+
int width = layer->width();
2622+
int height = layer->height();
2623+
2624+
QgsRasterBlock *rasterBlock = layer->dataProvider()->block( band, layer->extent(), width, height );
2625+
int noDataCount = -1;
2626+
if ( rasterBlock->hasNoDataValue() )
2627+
noDataCount = 0;
2628+
2629+
for ( int row = 0; row < height; row++ )
2630+
{
2631+
feedback->setProgress( 100 * row / height );
2632+
for ( int column = 0; column < width; column++ )
2633+
{
2634+
if ( feedback->isCanceled() )
2635+
break;
2636+
if ( noDataCount > -1 && rasterBlock->isNoData( row, column ) )
2637+
{
2638+
noDataCount += 1;
2639+
}
2640+
else
2641+
{
2642+
double value = rasterBlock->value( row, column );
2643+
uniqueValues[ value ]++;
2644+
}
2645+
}
2646+
}
2647+
2648+
QMap< double, int > sortedUniqueValues;
2649+
for ( auto it = uniqueValues.constBegin(); it != uniqueValues.constEnd(); ++it )
2650+
{
2651+
sortedUniqueValues.insert( it.key(), it.value() );
2652+
}
2653+
2654+
QVariantMap outputs;
2655+
if ( !outputFile.isEmpty() )
2656+
{
2657+
QFile file( outputFile );
2658+
if ( file.open( QIODevice::WriteOnly | QIODevice::Text ) )
2659+
{
2660+
QTextStream out( &file );
2661+
out << QString( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
2662+
out << QObject::tr( "<p>Analyzed file: %1 (band %2)</p>\n" ).arg( layer->source() ).arg( band );
2663+
out << QObject::tr( "<p>Total cell count: %1</p>\n" ).arg( width * height );
2664+
if ( noDataCount > -1 )
2665+
out << QObject::tr( "<p>NODATA count: %1</p>\n" ).arg( noDataCount );
2666+
out << QString( "<table><tr><td>%1</td><td>%2</td></tr>\n" ).arg( QObject::tr( "Value" ) ).arg( QObject::tr( "Count" ) );
2667+
2668+
for ( double key : sortedUniqueValues.keys() )
2669+
{
2670+
out << QString( "<tr><td>%1</td><td>%2</td></tr>\n" ).arg( key ).arg( sortedUniqueValues[key] );
2671+
}
2672+
out << QString( "</table>\n</body></html>" );
2673+
outputs.insert( QStringLiteral( "OUTPUT_HTML_FILE" ), outputFile );
2674+
}
2675+
}
2676+
2677+
return outputs;
2678+
}
2679+
25892680
///@endcond
25902681

25912682

‎src/core/processing/qgsnativealgorithms.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,29 @@ class QgsMeanCoordinatesAlgorithm : public QgsProcessingAlgorithm
810810

811811
};
812812

813+
/**
814+
* Native raster layer unique values count algorithm.
815+
*/
816+
class QgsRasterLayerUniqueValuesCountAlgorithm : public QgsProcessingAlgorithm
817+
{
818+
819+
public:
820+
821+
QgsRasterLayerUniqueValuesCountAlgorithm() = default;
822+
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
823+
QString name() const override { return QStringLiteral( "rasterlayeruniquevaluescount" ); }
824+
QString displayName() const override { return QObject::tr( "Raster layer unique values count" ); }
825+
QString group() const override { return QObject::tr( "Raster analysis" ); }
826+
QString shortHelpString() const override;
827+
QgsRasterLayerUniqueValuesCountAlgorithm *createInstance() const override SIP_FACTORY;
828+
829+
protected:
830+
831+
virtual QVariantMap processAlgorithm( const QVariantMap &parameters,
832+
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
833+
834+
};
835+
813836
///@endcond PRIVATE
814837

815838
#endif // QGSNATIVEALGORITHMS_H

0 commit comments

Comments
 (0)
Please sign in to comment.