QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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 {
163 redEnhancement->setContrastEnhancementAlgorithm( static_cast<QgsContrastEnhancement::ContrastEnhancementAlgorithm>( ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
164 }
165 if ( greenEnhancement )
166 {
167 greenEnhancement->setContrastEnhancementAlgorithm( static_cast<QgsContrastEnhancement::ContrastEnhancementAlgorithm>( ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
168 }
169 if ( blueEnhancement )
170 {
171 blueEnhancement->setContrastEnhancementAlgorithm( static_cast<QgsContrastEnhancement::ContrastEnhancementAlgorithm>( ( 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( mContrastEnhancementAlgorithmComboBox->findData( ( int ) QgsContrastEnhancement::StretchToMinimumMaximum ) );
281 }
282 emitWidgetChanged();
283 }
284}
285
286void QgsPointCloudRgbRendererWidget::setMinMaxValue( const QgsContrastEnhancement *ce, QLineEdit *minEdit, QLineEdit *maxEdit )
287{
288 if ( !minEdit || !maxEdit )
289 {
290 return;
291 }
292
293 if ( !ce )
294 {
295 minEdit->clear();
296 maxEdit->clear();
297 return;
298 }
299
300 minEdit->setText( QLocale().toString( ce->minimumValue() ) );
301 maxEdit->setText( QLocale().toString( ce->maximumValue() ) );
302
303 // QgsMultiBandColorRenderer is using individual contrast enhancements for each
304 // band, but this widget GUI has one for all
305 mContrastEnhancementAlgorithmComboBox->setCurrentIndex( mContrastEnhancementAlgorithmComboBox->findData( static_cast<int>( ce->contrastEnhancementAlgorithm() ) ) );
306}
307
308void QgsPointCloudRgbRendererWidget::setFromRenderer( const QgsPointCloudRenderer *r )
309{
310 mBlockChangedSignal = true;
311 const QgsPointCloudRgbRenderer *mbcr = dynamic_cast<const QgsPointCloudRgbRenderer *>( r );
312 if ( mbcr )
313 {
314 mRedAttributeComboBox->setAttribute( mbcr->redAttribute() );
315 mGreenAttributeComboBox->setAttribute( mbcr->greenAttribute() );
316 mBlueAttributeComboBox->setAttribute( mbcr->blueAttribute() );
317
318 mDisableMinMaxWidgetRefresh++;
319 setMinMaxValue( mbcr->redContrastEnhancement(), mRedMinLineEdit, mRedMaxLineEdit );
320 setMinMaxValue( mbcr->greenContrastEnhancement(), mGreenMinLineEdit, mGreenMaxLineEdit );
321 setMinMaxValue( mbcr->blueContrastEnhancement(), mBlueMinLineEdit, mBlueMaxLineEdit );
322 mDisableMinMaxWidgetRefresh--;
323 }
324 else
325 {
326 if ( mRedAttributeComboBox->findText( u"Red"_s ) > -1 && mRedAttributeComboBox->findText( u"Green"_s ) > -1 && mRedAttributeComboBox->findText( u"Blue"_s ) > -1 )
327 {
328 mRedAttributeComboBox->setAttribute( u"Red"_s );
329 mGreenAttributeComboBox->setAttribute( u"Green"_s );
330 mBlueAttributeComboBox->setAttribute( u"Blue"_s );
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.
Definition qgis.h:394
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