Skip to content

Commit e01dca7

Browse files
committed
[FEATURE] Allow selection of wanted stats for zonal stats (fix #4429)
1 parent 634641a commit e01dca7

6 files changed

+103
-27
lines changed

src/analysis/vector/qgszonalstatistics.cpp

+41-22
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@
3030
#define TO8F(x) QFile::encodeName( x ).constData()
3131
#endif
3232

33-
QgsZonalStatistics::QgsZonalStatistics( QgsVectorLayer* polygonLayer, const QString& rasterFile, const QString& attributePrefix, int rasterBand )
33+
QgsZonalStatistics::QgsZonalStatistics( QgsVectorLayer* polygonLayer, const QString& rasterFile, const QString& attributePrefix, int rasterBand , Statistics stats )
3434
: mRasterFilePath( rasterFile )
3535
, mRasterBand( rasterBand )
3636
, mPolygonLayer( polygonLayer )
3737
, mAttributePrefix( attributePrefix )
3838
, mInputNodataValue( -1 )
39+
, mStatistics( stats )
3940
{
4041

4142
}
@@ -44,6 +45,7 @@ QgsZonalStatistics::QgsZonalStatistics()
4445
: mRasterBand( 0 )
4546
, mPolygonLayer( 0 )
4647
, mInputNodataValue( -1 )
48+
, mStatistics( QgsZonalStatistics::All )
4749
{
4850

4951
}
@@ -110,26 +112,41 @@ int QgsZonalStatistics::calculateStatistics( QProgressDialog* p )
110112
QgsRectangle rasterBBox( geoTransform[0], geoTransform[3] - ( nCellsYGDAL * cellsizeY ),
111113
geoTransform[0] + ( nCellsXGDAL * cellsizeX ), geoTransform[3] );
112114

113-
//add the new count, sum, mean fields to the provider
115+
//add the new fields to the provider
114116
QList<QgsField> newFieldList;
115-
QString countFieldName = getUniqueFieldName( mAttributePrefix + "count" );
116-
QString sumFieldName = getUniqueFieldName( mAttributePrefix + "sum" );
117-
QString meanFieldName = getUniqueFieldName( mAttributePrefix + "mean" );
118-
QgsField countField( countFieldName, QVariant::Double, "double precision" );
119-
QgsField sumField( sumFieldName, QVariant::Double, "double precision" );
120-
QgsField meanField( meanFieldName, QVariant::Double, "double precision" );
121-
newFieldList.push_back( countField );
122-
newFieldList.push_back( sumField );
123-
newFieldList.push_back( meanField );
117+
QString countFieldName;
118+
if ( mStatistics & QgsZonalStatistics::Count )
119+
{
120+
countFieldName = getUniqueFieldName( mAttributePrefix + "count" );
121+
QgsField countField( countFieldName, QVariant::Double, "double precision" );
122+
newFieldList.push_back( countField );
123+
}
124+
QString sumFieldName;
125+
if ( mStatistics & QgsZonalStatistics::Sum )
126+
{
127+
sumFieldName = getUniqueFieldName( mAttributePrefix + "sum" );
128+
QgsField sumField( sumFieldName, QVariant::Double, "double precision" );
129+
newFieldList.push_back( sumField );
130+
}
131+
QString meanFieldName;
132+
if ( mStatistics & QgsZonalStatistics::Mean )
133+
{
134+
meanFieldName = getUniqueFieldName( mAttributePrefix + "mean" );
135+
QgsField meanField( meanFieldName, QVariant::Double, "double precision" );
136+
newFieldList.push_back( meanField );
137+
}
124138
vectorProvider->addAttributes( newFieldList );
125139

126140
//index of the new fields
127-
int countIndex = vectorProvider->fieldNameIndex( countFieldName );
128-
int sumIndex = vectorProvider->fieldNameIndex( sumFieldName );
129-
int meanIndex = vectorProvider->fieldNameIndex( meanFieldName );
141+
int countIndex = mStatistics & QgsZonalStatistics::Count ? vectorProvider->fieldNameIndex( countFieldName ) : -1;
142+
int sumIndex = mStatistics & QgsZonalStatistics::Sum ? vectorProvider->fieldNameIndex( sumFieldName ) : -1;
143+
int meanIndex = mStatistics & QgsZonalStatistics::Mean ? vectorProvider->fieldNameIndex( meanFieldName ) : -1;
130144

131-
if ( countIndex == -1 || sumIndex == -1 || meanIndex == -1 )
145+
if (( mStatistics & QgsZonalStatistics::Count && countIndex == -1 )
146+
|| ( mStatistics & QgsZonalStatistics::Sum && sumIndex == -1 )
147+
|| ( mStatistics & QgsZonalStatistics::Mean && meanIndex == -1 ) )
132148
{
149+
//failed to create a required field
133150
return 8;
134151
}
135152

@@ -204,22 +221,24 @@ int QgsZonalStatistics::calculateStatistics( QProgressDialog* p )
204221
rasterBBox, sum, count );
205222
}
206223

