QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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  mUserDefinedRadioButton->setChecked( true );
103  break;
104 
106  mMinMaxRadioButton->setChecked( true );
107  break;
108 
110  mStdDevRadioButton->setChecked( true );
111  break;
112 
114  mCumulativeCutRadioButton->setChecked( true );
115  break;
116  }
117 
118  switch ( minMaxOrigin.extent() )
119  {
121  mStatisticsExtentCombo->setCurrentIndex( IDX_WHOLE_RASTER );
122  break;
123 
125  mStatisticsExtentCombo->setCurrentIndex( IDX_CURRENT_CANVAS );
126  break;
127 
129  mStatisticsExtentCombo->setCurrentIndex( IDX_UPDATED_CANVAS );
130  break;
131  }
132 
133  mCumulativeCutLowerDoubleSpinBox->setValue( 100.0 * minMaxOrigin.cumulativeCutLower() );
134  mCumulativeCutUpperDoubleSpinBox->setValue( 100.0 * minMaxOrigin.cumulativeCutUpper() );
135  mStdDevSpinBox->setValue( minMaxOrigin.stdDevFactor() );
136 
137  cboAccuracy->setCurrentIndex( minMaxOrigin.statAccuracy() == QgsRasterMinMaxOrigin::Estimated ? 0 : 1 );
138 }
139 
141 {
143 
144  if ( mMinMaxRadioButton->isChecked() )
146  else if ( mStdDevRadioButton->isChecked() )
148  else if ( mCumulativeCutRadioButton->isChecked() )
150  else
151  minMaxOrigin.setLimits( QgsRasterMinMaxOrigin::None );
152 
153  switch ( mStatisticsExtentCombo->currentIndex() )
154  {
155  case IDX_WHOLE_RASTER:
156  default:
158  break;
159  case IDX_CURRENT_CANVAS:
161  break;
162  case IDX_UPDATED_CANVAS:
164  break;
165  }
166 
167  if ( cboAccuracy->currentIndex() == 0 )
169  else
171 
172  minMaxOrigin.setCumulativeCutLower(
173  mCumulativeCutLowerDoubleSpinBox->value() / 100.0 );
174  minMaxOrigin.setCumulativeCutUpper(
175  mCumulativeCutUpperDoubleSpinBox->value() / 100.0 );
176  minMaxOrigin.setStdDevFactor( mStdDevSpinBox->value() );
177 
178  return minMaxOrigin;
179 }
180 
182 {
183  QgsDebugMsg( QStringLiteral( "Entered." ) );
184  if ( !mLayer->dataProvider() )
185  return;
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:75
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 source data provider.
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.