QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
20#include "qgspointcloudlayer.h"
22#include "qgsdoublevalidator.h"
23
25
26QgsPointCloudRgbRendererWidget::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 mBlockChangedSignal = true;
69 redAttributeChanged();
70 greenAttributeChanged();
71 blueAttributeChanged();
72 mBlockChangedSignal = false;
73 minMaxModified();
74 }
75}
76
77QgsPointCloudRendererWidget *QgsPointCloudRgbRendererWidget::create( QgsPointCloudLayer *layer, QgsStyle *style, QgsPointCloudRenderer * )
78{
79 return new QgsPointCloudRgbRendererWidget( layer, style );
80}
81
82QgsPointCloudRenderer *QgsPointCloudRgbRendererWidget::renderer()
83{
84 if ( !mLayer )
85 {
86 return nullptr;
87 }
88
89 std::unique_ptr< QgsPointCloudRgbRenderer > renderer = std::make_unique< QgsPointCloudRgbRenderer >();
90 renderer->setRedAttribute( mRedAttributeComboBox->currentAttribute() );
91 renderer->setGreenAttribute( mGreenAttributeComboBox->currentAttribute() );
92 renderer->setBlueAttribute( mBlueAttributeComboBox->currentAttribute() );
93
94 setCustomMinMaxValues( renderer.get() );
95 return renderer.release();
96}
97
98void QgsPointCloudRgbRendererWidget::createValidators()
99{
100 mRedMinLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
101 mRedMaxLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
102 mGreenMinLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
103 mGreenMaxLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
104 mBlueMinLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
105 mBlueMaxLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
106}
107
108void QgsPointCloudRgbRendererWidget::setCustomMinMaxValues( QgsPointCloudRgbRenderer *r )
109{
110 if ( !r )
111 {
112 return;
113 }
114
115 if ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ==
117 {
118 r->setRedContrastEnhancement( nullptr );
119 r->setGreenContrastEnhancement( nullptr );
120 r->setBlueContrastEnhancement( nullptr );
121 return;
122 }
123
124 QgsContrastEnhancement *redEnhancement = nullptr;
125 QgsContrastEnhancement *greenEnhancement = nullptr;
126 QgsContrastEnhancement *blueEnhancement = nullptr;
127
128 bool redMinOk, redMaxOk;
129 const double redMin = QgsDoubleValidator::toDouble( mRedMinLineEdit->text(), &redMinOk );
130 const double redMax = QgsDoubleValidator::toDouble( mRedMaxLineEdit->text(), &redMaxOk );
131 if ( redMinOk && redMaxOk && !mRedAttributeComboBox->currentAttribute().isEmpty() )
132 {
134 redEnhancement->setMinimumValue( redMin );
135 redEnhancement->setMaximumValue( redMax );
136 }
137
138 bool greenMinOk, greenMaxOk;
139 const double greenMin = QgsDoubleValidator::toDouble( mGreenMinLineEdit->text(), &greenMinOk );
140 const double greenMax = QgsDoubleValidator::toDouble( mGreenMaxLineEdit->text(), &greenMaxOk );
141 if ( greenMinOk && greenMaxOk && !mGreenAttributeComboBox->currentAttribute().isEmpty() )
142 {
144 greenEnhancement->setMinimumValue( greenMin );
145 greenEnhancement->setMaximumValue( greenMax );
146 }
147
148 bool blueMinOk, blueMaxOk;
149 const double blueMin = QgsDoubleValidator::toDouble( mBlueMinLineEdit->text(), &blueMinOk );
150 const double blueMax = QgsDoubleValidator::toDouble( mBlueMaxLineEdit->text(), &blueMaxOk );
151 if ( blueMinOk && blueMaxOk && !mBlueAttributeComboBox->currentAttribute().isEmpty() )
152 {
154 blueEnhancement->setMinimumValue( blueMin );
155 blueEnhancement->setMaximumValue( blueMax );
156 }
157
158 if ( redEnhancement )
159 {
161 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
162 }
163 if ( greenEnhancement )
164 {
166 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
167 }
168 if ( blueEnhancement )
169 {
171 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
172 }
173 r->setRedContrastEnhancement( redEnhancement );
174 r->setGreenContrastEnhancement( greenEnhancement );
175 r->setBlueContrastEnhancement( blueEnhancement );
176}
177
178void QgsPointCloudRgbRendererWidget::mRedMinLineEdit_textChanged( const QString & )
179{
180 minMaxModified();
181}
182
183void QgsPointCloudRgbRendererWidget::mRedMaxLineEdit_textChanged( const QString & )
184{
185 minMaxModified();
186}
187
188void QgsPointCloudRgbRendererWidget::mGreenMinLineEdit_textChanged( const QString & )
189{
190 minMaxModified();
191}
192
193void QgsPointCloudRgbRendererWidget::mGreenMaxLineEdit_textChanged( const QString & )
194{
195 minMaxModified();
196}
197
198void QgsPointCloudRgbRendererWidget::mBlueMinLineEdit_textChanged( const QString & )
199{
200 minMaxModified();
201}
202
203void QgsPointCloudRgbRendererWidget::mBlueMaxLineEdit_textChanged( const QString & )
204{
205 minMaxModified();
206}
207
208void QgsPointCloudRgbRendererWidget::emitWidgetChanged()
209{
210 if ( !mBlockChangedSignal )
211 emit widgetChanged();
212}
213
214void QgsPointCloudRgbRendererWidget::redAttributeChanged()
215{
216 if ( mLayer && mLayer->dataProvider() )
217 {
218 const QgsPointCloudStatistics stats = mLayer->statistics();
219 const double max = stats.maximum( mRedAttributeComboBox->currentAttribute() );
220 if ( !std::isnan( max ) )
221 {
222 mDisableMinMaxWidgetRefresh++;
223 mRedMinLineEdit->setText( QLocale().toString( 0 ) );
224
225 // 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
226 // likely to be 8 bit or 16 bit color values
227 mRedMaxLineEdit->setText( QLocale().toString( max > 255 ? 65535 : 255 ) );
228 mDisableMinMaxWidgetRefresh--;
229 emitWidgetChanged();
230 }
231 }
232}
233
234void QgsPointCloudRgbRendererWidget::greenAttributeChanged()
235{
236 if ( mLayer && mLayer->dataProvider() )
237 {
238 const QgsPointCloudStatistics stats = mLayer->statistics();
239 const double max = stats.maximum( mGreenAttributeComboBox->currentAttribute() );
240 if ( !std::isnan( max ) )
241 {
242 mDisableMinMaxWidgetRefresh++;
243 mGreenMinLineEdit->setText( QLocale().toString( 0 ) );
244
245 // 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
246 // likely to be 8 bit or 16 bit color values
247 mGreenMaxLineEdit->setText( QLocale().toString( max > 255 ? 65535 : 255 ) );
248 mDisableMinMaxWidgetRefresh--;
249 emitWidgetChanged();
250 }
251 }
252}
253
254void QgsPointCloudRgbRendererWidget::blueAttributeChanged()
255{
256 if ( mLayer && mLayer->dataProvider() )
257 {
258 const QgsPointCloudStatistics stats = mLayer->statistics();
259 const double max = stats.maximum( mBlueAttributeComboBox->currentAttribute() );
260 if ( !std::isnan( max ) )
261 {
262 mDisableMinMaxWidgetRefresh++;
263 mBlueMinLineEdit->setText( QLocale().toString( 0 ) );
264
265 // 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
266 // likely to be 8 bit or 16 bit color values
267 mBlueMaxLineEdit->setText( QLocale().toString( max > 255 ? 65535 : 255 ) );
268 mDisableMinMaxWidgetRefresh--;
269 emitWidgetChanged();
270 }
271 }
272}
273
274void QgsPointCloudRgbRendererWidget::minMaxModified()
275{
276 if ( !mDisableMinMaxWidgetRefresh )
277 {
278 if ( ( QgsContrastEnhancement::ContrastEnhancementAlgorithm )( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) == QgsContrastEnhancement::NoEnhancement )
279 {
280 mContrastEnhancementAlgorithmComboBox->setCurrentIndex(
281 mContrastEnhancementAlgorithmComboBox->findData( ( int ) QgsContrastEnhancement::StretchToMinimumMaximum ) );
282 }
283 emitWidgetChanged();
284 }
285}
286
287void QgsPointCloudRgbRendererWidget::setMinMaxValue( const QgsContrastEnhancement *ce, QLineEdit *minEdit, QLineEdit *maxEdit )
288{
289 if ( !minEdit || !maxEdit )
290 {
291 return;
292 }
293
294 if ( !ce )
295 {
296 minEdit->clear();
297 maxEdit->clear();
298 return;
299 }
300
301 minEdit->setText( QLocale().toString( ce->minimumValue() ) );
302 maxEdit->setText( QLocale().toString( ce->maximumValue() ) );
303
304 // QgsMultiBandColorRenderer is using individual contrast enhancements for each
305 // band, but this widget GUI has one for all
306 mContrastEnhancementAlgorithmComboBox->setCurrentIndex( mContrastEnhancementAlgorithmComboBox->findData(
307 static_cast< int >( ce->contrastEnhancementAlgorithm() ) ) );
308}
309
310void QgsPointCloudRgbRendererWidget::setFromRenderer( const QgsPointCloudRenderer *r )
311{
312 mBlockChangedSignal = true;
313 const QgsPointCloudRgbRenderer *mbcr = dynamic_cast<const QgsPointCloudRgbRenderer *>( r );
314 if ( mbcr )
315 {
316 mRedAttributeComboBox->setAttribute( mbcr->redAttribute() );
317 mGreenAttributeComboBox->setAttribute( mbcr->greenAttribute() );
318 mBlueAttributeComboBox->setAttribute( mbcr->blueAttribute() );
319
320 mDisableMinMaxWidgetRefresh++;
321 setMinMaxValue( mbcr->redContrastEnhancement(), mRedMinLineEdit, mRedMaxLineEdit );
322 setMinMaxValue( mbcr->greenContrastEnhancement(), mGreenMinLineEdit, mGreenMaxLineEdit );
323 setMinMaxValue( mbcr->blueContrastEnhancement(), mBlueMinLineEdit, mBlueMaxLineEdit );
324 mDisableMinMaxWidgetRefresh--;
325 }
326 else
327 {
328 if ( mRedAttributeComboBox->findText( QStringLiteral( "Red" ) ) > -1 && mRedAttributeComboBox->findText( QStringLiteral( "Green" ) ) > -1 &&
329 mRedAttributeComboBox->findText( QStringLiteral( "Blue" ) ) > -1 )
330 {
331 mRedAttributeComboBox->setAttribute( QStringLiteral( "Red" ) );
332 mGreenAttributeComboBox->setAttribute( QStringLiteral( "Green" ) );
333 mBlueAttributeComboBox->setAttribute( QStringLiteral( "Blue" ) );
334 }
335 else
336 {
337 mRedAttributeComboBox->setCurrentIndex( mRedAttributeComboBox->count() > 1 ? 1 : 0 );
338 mGreenAttributeComboBox->setCurrentIndex( mGreenAttributeComboBox->count() > 2 ? 2 : 0 );
339 mBlueAttributeComboBox->setCurrentIndex( mBlueAttributeComboBox->count() > 3 ? 3 : 0 );
340 }
341 }
342 mBlockChangedSignal = false;
343}
344
@ 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 ...