207-
208-
if ( count == 0 )
224+
if ( mStatistics & QgsZonalStatistics::Mean && count > 0 )
209225
{
210-
mean = 0;
226+
mean = sum / count;
211227
}
212228
else
213229
{
214-
mean = sum / count;
230+
mean = 0;
215231
}
216232

217233
//write the statistics value to the vector data provider
218234
QgsChangedAttributesMap changeMap;
219235
QgsAttributeMap changeAttributeMap;
220-
changeAttributeMap.insert( countIndex, QVariant( count ) );
221-
changeAttributeMap.insert( sumIndex, QVariant( sum ) );
222-
changeAttributeMap.insert( meanIndex, QVariant( mean ) );
236+
if ( mStatistics & QgsZonalStatistics::Count )
237+
changeAttributeMap.insert( countIndex, QVariant( count ) );
238+
if ( mStatistics & QgsZonalStatistics::Sum )
239+
changeAttributeMap.insert( sumIndex, QVariant( sum ) );
240+
if ( mStatistics & QgsZonalStatistics::Mean )
241+
changeAttributeMap.insert( meanIndex, QVariant( mean ) );
223242
changeMap.insert( f.id(), changeAttributeMap );
224243
vectorProvider->changeAttributeValues( changeMap );
225244

src/analysis/vector/qgszonalstatistics.h

+16-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,19 @@ class QProgressDialog;
2929
class ANALYSIS_EXPORT QgsZonalStatistics
3030
{
3131
public:
32-
QgsZonalStatistics( QgsVectorLayer* polygonLayer, const QString& rasterFile, const QString& attributePrefix = "", int rasterBand = 1 );
32+
33+
//! Enumeration of flags that specify statistics to be calculated
34+
enum Statistic
35+
{
36+
Count = 0x01, //!< Pixel count
37+
Sum = 0x02, //!< Sum of pixel values
38+
Mean = 0x04, //!< Mean of pixel values
39+
All = Count | Sum | Mean
40+
};
41+
Q_DECLARE_FLAGS( Statistics, Statistic )
42+
43+
QgsZonalStatistics( QgsVectorLayer* polygonLayer, const QString& rasterFile, const QString& attributePrefix = "", int rasterBand = 1,
44+
Statistics stats = Statistic::All );
3345
~QgsZonalStatistics();
3446

3547
/**Starts the calculation
@@ -66,7 +78,9 @@ class ANALYSIS_EXPORT QgsZonalStatistics
6678
QString mAttributePrefix;
6779
/**The nodata value of the input layer*/
6880
float mInputNodataValue;
69-
81+
Statistics mStatistics;
7082
};
7183

84+
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsZonalStatistics::Statistics )
85+
7286
#endif // QGSZONALSTATISTICS_H

src/plugins/zonal_statistics/qgszonalstatisticsdialog.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,28 @@
2323
#include "qgisinterface.h"
2424

2525
#include <QSettings>
26+
#include <QListWidgetItem>
2627

