QGIS API Documentation  3.20.0-Odense (decaadbb31)
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  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
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
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 
173  mCumulativeCutLowerDoubleSpinBox->value() / 100.0 );
175  mCumulativeCutUpperDoubleSpinBox->value() / 100.0 );
176  minMaxOrigin.setStdDevFactor( mStdDevSpinBox->value() );
177 
178  return minMaxOrigin;
179 }
180 
182 {
183  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
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 }
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:86
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
QgsRectangle outputExtentToLayerExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from output CRS to layer's CRS
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.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
double maximumValue
The maximum cell value in the raster band.
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.
virtual int bandCount() const =0
Gets number of bands.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
Represents a raster layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
This class describes the origin of min/max values.
void setExtent(QgsRasterMinMaxOrigin::Extent extent)
Sets the extent.
QgsRasterMinMaxOrigin::StatAccuracy statAccuracy() const
Returns the raster statistic accuracy.
double cumulativeCutLower() const
Returns the lower bound of cumulative cut method (between 0 and 1).
@ Exact
Exact statistics.
@ Estimated
Approximated statistics.
QgsRasterMinMaxOrigin::Limits limits() const
Returns the raster limits.
double stdDevFactor() const
Returns the factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ].
void setLimits(QgsRasterMinMaxOrigin::Limits limits)
Sets the limits.
void setStatAccuracy(QgsRasterMinMaxOrigin::StatAccuracy accuracy)
Sets the statistics accuracy.
@ UpdatedCanvas
Constantly updated extent of the canvas is used to compute statistics.
@ CurrentCanvas
Current extent of the canvas (at the time of computation) is used to compute statistics.
@ WholeRaster
Whole raster is used to compute statistics.
void setCumulativeCutUpper(double val)
Sets the upper bound of cumulative cut method (between 0 and 1).
void setStdDevFactor(double val)
Sets the factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ].
double cumulativeCutUpper() const
Returns the upper bound of cumulative cut method (between 0 and 1).
void setCumulativeCutLower(double val)
Sets the lower bound of cumulative cut method (between 0 and 1).
@ StdDev
Range is [ mean - stdDevFactor() * stddev, mean + stdDevFactor() * stddev ].
@ MinMax
Real min-max values.
@ CumulativeCut
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ].
QgsRasterMinMaxOrigin::Extent extent() const
Returns the raster extent.
QgsRectangle extent()
Returns the extent selected by the user.
QgsRasterMinMaxWidget(QgsRasterLayer *layer, QWidget *parent=nullptr)
Constructor for QgsRasterMinMaxWidget.
void doComputations()
Load programmatically with current values.
QgsMapCanvas * mapCanvas()
Returns the map canvas associated with the widget.
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void load(int bandNo, double min, double max)
signal emitted when new min/max values are computed from statistics.
void setFromMinMaxOrigin(const QgsRasterMinMaxOrigin &)
Sets the "source" of min/max values.
int sampleSize()
Returns the selected sample size.
void setBands(const QList< int > &bands)
void hideUpdatedExtent()
Hide updated extent choice.
QgsRasterMinMaxOrigin minMaxOrigin()
Returns a QgsRasterMinMaxOrigin object with the widget values.
void widgetChanged()
Emitted when something on the widget has changed.
void userHasSetManualMinMaxValues()
Uncheck cumulative cut, min/max, std-dev radio buttons.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
const int IDX_CURRENT_CANVAS
const int IDX_WHOLE_RASTER
const int IDX_UPDATED_CANVAS