QGIS API Documentation 3.41.0-Master (af5edcb665c)
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, this, &QgsPointCloudRgbRendererWidget::redAttributeChanged );
59 connect( mGreenAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged, this, &QgsPointCloudRgbRendererWidget::greenAttributeChanged );
60 connect( mBlueAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged, this, &QgsPointCloudRgbRendererWidget::blueAttributeChanged );
61 connect( mContrastEnhancementAlgorithmComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRgbRendererWidget::emitWidgetChanged );
62
63 if ( layer )
64 {
65 // set nice initial values
66 mBlockChangedSignal = true;
67 redAttributeChanged();
68 greenAttributeChanged();
69 blueAttributeChanged();
70 mBlockChangedSignal = false;
71 minMaxModified();
72 }
73}
74
75QgsPointCloudRendererWidget *QgsPointCloudRgbRendererWidget::create( QgsPointCloudLayer *layer, QgsStyle *style, QgsPointCloudRenderer * )
76{
77 return new QgsPointCloudRgbRendererWidget( layer, style );
78}
79
80QgsPointCloudRenderer *QgsPointCloudRgbRendererWidget::renderer()
81{
82 if ( !mLayer )
83 {
84 return nullptr;
85 }
86
87 std::unique_ptr<QgsPointCloudRgbRenderer> renderer = std::make_unique<QgsPointCloudRgbRenderer>();
88 renderer->setRedAttribute( mRedAttributeComboBox->currentAttribute() );
89 renderer->setGreenAttribute( mGreenAttributeComboBox->currentAttribute() );
90 renderer->setBlueAttribute( mBlueAttributeComboBox->currentAttribute() );
91
92 setCustomMinMaxValues( renderer.get() );
93 return renderer.release();
94}
95
96void QgsPointCloudRgbRendererWidget::createValidators()
97{
98 mRedMinLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
99 mRedMaxLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
100 mGreenMinLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
101 mGreenMaxLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
102 mBlueMinLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
103 mBlueMaxLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
104}
105
106void QgsPointCloudRgbRendererWidget::setCustomMinMaxValues( QgsPointCloudRgbRenderer *r )
107{
108 if ( !r )
109 {
110 return;
111 }
112
113 if ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() == QgsContrastEnhancement::NoEnhancement )
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 const double redMin = QgsDoubleValidator::toDouble( mRedMinLineEdit->text(), &redMinOk );
127 const 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 const double greenMin = QgsDoubleValidator::toDouble( mGreenMinLineEdit->text(), &greenMinOk );
137 const 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 const double blueMin = QgsDoubleValidator::toDouble( mBlueMinLineEdit->text(), &blueMinOk );
147 const 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 }
161 if ( greenEnhancement )
162 {
164 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() )
165 ) );
166 }
167 if ( blueEnhancement )
168 {
170 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() )
171 ) );
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 }
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}
311
312void QgsPointCloudRgbRendererWidget::setFromRenderer( const QgsPointCloudRenderer *r )
313{
314 mBlockChangedSignal = true;
315 const QgsPointCloudRgbRenderer *mbcr = dynamic_cast<const QgsPointCloudRgbRenderer *>( r );
316 if ( mbcr )
317 {
318 mRedAttributeComboBox->setAttribute( mbcr->redAttribute() );
319 mGreenAttributeComboBox->setAttribute( mbcr->greenAttribute() );
320 mBlueAttributeComboBox->setAttribute( mbcr->blueAttribute() );
321
322 mDisableMinMaxWidgetRefresh++;
323 setMinMaxValue( mbcr->redContrastEnhancement(), mRedMinLineEdit, mRedMaxLineEdit );
324 setMinMaxValue( mbcr->greenContrastEnhancement(), mGreenMinLineEdit, mGreenMaxLineEdit );
325 setMinMaxValue( mbcr->blueContrastEnhancement(), mBlueMinLineEdit, mBlueMaxLineEdit );
326 mDisableMinMaxWidgetRefresh--;
327 }
328 else
329 {
330 if ( mRedAttributeComboBox->findText( QStringLiteral( "Red" ) ) > -1 && mRedAttributeComboBox->findText( QStringLiteral( "Green" ) ) > -1 && 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 ...