QGIS API Documentation  2.99.0-Master (0a63d1f)
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( theLayer )
35  , mCanvas( nullptr )
36  , mLastRectangleValid( false )
37  , mBandsChanged( false )
38 {
39  QgsDebugMsg( "Entered." );
40  setupUi( this );
41 
42  QgsRasterMinMaxOrigin defaultMinMaxOrigin;
43  setFromMinMaxOrigin( defaultMinMaxOrigin );
44 }
45 
47 {
48  mCanvas = canvas;
49 }
50 
52 {
53  return mCanvas;
54 }
55 
56 void QgsRasterMinMaxWidget::setBands( const QList<int> & theBands )
57 {
58  mBandsChanged = theBands != mBands;
59  mBands = theBands;
60 }
61 
63 {
64  const int nExtentIdx = mStatisticsExtentCombo->currentIndex();
65  if ( nExtentIdx != IDX_CURRENT_CANVAS && nExtentIdx != IDX_UPDATED_CANVAS )
66  return QgsRectangle();
67 
68  if ( mLayer && mCanvas )
69  return mCanvas->mapSettings().outputExtentToLayerExtent( mLayer, mCanvas->extent() );
70  else if ( mCanvas )
71  return mCanvas->extent();
72  else
73  return QgsRectangle();
74 }
75 
77 {
78  mUserDefinedRadioButton->setChecked( true );
79  mStatisticsExtentCombo->setCurrentIndex( IDX_WHOLE_RASTER );
80 }
81 
82 void QgsRasterMinMaxWidget::on_mUserDefinedRadioButton_toggled( bool toggled )
83 {
84  mStatisticsExtentCombo->setEnabled( !toggled );
85  cboAccuracy->setEnabled( !toggled );
86  emit widgetChanged();
87 }
88 
90 {
91  switch ( minMaxOrigin.limits() )
92  {
94  default:
95  mUserDefinedRadioButton->setChecked( true );
96  break;
97 
99  mMinMaxRadioButton->setChecked( true );
100  break;
101 
103  mStdDevRadioButton->setChecked( true );
104  break;
105 
107  mCumulativeCutRadioButton->setChecked( true );
108  break;
109  }
110 
111  switch ( minMaxOrigin.extent() )
112  {
113  default:
115  mStatisticsExtentCombo->setCurrentIndex( IDX_WHOLE_RASTER );
116  break;
117 
119  mStatisticsExtentCombo->setCurrentIndex( IDX_CURRENT_CANVAS );
120  break;
121 
123  mStatisticsExtentCombo->setCurrentIndex( IDX_UPDATED_CANVAS );
124  break;
125  }
126 
127  mCumulativeCutLowerDoubleSpinBox->setValue( 100.0 * minMaxOrigin.cumulativeCutLower() );
128  mCumulativeCutUpperDoubleSpinBox->setValue( 100.0 * minMaxOrigin.cumulativeCutUpper() );
129  mStdDevSpinBox->setValue( minMaxOrigin.stdDevFactor() );
130 
131  cboAccuracy->setCurrentIndex( minMaxOrigin.statAccuracy() == QgsRasterMinMaxOrigin::Estimated ? 0 : 1 );
132 }
133 
135 {
137 
138  if ( mMinMaxRadioButton->isChecked() )
140  else if ( mStdDevRadioButton->isChecked() )
142  else if ( mCumulativeCutRadioButton->isChecked() )
144  else
145  minMaxOrigin.setLimits( QgsRasterMinMaxOrigin::None );
146 
147  switch ( mStatisticsExtentCombo->currentIndex() )
148  {
149  case IDX_WHOLE_RASTER:
150  default:
152  break;
153  case IDX_CURRENT_CANVAS:
155  break;
156  case IDX_UPDATED_CANVAS:
158  break;
159  }
160 
161  if ( cboAccuracy->currentIndex() == 0 )
163  else
165 
166  minMaxOrigin.setCumulativeCutLower(
167  mCumulativeCutLowerDoubleSpinBox->value() / 100.0 );
168  minMaxOrigin.setCumulativeCutUpper(
169  mCumulativeCutUpperDoubleSpinBox->value() / 100.0 );
170  minMaxOrigin.setStdDevFactor( mStdDevSpinBox->value() );
171 
172  return minMaxOrigin;
173 }
174 
176 {
177  QgsDebugMsg( "Entered." );
178 
179  QgsRectangle myExtent = extent(); // empty == full
180  int mySampleSize = sampleSize(); // 0 == exact
181 
182  QgsRasterMinMaxOrigin newMinMaxOrigin = minMaxOrigin();
183  if ( mLastRectangleValid && mLastRectangle == myExtent &&
184  mLastMinMaxOrigin == newMinMaxOrigin &&
185  !mBandsChanged )
186  {
187  QgsDebugMsg( "Does not need to redo statistics computations" );
188  return;
189  }
190 
191  mLastRectangleValid = true;
192  mLastRectangle = myExtent;
193  mLastMinMaxOrigin = newMinMaxOrigin;
194  mBandsChanged = false;
195 
196  Q_FOREACH ( int myBand, mBands )
197  {
198  QgsDebugMsg( QString( "myBand = %1" ).arg( myBand ) );
199  if ( myBand < 1 || myBand > mLayer->dataProvider()->bandCount() )
200  {
201  continue;
202  }
203  double myMin = std::numeric_limits<double>::quiet_NaN();
204  double myMax = std::numeric_limits<double>::quiet_NaN();
205 
206  bool updateMinMax = false;
207  if ( mCumulativeCutRadioButton->isChecked() )
208  {
209  updateMinMax = true;
210  double myLower = mCumulativeCutLowerDoubleSpinBox->value() / 100.0;
211  double myUpper = mCumulativeCutUpperDoubleSpinBox->value() / 100.0;
212  mLayer->dataProvider()->cumulativeCut( myBand, myLower, myUpper, myMin, myMax, myExtent, mySampleSize );
213  }
214  else if ( mMinMaxRadioButton->isChecked() )
215  {
216  updateMinMax = true;
217  // TODO: consider provider minimum/maximumValue() (has to be defined well in povider)
218  QgsRasterBandStats myRasterBandStats = mLayer->dataProvider()->bandStatistics( myBand, QgsRasterBandStats::Min | QgsRasterBandStats::Max, myExtent, mySampleSize );
219  myMin = myRasterBandStats.minimumValue;
220  myMax = myRasterBandStats.maximumValue;
221  }
222  else if ( mStdDevRadioButton->isChecked() )
223  {
224  updateMinMax = true;
225  QgsRasterBandStats myRasterBandStats = mLayer->dataProvider()->bandStatistics( myBand, QgsRasterBandStats::Mean | QgsRasterBandStats::StdDev, myExtent, mySampleSize );
226  double myStdDev = mStdDevSpinBox->value();
227  myMin = myRasterBandStats.mean - ( myStdDev * myRasterBandStats.stdDev );
228  myMax = myRasterBandStats.mean + ( myStdDev * myRasterBandStats.stdDev );
229  }
230 
231  if ( updateMinMax )
232  emit load( myBand, myMin, myMax );
233  }
234 }
235 
237 {
238  mStatisticsExtentCombo->removeItem( IDX_UPDATED_CANVAS );
239 }
virtual int bandCount() const =0
Get number of bands.
void setStatAccuracy(StatAccuracy theAccuracy)
Set statistics accuracy.
A rectangle specified with double values.
Definition: qgsrectangle.h:36
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
void setBands(const QList< int > &theBands)
double maximumValue
The maximum cell value in the raster band.
QgsRasterMinMaxOrigin minMaxOrigin()
Return a QgsRasterMinMaxOrigin object with the widget values.
void setExtent(Extent theExtent)
Set extent.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:74
StatAccuracy statAccuracy() const
Return statistic accuracy.
Current extent of the canvas (at the time of computation) is used to compute statistics.
double cumulativeCutLower() const
Return lower bound of cumulative cut method (between 0 and 1).
void widgetChanged()
Emitted when something on the widget has changed.
virtual QgsRasterBandStats bandStatistics(int theBandNo, int theStats=QgsRasterBandStats::All, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0)
Get band statistics.
double stdDev
The standard deviation of the cell values.
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 setLimits(Limits theLimits)
Set limits.
double cumulativeCutUpper() const
Return upper bound of cumulative cut method (between 0 and 1).
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
Constantly updated extent of the canvas is used to compute statistics.
QgsRasterMinMaxWidget(QgsRasterLayer *theLayer, QWidget *parent=nullptr)
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) ]...
void load(int theBandNo, double theMin, double theMax)
signal emitted when new min/max values are computed from statistics.
int sampleSize()
Return the selected sample size.
void setCumulativeCutLower(double val)
Set lower bound of cumulative cut method (between 0 and 1).
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
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.
Whole raster is used to compute statistics.
Extent extent() const
Return extent.
double minimumValue
The minimum cell value in the raster band.
QgsRasterDataProvider * dataProvider()
Returns the data provider.
const int IDX_CURRENT_CANVAS
virtual void cumulativeCut(int theBandNo, double theLowerCount, double theUpperCount, double &theLowerValue, double &theUpperValue, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0)
Find values for cumulative pixel count cut.
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 ]...
Limits limits() const
Return limits.
QgsRectangle outputExtentToLayerExtent(QgsMapLayer *theLayer, QgsRectangle extent) const
transform bounding box from output CRS to layer&#39;s CRS
void doComputations()
Load programmatically with current values.
const int IDX_WHOLE_RASTER
void setFromMinMaxOrigin(const QgsRasterMinMaxOrigin &)
Set the "source" of min/max values.