QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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  const auto constMBands = mBands;
205  for ( int myBand : constMBands )
206  {
207  QgsDebugMsg( QStringLiteral( "myBand = %1" ).arg( myBand ) );
208  if ( myBand < 1 || myBand > mLayer->dataProvider()->bandCount() )
209  {
210  continue;
211  }
212  double myMin = std::numeric_limits<double>::quiet_NaN();
213  double myMax = std::numeric_limits<double>::quiet_NaN();
214 
215  bool updateMinMax = false;
216  if ( mCumulativeCutRadioButton->isChecked() )
217  {
218  updateMinMax = true;
219  double myLower = mCumulativeCutLowerDoubleSpinBox->value() / 100.0;
220  double myUpper = mCumulativeCutUpperDoubleSpinBox->value() / 100.0;
221  mLayer->dataProvider()->cumulativeCut( myBand, myLower, myUpper, myMin, myMax, myExtent, mySampleSize );
222  }
223  else if ( mMinMaxRadioButton->isChecked() )
224  {
225  updateMinMax = true;
226  // TODO: consider provider minimum/maximumValue() (has to be defined well in povider)
227  QgsRasterBandStats myRasterBandStats = mLayer->dataProvider()->bandStatistics( myBand, QgsRasterBandStats::Min | QgsRasterBandStats::Max, myExtent, mySampleSize );
228  myMin = myRasterBandStats.minimumValue;
229  myMax = myRasterBandStats.maximumValue;
230  }
231  else if ( mStdDevRadioButton->isChecked() )
232  {
233  updateMinMax = true;
234  QgsRasterBandStats myRasterBandStats = mLayer->dataProvider()->bandStatistics( myBand, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, myExtent, mySampleSize );
235  double myStdDev = mStdDevSpinBox->value();
236  myMin = myRasterBandStats.mean - ( myStdDev * myRasterBandStats.stdDev );
237  myMax = myRasterBandStats.mean + ( myStdDev * myRasterBandStats.stdDev );
238  }
239 
240  if ( updateMinMax )
241  emit load( myBand, myMin, myMax );
242  }
243 }
244 
246 {
247  mStatisticsExtentCombo->removeItem( IDX_UPDATED_CANVAS );
248 }
QgsRasterMinMaxOrigin::Limits limits() const
Returns the raster limits.
virtual int bandCount() const =0
Gets number of bands.
QgsRasterMinMaxOrigin::Extent extent() const
Returns the raster extent.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
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()
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:73
Current extent of the canvas (at the time of computation) is used to compute statistics.
void setExtent(QgsRasterMinMaxOrigin::Extent extent)
Sets the extent.
double cumulativeCutLower() const
Returns the 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
Returns the layer&#39;s data provider, it may be nullptr.
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
Returns the 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)
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.
const QgsMapSettings & mapSettings() const
Gets 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)
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 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
Returns the raster statistic accuracy.
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).
double stdDevFactor() const
Returns the 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 &)
Sets the "source" of min/max values.