QGIS API Documentation  2.99.0-Master (19b062c)
qgsrasterminmaxwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterminmaxwidget.h
3  ---------------------------------
4  begin : July 2012
5  copyright : (C) 2012 by Radim Blazek
6  email : radim dot blazek at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include <QSettings>
19 #include <QMessageBox>
20 
21 #include "qgsrasterlayer.h"
22 #include "qgsrasterminmaxwidget.h"
23 #include "qgsmapcanvas.h"
24 #include "qgsrasterrenderer.h"
25 #include "qgsrasterdataprovider.h"
26 #include "qgsrasterminmaxorigin.h"
27 
28 const int IDX_WHOLE_RASTER = 0;
29 const int IDX_CURRENT_CANVAS = 1;
30 const int IDX_UPDATED_CANVAS = 2;
31 
33  : QWidget( parent )
34  , mLayer( layer )
35  , mLastRectangleValid( false )
36  , mBandsChanged( false )
37 {
38  QgsDebugMsg( "Entered." );
39  setupUi( this );
40  connect( mUserDefinedRadioButton, &QRadioButton::toggled, this, &QgsRasterMinMaxWidget::mUserDefinedRadioButton_toggled );
41  connect( mMinMaxRadioButton, &QRadioButton::toggled, this, &QgsRasterMinMaxWidget::mMinMaxRadioButton_toggled );
42  connect( mStdDevRadioButton, &QRadioButton::toggled, this, &QgsRasterMinMaxWidget::mStdDevRadioButton_toggled );
43  connect( mCumulativeCutRadioButton, &QRadioButton::toggled, this, &QgsRasterMinMaxWidget::mCumulativeCutRadioButton_toggled );
44  connect( mStatisticsExtentCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMinMaxWidget::mStatisticsExtentCombo_currentIndexChanged );
45  connect( mCumulativeCutLowerDoubleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMinMaxWidget::mCumulativeCutLowerDoubleSpinBox_valueChanged );
46  connect( mCumulativeCutUpperDoubleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMinMaxWidget::mCumulativeCutUpperDoubleSpinBox_valueChanged );
47  connect( mStdDevSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMinMaxWidget::mStdDevSpinBox_valueChanged );
48  connect( cboAccuracy, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMinMaxWidget::cboAccuracy_currentIndexChanged );
49 
50  QgsRasterMinMaxOrigin defaultMinMaxOrigin;
51  setFromMinMaxOrigin( defaultMinMaxOrigin );
52 }
53 
55 {
56  mCanvas = canvas;
57 }
58 
60 {
61  return mCanvas;
62 }
63 
64 void QgsRasterMinMaxWidget::setBands( const QList<int> &bands )
65 {
66  mBandsChanged = bands != mBands;
67  mBands = bands;
68 }
69 
71 {
72  const int nExtentIdx = mStatisticsExtentCombo->currentIndex();
73  if ( nExtentIdx != IDX_CURRENT_CANVAS && nExtentIdx != IDX_UPDATED_CANVAS )
74  return QgsRectangle();
75 
76  if ( mLayer && mCanvas )
77  return mCanvas->mapSettings().outputExtentToLayerExtent( mLayer, mCanvas->extent() );
78  else if ( mCanvas )
79  return mCanvas->extent();
80  else
81  return QgsRectangle();
82 }
83 
85 {
86  mUserDefinedRadioButton->setChecked( true );
87  mStatisticsExtentCombo->setCurrentIndex( IDX_WHOLE_RASTER );
88 }
89 
90 void QgsRasterMinMaxWidget::mUserDefinedRadioButton_toggled( bool toggled )
91 {
92  mStatisticsExtentCombo->setEnabled( !toggled );
93  cboAccuracy->setEnabled( !toggled );
94  emit widgetChanged();
95 }
96 
98 {
99  switch ( minMaxOrigin.limits() )
100  {
102  default:
103  mUserDefinedRadioButton->setChecked( true );
104  break;
105 
107  mMinMaxRadioButton->setChecked( true );
108  break;
109 
111  mStdDevRadioButton->setChecked( true );
112  break;
113 
115  mCumulativeCutRadioButton->setChecked( true );
116  break;
117  }
118 
119  switch ( minMaxOrigin.extent() )
120  {
121  default:
123  mStatisticsExtentCombo->setCurrentIndex( IDX_WHOLE_RASTER );
124  break;
125 
127  mStatisticsExtentCombo->setCurrentIndex( IDX_CURRENT_CANVAS );
128  break;
129 
131  mStatisticsExtentCombo->setCurrentIndex( IDX_UPDATED_CANVAS );
132  break;
133  }
134 
135  mCumulativeCutLowerDoubleSpinBox->setValue( 100.0 * minMaxOrigin.cumulativeCutLower() );
136  mCumulativeCutUpperDoubleSpinBox->setValue( 100.0 * minMaxOrigin.cumulativeCutUpper() );
137  mStdDevSpinBox->setValue( minMaxOrigin.stdDevFactor() );
138 
139  cboAccuracy->setCurrentIndex( minMaxOrigin.statAccuracy() == QgsRasterMinMaxOrigin::Estimated ? 0 : 1 );
140 }
141 
143 {
145 
146  if ( mMinMaxRadioButton->isChecked() )
148  else if ( mStdDevRadioButton->isChecked() )
150  else if ( mCumulativeCutRadioButton->isChecked() )
152  else
153  minMaxOrigin.setLimits( QgsRasterMinMaxOrigin::None );
154 
155  switch ( mStatisticsExtentCombo->currentIndex() )
156  {
157  case IDX_WHOLE_RASTER:
158  default:
160  break;
161  case IDX_CURRENT_CANVAS:
163  break;
164  case IDX_UPDATED_CANVAS:
166  break;
167  }
168 
169  if ( cboAccuracy->currentIndex() == 0 )
171  else
173 
174  minMaxOrigin.setCumulativeCutLower(
175  mCumulativeCutLowerDoubleSpinBox->value() / 100.0 );
176  minMaxOrigin.setCumulativeCutUpper(
177  mCumulativeCutUpperDoubleSpinBox->value() / 100.0 );
178  minMaxOrigin.setStdDevFactor( mStdDevSpinBox->value() );
179 
180  return minMaxOrigin;
181 }
182 
184 {
185  QgsDebugMsg( "Entered." );
186 
187  QgsRectangle myExtent = extent(); // empty == full
188  int mySampleSize = sampleSize(); // 0 == exact
189 
190  QgsRasterMinMaxOrigin newMinMaxOrigin = minMaxOrigin();
191  if ( mLastRectangleValid && mLastRectangle == myExtent &&
192  mLastMinMaxOrigin == newMinMaxOrigin &&
193  !mBandsChanged )
194  {
195  QgsDebugMsg( "Does not need to redo statistics computations" );
196  return;
197  }
198 
199  mLastRectangleValid = true;
200  mLastRectangle = myExtent;
201  mLastMinMaxOrigin = newMinMaxOrigin;
202  mBandsChanged = false;
203 
204  Q_FOREACH ( int myBand, mBands )
205  {
206  QgsDebugMsg( QString( "myBand = %1" ).arg( myBand ) );
207  if ( myBand < 1 || myBand > mLayer->dataProvider()->bandCount() )
208  {
209  continue;
210  }
211  double myMin = std::numeric_limits<double>::quiet_NaN();
212  double myMax = std::numeric_limits<double>::quiet_NaN();
213 
214  bool updateMinMax = false;
215  if ( mCumulativeCutRadioButton->isChecked() )
216  {
217  updateMinMax = true;
218  double myLower = mCumulativeCutLowerDoubleSpinBox->value() / 100.0;
219  double myUpper = mCumulativeCutUpperDoubleSpinBox->value() / 100.0;
220  mLayer->dataProvider()->cumulativeCut( myBand, myLower, myUpper, myMin, myMax, myExtent, mySampleSize );
221  }
222  else if ( mMinMaxRadioButton->isChecked() )
223  {
224  updateMinMax = true;
225  // TODO: consider provider minimum/maximumValue() (has to be defined well in povider)
226  QgsRasterBandStats myRasterBandStats = mLayer->dataProvider()->bandStatistics( myBand, QgsRasterBandStats::Min | QgsRasterBandStats::Max, myExtent, mySampleSize );
227  myMin = myRasterBandStats.minimumValue;
228  myMax = myRasterBandStats.maximumValue;
229  }
230  else if ( mStdDevRadioButton->isChecked() )
231  {
232  updateMinMax = true;
233  QgsRasterBandStats myRasterBandStats = mLayer->dataProvider()->bandStatistics( myBand, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, myExtent, mySampleSize );
234  double myStdDev = mStdDevSpinBox->value();
235  myMin = myRasterBandStats.mean - ( myStdDev * myRasterBandStats.stdDev );
236  myMax = myRasterBandStats.mean + ( myStdDev * myRasterBandStats.stdDev );
237  }
238 
239  if ( updateMinMax )
240  emit load( myBand, myMin, myMax );
241  }
242 }
243 
245 {
246  mStatisticsExtentCombo->removeItem( IDX_UPDATED_CANVAS );
247 }
QgsRasterMinMaxOrigin::Limits limits() const
Return limits.
virtual int bandCount() const =0
Get number of bands.
QgsRasterMinMaxOrigin::Extent extent() const
Return extent.
A rectangle specified with double values.
Definition: qgsrectangle.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
QgsRectangle outputExtentToLayerExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from output CRS to layer&#39;s CRS
double maximumValue
The maximum cell value in the raster band.
QgsRasterMinMaxOrigin minMaxOrigin()
Return a QgsRasterMinMaxOrigin object with the widget values.
virtual void cumulativeCut(int bandNo, double lowerCount, double upperCount, double &lowerValue, double &upperValue, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0)
Find values for cumulative pixel count cut.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:74
Current extent of the canvas (at the time of computation) is used to compute statistics.
void setExtent(QgsRasterMinMaxOrigin::Extent extent)
Set extent.
double cumulativeCutLower() const
Return lower bound of cumulative cut method (between 0 and 1).
void widgetChanged()
Emitted when something on the widget has changed.
double stdDev
The standard deviation of the cell values.
QgsRasterDataProvider * dataProvider() override
This class describes the origin of min/max values.
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
void setBands(const QList< int > &bands)
double cumulativeCutUpper() const
Return upper bound of cumulative cut method (between 0 and 1).
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
Constantly updated extent of the canvas is used to compute statistics.
Range is [ mean - stdDevFactor() * stddev, mean + stdDevFactor() * stddev ].
void hideUpdatedExtent()
Hide updated extent choice.
const int IDX_UPDATED_CANVAS
void setStdDevFactor(double val)
Set factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ]...
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ]...
int sampleSize()
Return the selected sample size.
void setCumulativeCutLower(double val)
Set lower bound of cumulative cut method (between 0 and 1).
void setLimits(QgsRasterMinMaxOrigin::Limits limits)
Set limits.
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Get band statistics.
void userHasSetManualMinMaxValues()
Uncheck cumulative cut, min/max, std-dev radio buttons.
QgsRectangle extent()
Return the extent selected by the user.
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setStatAccuracy(QgsRasterMinMaxOrigin::StatAccuracy accuracy)
Set statistics accuracy.
Whole raster is used to compute statistics.
double minimumValue
The minimum cell value in the raster band.
void load(int bandNo, double min, double max)
signal emitted when new min/max values are computed from statistics.
QgsRasterMinMaxOrigin::StatAccuracy statAccuracy() const
Return statistic accuracy.
QgsRasterMinMaxWidget(QgsRasterLayer *layer, QWidget *parent=0)
const int IDX_CURRENT_CANVAS
QgsMapCanvas * mapCanvas()
Returns the map canvas associated with the widget.
void setCumulativeCutUpper(double val)
Set upper bound of cumulative cut method (between 0 and 1).
double stdDevFactor() const
Return factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ]...
void doComputations()
Load programmatically with current values.
const int IDX_WHOLE_RASTER
void setFromMinMaxOrigin(const QgsRasterMinMaxOrigin &)
Set the "source" of min/max values.