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