QGIS API Documentation 3.41.0-Master (3440c17df1d)
Loading...
Searching...
No Matches
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 "moc_qgspointcloudrgbrendererwidget.cpp"
21#include "qgspointcloudlayer.h"
23#include "qgsdoublevalidator.h"
24
26
27QgsPointCloudRgbRendererWidget::QgsPointCloudRgbRendererWidget( QgsPointCloudLayer *layer, QgsStyle *style )
28 : QgsPointCloudRendererWidget( layer, style )
29{
30 setupUi( this );
31 connect( mRedMinLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mRedMinLineEdit_textChanged );
32 connect( mRedMaxLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mRedMaxLineEdit_textChanged );
33 connect( mGreenMinLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mGreenMinLineEdit_textChanged );
34 connect( mGreenMaxLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mGreenMaxLineEdit_textChanged );
35 connect( mBlueMinLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mBlueMinLineEdit_textChanged );
36 connect( mBlueMaxLineEdit, &QLineEdit::textChanged, this, &QgsPointCloudRgbRendererWidget::mBlueMaxLineEdit_textChanged );
37 createValidators();
38
39 mRedAttributeComboBox->setAllowEmptyAttributeName( true );
40 mGreenAttributeComboBox->setAllowEmptyAttributeName( true );
41 mBlueAttributeComboBox->setAllowEmptyAttributeName( true );
42
43 //contrast enhancement algorithms
44 mContrastEnhancementAlgorithmComboBox->addItem( tr( "No Enhancement" ), QgsContrastEnhancement::NoEnhancement );
45 mContrastEnhancementAlgorithmComboBox->addItem( tr( "Stretch to MinMax" ), QgsContrastEnhancement::StretchToMinimumMaximum );
46 mContrastEnhancementAlgorithmComboBox->addItem( tr( "Stretch and Clip to MinMax" ), QgsContrastEnhancement::StretchAndClipToMinimumMaximum );
47 mContrastEnhancementAlgorithmComboBox->addItem( tr( "Clip to MinMax" ), QgsContrastEnhancement::ClipToMinimumMaximum );
48
49 if ( layer )
50 {
51 mRedAttributeComboBox->setLayer( layer );
52 mGreenAttributeComboBox->setLayer( layer );
53 mBlueAttributeComboBox->setLayer( layer );
54
55 setFromRenderer( layer->renderer() );
56 }
57
58 connect( mRedAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged,
59 this, &QgsPointCloudRgbRendererWidget::redAttributeChanged );
60 connect( mGreenAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged,
61 this, &QgsPointCloudRgbRendererWidget::greenAttributeChanged );
62 connect( mBlueAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged,
63 this, &QgsPointCloudRgbRendererWidget::blueAttributeChanged );
64 connect( mContrastEnhancementAlgorithmComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRgbRendererWidget::emitWidgetChanged );
65
66 if ( layer )
67 {
68 // set nice initial values
69 mBlockChangedSignal = true;
70 redAttributeChanged();
71 greenAttributeChanged();
72 blueAttributeChanged();
73 mBlockChangedSignal = false;
74 minMaxModified();
75 }
76}
77
78QgsPointCloudRendererWidget *QgsPointCloudRgbRendererWidget::create( QgsPointCloudLayer *layer, QgsStyle *style, QgsPointCloudRenderer * )
79{
80 return new QgsPointCloudRgbRendererWidget( layer, style );
81}
82
83QgsPointCloudRenderer *QgsPointCloudRgbRendererWidget::renderer()
84{
85 if ( !mLayer )
86 {
87 return nullptr;
88 }
89
90 std::unique_ptr< QgsPointCloudRgbRenderer > renderer = std::make_unique< QgsPointCloudRgbRenderer >();
91 renderer->setRedAttribute( mRedAttributeComboBox->currentAttribute() );
92 renderer->setGreenAttribute( mGreenAttributeComboBox->currentAttribute() );
93 renderer->setBlueAttribute( mBlueAttributeComboBox->currentAttribute() );
94
95 setCustomMinMaxValues( renderer.get() );
96 return renderer.release();
97}
98
99void QgsPointCloudRgbRendererWidget::createValidators()
100{
101 mRedMinLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
102 mRedMaxLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
103 mGreenMinLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
104 mGreenMaxLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
105 mBlueMinLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
106 mBlueMaxLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
107}
108
109void QgsPointCloudRgbRendererWidget::setCustomMinMaxValues( QgsPointCloudRgbRenderer *r )
110{
111 if ( !r )
112 {
113 return;
114 }
115
116 if ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ==
118 {
119 r->setRedContrastEnhancement( nullptr );
120 r->setGreenContrastEnhancement( nullptr );
121 r->setBlueContrastEnhancement( nullptr );
122 return;
123 }
124
125 QgsContrastEnhancement *redEnhancement = nullptr;
126 QgsContrastEnhancement *greenEnhancement = nullptr;
127 QgsContrastEnhancement *blueEnhancement = nullptr;
128
129 bool redMinOk, redMaxOk;
130 const double redMin = QgsDoubleValidator::toDouble( mRedMinLineEdit->text(), &redMinOk );
131 const double redMax = QgsDoubleValidator::toDouble( mRedMaxLineEdit->text(), &redMaxOk );
132 if ( redMinOk && redMaxOk && !mRedAttributeComboBox->currentAttribute().isEmpty() )
133 {
135 redEnhancement->setMinimumValue( redMin );
136 redEnhancement->setMaximumValue( redMax );
137 }
138
139 bool greenMinOk, greenMaxOk;
140 const double greenMin = QgsDoubleValidator::toDouble( mGreenMinLineEdit->text(), &greenMinOk );
141 const double greenMax = QgsDoubleValidator::toDouble( mGreenMaxLineEdit->text(), &greenMaxOk );
142 if ( greenMinOk && greenMaxOk && !mGreenAttributeComboBox->currentAttribute().isEmpty() )
143 {
145 greenEnhancement->setMinimumValue( greenMin );
146 greenEnhancement->setMaximumValue( greenMax );
147 }
148
149 bool blueMinOk, blueMaxOk;
150 const double blueMin = QgsDoubleValidator::toDouble( mBlueMinLineEdit->text(), &blueMinOk );
151 const double blueMax = QgsDoubleValidator::toDouble( mBlueMaxLineEdit->text(), &blueMaxOk );
152 if ( blueMinOk && blueMaxOk && !mBlueAttributeComboBox->currentAttribute().isEmpty() )
153 {
155 blueEnhancement->setMinimumValue( blueMin );
156 blueEnhancement->setMaximumValue( blueMax );
157 }
158
159 if ( redEnhancement )
160 {
162 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
163 }
164 if ( greenEnhancement )
165 {
167 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
168 }
169 if ( blueEnhancement )
170 {
172 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
173 }
174 r->setRedContrastEnhancement( redEnhancement );
175 r->setGreenContrastEnhancement( greenEnhancement );
176 r->setBlueContrastEnhancement( blueEnhancement );
177}
178
179void QgsPointCloudRgbRendererWidget::mRedMinLineEdit_textChanged( const QString & )
180{
181 minMaxModified();
182}
183
184void QgsPointCloudRgbRendererWidget::mRedMaxLineEdit_textChanged( const QString & )
185{
186 minMaxModified();
187}
188
189void QgsPointCloudRgbRendererWidget::mGreenMinLineEdit_textChanged( const QString & )
190{
191 minMaxModified();
192}
193
194void QgsPointCloudRgbRendererWidget::mGreenMaxLineEdit_textChanged( const QString & )
195{
196 minMaxModified();
197}
198
199void QgsPointCloudRgbRendererWidget::mBlueMinLineEdit_textChanged( const QString & )
200{
201 minMaxModified();
202}
203
204void QgsPointCloudRgbRendererWidget::mBlueMaxLineEdit_textChanged( const QString & )
205{
206 minMaxModified();
207}
208
209void QgsPointCloudRgbRendererWidget::emitWidgetChanged()
210{
211 if ( !mBlockChangedSignal )
212 emit widgetChanged();
213}
214
215void QgsPointCloudRgbRendererWidget::redAttributeChanged()
216{
217 if ( mLayer && mLayer->dataProvider() )
218 {
219 const QgsPointCloudStatistics stats = mLayer->statistics();
220 const double max = stats.maximum( mRedAttributeComboBox->currentAttribute() );
221 if ( !std::isnan( max ) )
222 {
223 mDisableMinMaxWidgetRefresh++;
224 mRedMinLineEdit->setText( QLocale().toString( 0 ) );
225
226 // 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
227 // likely to be 8 bit or 16 bit color values
228 mRedMaxLineEdit->setText( QLocale().toString( max > 255 ? 65535 : 255 ) );
229 mDisableMinMaxWidgetRefresh--;
230 emitWidgetChanged();
231 }
232 }
233}
234
235void QgsPointCloudRgbRendererWidget::greenAttributeChanged()
236{
237 if ( mLayer && mLayer->dataProvider() )
238 {
239 const QgsPointCloudStatistics stats = mLayer->statistics();
240 const double max = stats.maximum( mGreenAttributeComboBox->currentAttribute() );
241 if ( !std::isnan( max ) )
242 {
243 mDisableMinMaxWidgetRefresh++;
244 mGreenMinLineEdit->setText( QLocale().toString( 0 ) );
245
246 // 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
247 // likely to be 8 bit or 16 bit color values
248 mGreenMaxLineEdit->setText( QLocale().toString( max > 255 ? 65535 : 255 ) );
249 mDisableMinMaxWidgetRefresh--;
250 emitWidgetChanged();
251 }
252 }
253}
254
255void QgsPointCloudRgbRendererWidget::blueAttributeChanged()
256{
257 if ( mLayer && mLayer->dataProvider() )
258 {
259 const QgsPointCloudStatistics stats = mLayer->statistics();
260 const double max = stats.maximum( mBlueAttributeComboBox->currentAttribute() );
261 if ( !std::isnan( max ) )
262 {
263 mDisableMinMaxWidgetRefresh++;
264 mBlueMinLineEdit->setText( QLocale().toString( 0 ) );
265
266 // 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
267 // likely to be 8 bit or 16 bit color values
268 mBlueMaxLineEdit->setText( QLocale().toString( max > 255 ? 65535 : 255 ) );
269 mDisableMinMaxWidgetRefresh--;
270 emitWidgetChanged();
271 }
272 }
273}
274
275void QgsPointCloudRgbRendererWidget::minMaxModified()
276{
277 if ( !mDisableMinMaxWidgetRefresh )
278 {
279 if ( ( QgsContrastEnhancement::ContrastEnhancementAlgorithm )( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) == QgsContrastEnhancement::NoEnhancement )
280 {
281 mContrastEnhancementAlgorithmComboBox->setCurrentIndex(
282 mContrastEnhancementAlgorithmComboBox->findData( ( int ) QgsContrastEnhancement::StretchToMinimumMaximum ) );
283 }
284 emitWidgetChanged();
285 }
286}
287
288void QgsPointCloudRgbRendererWidget::setMinMaxValue( const QgsContrastEnhancement *ce, QLineEdit *minEdit, QLineEdit *maxEdit )
289{
290 if ( !minEdit || !maxEdit )
291 {
292 return;
293 }
294
295 if ( !ce )
296 {
297 minEdit->clear();
298 maxEdit->clear();
299 return;
300 }
301
302 minEdit->setText( QLocale().toString( ce->minimumValue() ) );
303 maxEdit->setText( QLocale().toString( ce->maximumValue() ) );
304
305 // QgsMultiBandColorRenderer is using individual contrast enhancements for each
306 // band, but this widget GUI has one for all
307 mContrastEnhancementAlgorithmComboBox->setCurrentIndex( mContrastEnhancementAlgorithmComboBox->findData(
308 static_cast< int >( ce->contrastEnhancementAlgorithm() ) ) );
309}
310
311void QgsPointCloudRgbRendererWidget::setFromRenderer( const QgsPointCloudRenderer *r )
312{
313 mBlockChangedSignal = true;
314 const QgsPointCloudRgbRenderer *mbcr = dynamic_cast<const QgsPointCloudRgbRenderer *>( r );
315 if ( mbcr )
316 {
317 mRedAttributeComboBox->setAttribute( mbcr->redAttribute() );
318 mGreenAttributeComboBox->setAttribute( mbcr->greenAttribute() );
319 mBlueAttributeComboBox->setAttribute( mbcr->blueAttribute() );
320
321 mDisableMinMaxWidgetRefresh++;
322 setMinMaxValue( mbcr->redContrastEnhancement(), mRedMinLineEdit, mRedMaxLineEdit );
323 setMinMaxValue( mbcr->greenContrastEnhancement(), mGreenMinLineEdit, mGreenMaxLineEdit );
324 setMinMaxValue( mbcr->blueContrastEnhancement(), mBlueMinLineEdit, mBlueMaxLineEdit );
325 mDisableMinMaxWidgetRefresh--;
326 }
327 else
328 {
329 if ( mRedAttributeComboBox->findText( QStringLiteral( "Red" ) ) > -1 && mRedAttributeComboBox->findText( QStringLiteral( "Green" ) ) > -1 &&
330 mRedAttributeComboBox->findText( QStringLiteral( "Blue" ) ) > -1 )
331 {
332 mRedAttributeComboBox->setAttribute( QStringLiteral( "Red" ) );
333 mGreenAttributeComboBox->setAttribute( QStringLiteral( "Green" ) );
334 mBlueAttributeComboBox->setAttribute( QStringLiteral( "Blue" ) );
335 }
336 else
337 {
338 mRedAttributeComboBox->setCurrentIndex( mRedAttributeComboBox->count() > 1 ? 1 : 0 );
339 mGreenAttributeComboBox->setCurrentIndex( mGreenAttributeComboBox->count() > 2 ? 2 : 0 );
340 mBlueAttributeComboBox->setCurrentIndex( mBlueAttributeComboBox->count() > 3 ? 3 : 0 );
341 }
342 }
343 mBlockChangedSignal = false;
344}
345
@ 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.
Class used to store statistics of a point cloud dataset.
double maximum(const QString &attribute) const
Returns the maximum value for the attribute attribute If no matching statistic is available then NaN ...