QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgspointcloudrgbrendererwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointcloudrgbrendererwidget.cpp
3  ---------------------
4  begin : November 2020
5  copyright : (C) 2020 by Nyall Dawson
6  email : nyall dot dawson 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 
19 #include "qgscontrastenhancement.h"
20 #include "qgspointcloudlayer.h"
22 #include "qgsdoublevalidator.h"
23 
25 
26 QgsPointCloudRgbRendererWidget::QgsPointCloudRgbRendererWidget( QgsPointCloudLayer *layer, QgsStyle *style )
27  : QgsPointCloudRendererWidget( layer, style )
28 {
29  setupUi( this );
30  connect( mRedMinLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mRedMinLineEdit_textChanged );
31  connect( mRedMaxLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mRedMaxLineEdit_textChanged );
32  connect( mGreenMinLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mGreenMinLineEdit_textChanged );
33  connect( mGreenMaxLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mGreenMaxLineEdit_textChanged );
34  connect( mBlueMinLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mBlueMinLineEdit_textChanged );
35  connect( mBlueMaxLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mBlueMaxLineEdit_textChanged );
36  createValidators();
37 
38  mRedAttributeComboBox->setAllowEmptyAttributeName( true );
39  mGreenAttributeComboBox->setAllowEmptyAttributeName( true );
40  mBlueAttributeComboBox->setAllowEmptyAttributeName( true );
41 
42  //contrast enhancement algorithms
43  mContrastEnhancementAlgorithmComboBox->addItem( tr( "No Enhancement" ), QgsContrastEnhancement::NoEnhancement );
44  mContrastEnhancementAlgorithmComboBox->addItem( tr( "Stretch to MinMax" ), QgsContrastEnhancement::StretchToMinimumMaximum );
45  mContrastEnhancementAlgorithmComboBox->addItem( tr( "Stretch and Clip to MinMax" ), QgsContrastEnhancement::StretchAndClipToMinimumMaximum );
46  mContrastEnhancementAlgorithmComboBox->addItem( tr( "Clip to MinMax" ), QgsContrastEnhancement::ClipToMinimumMaximum );
47 
48  if ( layer )
49  {
50  mRedAttributeComboBox->setLayer( layer );
51  mGreenAttributeComboBox->setLayer( layer );
52  mBlueAttributeComboBox->setLayer( layer );
53 
54  setFromRenderer( layer->renderer() );
55  }
56 
57  connect( mRedAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged,
58  this, &QgsPointCloudRgbRendererWidget::redAttributeChanged );
59  connect( mGreenAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged,
60  this, &QgsPointCloudRgbRendererWidget::greenAttributeChanged );
61  connect( mBlueAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged,
62  this, &QgsPointCloudRgbRendererWidget::blueAttributeChanged );
63  connect( mContrastEnhancementAlgorithmComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRgbRendererWidget::emitWidgetChanged );
64 
65  if ( layer )
66  {
67  // set nice initial values
68  redAttributeChanged();
69  greenAttributeChanged();
70  blueAttributeChanged();
71  }
72 }
73 
74 QgsPointCloudRendererWidget *QgsPointCloudRgbRendererWidget::create( QgsPointCloudLayer *layer, QgsStyle *style, QgsPointCloudRenderer * )
75 {
76  return new QgsPointCloudRgbRendererWidget( layer, style );
77 }
78 
79 QgsPointCloudRenderer *QgsPointCloudRgbRendererWidget::renderer()
80 {
81  if ( !mLayer )
82  {
83  return nullptr;
84  }
85 
86  std::unique_ptr< QgsPointCloudRgbRenderer > renderer = std::make_unique< QgsPointCloudRgbRenderer >();
87  renderer->setRedAttribute( mRedAttributeComboBox->currentAttribute() );
88  renderer->setGreenAttribute( mGreenAttributeComboBox->currentAttribute() );
89  renderer->setBlueAttribute( mBlueAttributeComboBox->currentAttribute() );
90 
91  setCustomMinMaxValues( renderer.get() );
92  return renderer.release();
93 }
94 
95 void QgsPointCloudRgbRendererWidget::createValidators()
96 {
97  mRedMinLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
98  mRedMaxLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
99  mGreenMinLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
100  mGreenMaxLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
101  mBlueMinLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
102  mBlueMaxLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
103 }
104 
105 void QgsPointCloudRgbRendererWidget::setCustomMinMaxValues( QgsPointCloudRgbRenderer *r )
106 {
107  if ( !r )
108  {
109  return;
110  }
111 
112  if ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ==
114  {
115  r->setRedContrastEnhancement( nullptr );
116  r->setGreenContrastEnhancement( nullptr );
117  r->setBlueContrastEnhancement( nullptr );
118  return;
119  }
120 
121  QgsContrastEnhancement *redEnhancement = nullptr;
122  QgsContrastEnhancement *greenEnhancement = nullptr;
123  QgsContrastEnhancement *blueEnhancement = nullptr;
124 
125  bool redMinOk, redMaxOk;
126  double redMin = QgsDoubleValidator::toDouble( mRedMinLineEdit->text(), &redMinOk );
127  double redMax = QgsDoubleValidator::toDouble( mRedMaxLineEdit->text(), &redMaxOk );
128  if ( redMinOk && redMaxOk && !mRedAttributeComboBox->currentAttribute().isEmpty() )
129  {
131  redEnhancement->setMinimumValue( redMin );
132  redEnhancement->setMaximumValue( redMax );
133  }
134 
135  bool greenMinOk, greenMaxOk;
136  double greenMin = QgsDoubleValidator::toDouble( mGreenMinLineEdit->text(), &greenMinOk );
137  double greenMax = QgsDoubleValidator::toDouble( mGreenMaxLineEdit->text(), &greenMaxOk );
138  if ( greenMinOk && greenMaxOk && !mGreenAttributeComboBox->currentAttribute().isEmpty() )
139  {
141  greenEnhancement->setMinimumValue( greenMin );
142  greenEnhancement->setMaximumValue( greenMax );
143  }
144 
145  bool blueMinOk, blueMaxOk;
146  double blueMin = QgsDoubleValidator::toDouble( mBlueMinLineEdit->text(), &blueMinOk );
147  double blueMax = QgsDoubleValidator::toDouble( mBlueMaxLineEdit->text(), &blueMaxOk );
148  if ( blueMinOk && blueMaxOk && !mBlueAttributeComboBox->currentAttribute().isEmpty() )
149  {
151  blueEnhancement->setMinimumValue( blueMin );
152  blueEnhancement->setMaximumValue( blueMax );
153  }
154 
155  if ( redEnhancement )
156  {
158  ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
159  }
160  if ( greenEnhancement )
161  {
163  ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
164  }
165  if ( blueEnhancement )
166  {
168  ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
169  }
170  r->setRedContrastEnhancement( redEnhancement );
171  r->setGreenContrastEnhancement( greenEnhancement );
172  r->setBlueContrastEnhancement( blueEnhancement );
173 }
174 
175 void QgsPointCloudRgbRendererWidget::mRedMinLineEdit_textChanged( const QString & )
176 {
177  minMaxModified();
178 }
179 
180 void QgsPointCloudRgbRendererWidget::mRedMaxLineEdit_textChanged( const QString & )
181 {
182  minMaxModified();
183 }
184 
185 void QgsPointCloudRgbRendererWidget::mGreenMinLineEdit_textChanged( const QString & )
186 {
187  minMaxModified();
188 }
189 
190 void QgsPointCloudRgbRendererWidget::mGreenMaxLineEdit_textChanged( const QString & )
191 {
192  minMaxModified();
193 }
194 
195 void QgsPointCloudRgbRendererWidget::mBlueMinLineEdit_textChanged( const QString & )
196 {
197  minMaxModified();
198 }
199 
200 void QgsPointCloudRgbRendererWidget::mBlueMaxLineEdit_textChanged( const QString & )
201 {
202  minMaxModified();
203 }
204 
205 void QgsPointCloudRgbRendererWidget::emitWidgetChanged()
206 {
207  if ( !mBlockChangedSignal )
208  emit widgetChanged();
209 }
210 
211 void QgsPointCloudRgbRendererWidget::redAttributeChanged()
212 {
213  if ( mLayer && mLayer->dataProvider() )
214  {
215  const QVariant max = mLayer->dataProvider()->metadataStatistic( mRedAttributeComboBox->currentAttribute(), QgsStatisticalSummary::Max );
216  if ( max.isValid() )
217  {
218  const int maxValue = max.toInt();
219  mDisableMinMaxWidgetRefresh++;
220  mRedMinLineEdit->setText( QLocale().toString( 0 ) );
221 
222  // try and guess suitable range from input max values -- we don't just take the provider max value directly here, but rather see if it's
223  // likely to be 8 bit or 16 bit color values
224  mRedMaxLineEdit->setText( QLocale().toString( maxValue > 255 ? 65535 : 255 ) );
225  mDisableMinMaxWidgetRefresh--;
226  emitWidgetChanged();
227  }
228  }
229 }
230 
231 void QgsPointCloudRgbRendererWidget::greenAttributeChanged()
232 {
233  if ( mLayer && mLayer->dataProvider() )
234  {
235  const QVariant max = mLayer->dataProvider()->metadataStatistic( mGreenAttributeComboBox->currentAttribute(), QgsStatisticalSummary::Max );
236  if ( max.isValid() )
237  {
238  const int maxValue = max.toInt();
239  mDisableMinMaxWidgetRefresh++;
240  mGreenMinLineEdit->setText( QLocale().toString( 0 ) );
241 
242  // try and guess suitable range from input max values -- we don't just take the provider max value directly here, but rather see if it's
243  // likely to be 8 bit or 16 bit color values
244  mGreenMaxLineEdit->setText( QLocale().toString( maxValue > 255 ? 65535 : 255 ) );
245  mDisableMinMaxWidgetRefresh--;
246  emitWidgetChanged();
247  }
248  }
249 }
250 
251 void QgsPointCloudRgbRendererWidget::blueAttributeChanged()
252 {
253  if ( mLayer && mLayer->dataProvider() )
254  {
255  const QVariant max = mLayer->dataProvider()->metadataStatistic( mBlueAttributeComboBox->currentAttribute(), QgsStatisticalSummary::Max );
256  if ( max.isValid() )
257  {
258  const int maxValue = max.toInt();
259  mDisableMinMaxWidgetRefresh++;
260  mBlueMinLineEdit->setText( QLocale().toString( 0 ) );
261 
262  // try and guess suitable range from input max values -- we don't just take the provider max value directly here, but rather see if it's
263  // likely to be 8 bit or 16 bit color values
264  mBlueMaxLineEdit->setText( QLocale().toString( maxValue > 255 ? 65535 : 255 ) );
265  mDisableMinMaxWidgetRefresh--;
266  emitWidgetChanged();
267  }
268  }
269 }
270 
271 void QgsPointCloudRgbRendererWidget::minMaxModified()
272 {
273  if ( !mDisableMinMaxWidgetRefresh )
274  {
275  if ( ( QgsContrastEnhancement::ContrastEnhancementAlgorithm )( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) == QgsContrastEnhancement::NoEnhancement )
276  {
277  mContrastEnhancementAlgorithmComboBox->setCurrentIndex(
278  mContrastEnhancementAlgorithmComboBox->findData( ( int ) QgsContrastEnhancement::StretchToMinimumMaximum ) );
279  }
280  emitWidgetChanged();
281  }
282 }
283 
284 void QgsPointCloudRgbRendererWidget::setMinMaxValue( const QgsContrastEnhancement *ce, QLineEdit *minEdit, QLineEdit *maxEdit )
285 {
286  if ( !minEdit || !maxEdit )
287  {
288  return;
289  }
290 
291  if ( !ce )
292  {
293  minEdit->clear();
294  maxEdit->clear();
295  return;
296  }
297 
298  minEdit->setText( QLocale().toString( ce->minimumValue() ) );
299  maxEdit->setText( QLocale().toString( ce->maximumValue() ) );
300 
301  // QgsMultiBandColorRenderer is using individual contrast enhancements for each
302  // band, but this widget GUI has one for all
303  mContrastEnhancementAlgorithmComboBox->setCurrentIndex( mContrastEnhancementAlgorithmComboBox->findData(
304  static_cast< int >( ce->contrastEnhancementAlgorithm() ) ) );
305 }
306 
307 void QgsPointCloudRgbRendererWidget::setFromRenderer( const QgsPointCloudRenderer *r )
308 {
309  mBlockChangedSignal = true;
310  const QgsPointCloudRgbRenderer *mbcr = dynamic_cast<const QgsPointCloudRgbRenderer *>( r );
311  if ( mbcr )
312  {
313  mRedAttributeComboBox->setAttribute( mbcr->redAttribute() );
314  mGreenAttributeComboBox->setAttribute( mbcr->greenAttribute() );
315  mBlueAttributeComboBox->setAttribute( mbcr->blueAttribute() );
316 
317  mDisableMinMaxWidgetRefresh++;
318  setMinMaxValue( mbcr->redContrastEnhancement(), mRedMinLineEdit, mRedMaxLineEdit );
319  setMinMaxValue( mbcr->greenContrastEnhancement(), mGreenMinLineEdit, mGreenMaxLineEdit );
320  setMinMaxValue( mbcr->blueContrastEnhancement(), mBlueMinLineEdit, mBlueMaxLineEdit );
321  mDisableMinMaxWidgetRefresh--;
322  }
323  else
324  {
325  if ( mRedAttributeComboBox->findText( QStringLiteral( "Red" ) ) > -1 && mRedAttributeComboBox->findText( QStringLiteral( "Green" ) ) > -1 &&
326  mRedAttributeComboBox->findText( QStringLiteral( "Blue" ) ) > -1 )
327  {
328  mRedAttributeComboBox->setAttribute( QStringLiteral( "Red" ) );
329  mGreenAttributeComboBox->setAttribute( QStringLiteral( "Green" ) );
330  mBlueAttributeComboBox->setAttribute( QStringLiteral( "Blue" ) );
331  }
332  else
333  {
334  mRedAttributeComboBox->setCurrentIndex( mRedAttributeComboBox->count() > 1 ? 1 : 0 );
335  mGreenAttributeComboBox->setCurrentIndex( mGreenAttributeComboBox->count() > 2 ? 2 : 0 );
336  mBlueAttributeComboBox->setCurrentIndex( mBlueAttributeComboBox->count() > 3 ? 3 : 0 );
337  }
338  }
339  mBlockChangedSignal = false;
340 }
341 
@ UnknownDataType
Unknown or unspecified type.
Manipulates raster or point cloud pixel values so that they enhanceContrast or clip into a specified ...
ContrastEnhancementAlgorithm
This enumerator describes the types of contrast enhancement algorithms that can be used.
@ StretchToMinimumMaximum
Linear histogram.
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
void setMinimumValue(double value, bool generateTable=true)
Sets the minimum value for the contrast enhancement range.
void setContrastEnhancementAlgorithm(ContrastEnhancementAlgorithm algorithm, bool generateTable=true)
Sets the contrast enhancement algorithm.
double minimumValue() const
Returns the minimum value for the contrast enhancement range.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
void setMaximumValue(double value, bool generateTable=true)
Sets the maximum value for the contrast enhancement range.
double maximumValue() const
Returns the maximum value for the contrast enhancement range.
QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator and QRegularExpressionVali...
static double toDouble(const QString &input, bool *ok)
Converts input string to double value.
void attributeChanged(const QString &name)
Emitted when the currently selected attribute changes.
Represents a map layer supporting display of point clouds.
QgsPointCloudRenderer * renderer()
Returns the 2D renderer for the point cloud.
Base class for point cloud 2D renderer settings widgets.
Abstract base class for 2d point cloud renderers.
An RGB renderer for 2d visualisation of point clouds using embedded red, green and blue attributes.
void setRedContrastEnhancement(QgsContrastEnhancement *enhancement)
Sets the contrast enhancement to use for the red channel.
QString redAttribute() const
Returns the attribute to use for the red channel.
QString greenAttribute() const
Returns the attribute to use for the green channel.
void setBlueContrastEnhancement(QgsContrastEnhancement *enhancement)
Sets the contrast enhancement to use for the blue channel.
const QgsContrastEnhancement * greenContrastEnhancement() const
Returns the contrast enhancement to use for the green channel.
QString blueAttribute() const
Returns the attribute to use for the blue channel.
void setGreenContrastEnhancement(QgsContrastEnhancement *enhancement)
Sets the contrast enhancement to use for the green channel.
const QgsContrastEnhancement * blueContrastEnhancement() const
Returns the contrast enhancement to use for the blue channel.
const QgsContrastEnhancement * redContrastEnhancement() const
Returns the contrast enhancement to use for the red channel.