QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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( QStringLiteral( "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( QStringLiteral( "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( QStringLiteral( "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( QStringLiteral( "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 }
virtual int bandCount() const =0
Gets number of bands.
A rectangle specified with double values.
Definition: qgsrectangle.h:40
double stdDevFactor() const
Returns the factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ]...
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
QgsRasterMinMaxOrigin::StatAccuracy statAccuracy() const
Returns the raster statistic accuracy.
double maximumValue
The maximum cell value in the raster band.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QgsRasterMinMaxOrigin minMaxOrigin()
Returns 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)
Sets the extent.
void widgetChanged()
Emitted when something on the widget has changed.
double stdDev
The standard deviation of the cell values.
QgsRasterDataProvider * dataProvider() override
Returns the layer&#39;s data provider.
This class describes the origin of min/max values.
QgsRasterMinMaxOrigin::Extent extent() const
Returns the raster extent.
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)
QgsRasterMinMaxOrigin::Limits limits() const
Returns the raster limits.
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)
Sets the 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) ]...
QgsRasterMinMaxWidget(QgsRasterLayer *layer, QWidget *parent=nullptr)
Constructor for QgsRasterMinMaxWidget.
int sampleSize()
Returns the selected sample size.
void setCumulativeCutLower(double val)
Sets the lower bound of cumulative cut method (between 0 and 1).
void setLimits(QgsRasterMinMaxOrigin::Limits limits)
Sets the limits.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
void userHasSetManualMinMaxValues()
Uncheck cumulative cut, min/max, std-dev radio buttons.
QgsRectangle extent()
Returns the extent selected by the user.
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setStatAccuracy(QgsRasterMinMaxOrigin::StatAccuracy accuracy)
Sets the statistics accuracy.
Whole raster is used to compute statistics.
double cumulativeCutLower() const
Returns the lower bound of cumulative cut method (between 0 and 1).
double cumulativeCutUpper() const
Returns the upper bound of cumulative cut method (between 0 and 1).
QgsRectangle outputExtentToLayerExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from output CRS to layer&#39;s CRS
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.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
const int IDX_CURRENT_CANVAS
QgsMapCanvas * mapCanvas()
Returns the map canvas associated with the widget.
void setCumulativeCutUpper(double val)
Sets the upper bound of cumulative cut method (between 0 and 1).
void doComputations()
Load programmatically with current values.
const int IDX_WHOLE_RASTER
void setFromMinMaxOrigin(const QgsRasterMinMaxOrigin &)
Sets the "source" of min/max values.