2728
QgsZonalStatisticsDialog::QgsZonalStatisticsDialog( QgisInterface* iface ): QDialog( iface->mainWindow() ), mIface( iface )
2829
{
2930
setupUi( this );
3031

32+
QListWidgetItem* countItem = new QListWidgetItem( tr( "Count" ), mStatsListWidget );
33+
countItem->setFlags( countItem->flags() | Qt::ItemIsUserCheckable );
34+
countItem->setCheckState( Qt::Checked );
35+
countItem->setData( Qt::UserRole, QgsZonalStatistics::Count );
36+
mStatsListWidget->addItem( countItem );
37+
QListWidgetItem* sumItem = new QListWidgetItem( tr( "Sum" ), mStatsListWidget );
38+
sumItem->setFlags( sumItem->flags() | Qt::ItemIsUserCheckable );
39+
sumItem->setCheckState( Qt::Checked );
40+
sumItem->setData( Qt::UserRole, QgsZonalStatistics::Sum );
41+
mStatsListWidget->addItem( sumItem );
42+
QListWidgetItem* meanItem = new QListWidgetItem( tr( "Mean" ), mStatsListWidget );
43+
meanItem->setFlags( meanItem->flags() | Qt::ItemIsUserCheckable );
44+
meanItem->setCheckState( Qt::Checked );
45+
meanItem->setData( Qt::UserRole, QgsZonalStatistics::Mean );
46+
mStatsListWidget->addItem( meanItem );
47+
3148
QSettings settings;
3249
restoreGeometry( settings.value( "Plugin-ZonalStatistics/geometry" ).toByteArray() );
3350

@@ -107,6 +124,20 @@ QString QgsZonalStatisticsDialog::attributePrefix() const
107124
return mColumnPrefixLineEdit->text();
108125
}
109126

127+
QgsZonalStatistics::Statistics QgsZonalStatisticsDialog::selectedStats() const
128+
{
129+
QgsZonalStatistics::Statistics stats = 0;
130+
for ( int i = 0; i < mStatsListWidget->count(); ++i )
131+
{
132+
QListWidgetItem* item = mStatsListWidget->item( i );
133+
if ( item->checkState() == Qt::Checked )
134+
{
135+
stats |= ( QgsZonalStatistics::Statistic )( item->data( Qt::UserRole ).toInt() );
136+
}
137+
}
138+
return stats;
139+
}
140+
110141
QString QgsZonalStatisticsDialog::proposeAttributePrefix() const
111142
{
112143
if ( !polygonLayer() )

src/plugins/zonal_statistics/qgszonalstatisticsdialog.h

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define QGSZONALSTATISTICSDIALOG_H
2020

2121
#include "ui_qgszonalstatisticsdialogbase.h"
22+
#include "qgszonalstatistics.h"
2223

2324
class QgisInterface;
2425
class QgsVectorLayer;
@@ -34,6 +35,7 @@ class QgsZonalStatisticsDialog: public QDialog, private Ui::QgsZonalStatisticsDi
3435
int rasterBand() const {return 1;} //todo: expose that in the GUI
3536
QgsVectorLayer* polygonLayer() const;
3637
QString attributePrefix() const;
38+
QgsZonalStatistics::Statistics selectedStats() const;
3739

3840
private:
3941
QgsZonalStatisticsDialog();

src/plugins/zonal_statistics/qgszonalstatisticsdialogbase.ui

+12-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>240</width>
10-
<height>193</height>
9+
<width>254</width>
10+
<height>320</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -48,6 +48,16 @@
4848
</property>
4949
</widget>
5050
</item>
51+
<item>
52+
<widget class="QLabel" name="label">
53+
<property name="text">
54+
<string>Statistics to calculate:</string>
55+
</property>
56+
</widget>
57+
</item>
58+
<item>
59+
<widget class="QListWidget" name="mStatsListWidget"/>
60+
</item>
5161
<item>
5262
<widget class="QDialogButtonBox" name="buttonBox">
5363
<property name="orientation">

src/plugins/zonal_statistics/qgszonalstatisticsplugin.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void QgsZonalStatisticsPlugin::run()
7272
return;
7373
}
7474

75-
QgsZonalStatistics zs( vl, rasterFile, d.attributePrefix(), 1 ); //atm hardcode first band
75+
QgsZonalStatistics zs( vl, rasterFile, d.attributePrefix(), 1, d.selectedStats() ); //atm hardcode first band
7676
QProgressDialog p( tr( "Calculating zonal statistics..." ), tr( "Abort..." ), 0, 0 );
7777
p.setWindowModality( Qt::WindowModal );
7878
zs.calculateStatistics( &p );

0 commit comments

Comments
 (0)