1 /***************************************************************************
2 qgspointcloud3dsymbolwidget.cpp
3 ------------------------------
4 Date : November 2020
5 Copyright : (C) 2020 by Nedjima Belgacem
6 Email : belgacem dot nedjima at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16 #include "qgspointcloud3dsymbolwidget.h"
17
18 #include "qgspointcloudlayer.h"
19 #include "qgspointcloud3dsymbol.h"
20 #include "qgspointcloudlayer3drenderer.h"
21 #include "qgsapplication.h"
22 #include "qgspointcloudrenderer.h"
23 #include "qgspointcloudattributebyramprenderer.h"
24 #include "qgspointcloudrgbrenderer.h"
25 #include "qgspointcloudclassifiedrenderer.h"
26 #include "qgsdoublevalidator.h"
27 #include "qgspointcloudclassifiedrendererwidget.h"
28 #include "qgspointcloudlayerelevationproperties.h"
29
QgsPointCloud3DSymbolWidget(QgsPointCloudLayer * layer,QgsPointCloud3DSymbol * symbol,QWidget * parent)30 QgsPointCloud3DSymbolWidget::QgsPointCloud3DSymbolWidget( QgsPointCloudLayer *layer, QgsPointCloud3DSymbol *symbol, QWidget *parent )
31 : QWidget( parent )
32 , mLayer( layer )
33 {
34 setupUi( this );
35
36 mPointSizeSpinBox->setClearValue( 2.0 );
37 mMaxScreenErrorSpinBox->setClearValue( 1.0 );
38
39 mColorRampShaderMinEdit->setShowClearButton( false );
40 mColorRampShaderMaxEdit->setShowClearButton( false );
41
42 mRenderingParameterComboBox->setLayer( layer );
43 mRenderingParameterComboBox->setFilters( QgsPointCloudAttributeProxyModel::AllTypes );
44 mRenderingParameterComboBox->setAllowEmptyAttributeName( false );
45
46 mSingleColorBtn->setAllowOpacity( false );
47 mSingleColorBtn->setColorDialogTitle( tr( "Select Point Color" ) );
48 mSingleColorBtn->setColor( QColor( 0, 0, 255 ) ); // default color
49
50 mRenderingStyleComboBox->addItem( tr( "No Rendering" ), QString() );
51 mRenderingStyleComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "styleicons/singlecolor.svg" ) ), tr( "Single Color" ), QStringLiteral( "single-color" ) );
52 mRenderingStyleComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "styleicons/singlebandpseudocolor.svg" ) ), tr( "Attribute by Ramp" ), QStringLiteral( "color-ramp" ) );
53 mRenderingStyleComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "styleicons/multibandcolor.svg" ) ), tr( "RGB" ), QStringLiteral( "rgb" ) );
54 mRenderingStyleComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "styleicons/paletted.svg" ) ), tr( "Classification" ), QStringLiteral( "classification" ) );
55
56 connect( mRedMinLineEdit, &QLineEdit::textChanged, this, &QgsPointCloud3DSymbolWidget::mRedMinLineEdit_textChanged );
57 connect( mRedMaxLineEdit, &QLineEdit::textChanged, this, &QgsPointCloud3DSymbolWidget::mRedMaxLineEdit_textChanged );
58 connect( mGreenMinLineEdit, &QLineEdit::textChanged, this, &QgsPointCloud3DSymbolWidget::mGreenMinLineEdit_textChanged );
59 connect( mGreenMaxLineEdit, &QLineEdit::textChanged, this, &QgsPointCloud3DSymbolWidget::mGreenMaxLineEdit_textChanged );
60 connect( mBlueMinLineEdit, &QLineEdit::textChanged, this, &QgsPointCloud3DSymbolWidget::mBlueMinLineEdit_textChanged );
61 connect( mBlueMaxLineEdit, &QLineEdit::textChanged, this, &QgsPointCloud3DSymbolWidget::mBlueMaxLineEdit_textChanged );
62 createValidators();
63
64 mRedAttributeComboBox->setAllowEmptyAttributeName( true );
65 mGreenAttributeComboBox->setAllowEmptyAttributeName( true );
66 mBlueAttributeComboBox->setAllowEmptyAttributeName( true );
67
68 //contrast enhancement algorithms
69 mContrastEnhancementAlgorithmComboBox->addItem( tr( "No Enhancement" ), QgsContrastEnhancement::NoEnhancement );
70 mContrastEnhancementAlgorithmComboBox->addItem( tr( "Stretch to MinMax" ), QgsContrastEnhancement::StretchToMinimumMaximum );
71 mContrastEnhancementAlgorithmComboBox->addItem( tr( "Stretch and Clip to MinMax" ), QgsContrastEnhancement::StretchAndClipToMinimumMaximum );
72 mContrastEnhancementAlgorithmComboBox->addItem( tr( "Clip to MinMax" ), QgsContrastEnhancement::ClipToMinimumMaximum );
73
74 mRedAttributeComboBox->setLayer( layer );
75 mGreenAttributeComboBox->setLayer( layer );
76 mBlueAttributeComboBox->setLayer( layer );
77
78 connect( mRedAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged, this, &QgsPointCloud3DSymbolWidget::redAttributeChanged );
79 connect( mGreenAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged, this, &QgsPointCloud3DSymbolWidget::greenAttributeChanged );
80 connect( mBlueAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged, this, &QgsPointCloud3DSymbolWidget::blueAttributeChanged );
81 connect( mContrastEnhancementAlgorithmComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloud3DSymbolWidget::emitChangedSignal );
82
83 // set nice initial values
84 redAttributeChanged();
85 greenAttributeChanged();
86 blueAttributeChanged();
87
88 mRenderingStyleComboBox->setCurrentIndex( 0 );
89 mStackedWidget->setCurrentIndex( 0 );
90
91 whileBlocking( mPointBudgetSpinBox )->setMinimum( std::min( mLayer->pointCount() / 2, ( qint64 )100000 ) );
92 whileBlocking( mPointBudgetSpinBox )->setMaximum( mLayer->pointCount() + 1 );
93 whileBlocking( mPointBudgetSpinBox )->setValue( 1000000 );
94
95 if ( symbol )
96 setSymbol( symbol );
97
98 connect( mPointSizeSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsPointCloud3DSymbolWidget::emitChangedSignal );
99 connect( mRenderingStyleComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsPointCloud3DSymbolWidget::onRenderingStyleChanged );
100 connect( mScalarRecalculateMinMaxButton, &QPushButton::clicked, this, &QgsPointCloud3DSymbolWidget::setMinMaxFromLayer );
101 connect( mColorRampShaderWidget, &QgsColorRampShaderWidget::widgetChanged, this, &QgsPointCloud3DSymbolWidget::emitChangedSignal );
102 connect( mSingleColorBtn, &QgsColorButton::colorChanged, this, &QgsPointCloud3DSymbolWidget::emitChangedSignal );
103 connect( mRenderingParameterComboBox, &QgsPointCloudAttributeComboBox::attributeChanged, this, &QgsPointCloud3DSymbolWidget::rampAttributeChanged );
104 connect( mColorRampShaderMinEdit, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsPointCloud3DSymbolWidget::minMaxChanged );
105 connect( mColorRampShaderMaxEdit, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsPointCloud3DSymbolWidget::minMaxChanged );
106
107 connect( mMaxScreenErrorSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [&]() { emitChangedSignal(); } );
108 connect( mShowBoundingBoxesCheckBox, &QCheckBox::stateChanged, this, [&]() { emitChangedSignal(); } );
109 connect( mPointBudgetSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [&]() { emitChangedSignal(); } );
110
111 if ( !symbol ) // if we have a symbol, this was already handled in setSymbol above
112 rampAttributeChanged();
113
114 mClassifiedRendererWidget = new QgsPointCloudClassifiedRendererWidget( layer, nullptr );
115 mClassifiedRendererWidget->setParent( this );
116 mClassifiedRenderingLayout->addWidget( mClassifiedRendererWidget );
117
118 connect( mClassifiedRendererWidget, &QgsPointCloudClassifiedRendererWidget::widgetChanged, this, &QgsPointCloud3DSymbolWidget::emitChangedSignal );
119 }
120
setSymbol(QgsPointCloud3DSymbol * symbol)121 void QgsPointCloud3DSymbolWidget::setSymbol( QgsPointCloud3DSymbol *symbol )
122 {
123 mBlockChangedSignals++;
124 if ( !symbol )
125 {
126 mRenderingStyleComboBox->setCurrentIndex( 0 );
127 mStackedWidget->setCurrentIndex( 0 );
128 mBlockChangedSignals--;
129 return;
130 }
131
132 mRenderingStyleComboBox->setCurrentIndex( mRenderingStyleComboBox->findData( symbol->symbolType() ) );
133 mPointSizeSpinBox->setValue( symbol->pointSize() );
134
135 if ( symbol->symbolType() == QLatin1String( "single-color" ) )
136 {
137 mStackedWidget->setCurrentIndex( 1 );
138 QgsSingleColorPointCloud3DSymbol *symb = dynamic_cast<QgsSingleColorPointCloud3DSymbol *>( symbol );
139 mSingleColorBtn->setColor( symb->singleColor() );
140 }
141 else if ( symbol->symbolType() == QLatin1String( "color-ramp" ) )
142 {
143 mStackedWidget->setCurrentIndex( 2 );
144 QgsColorRampPointCloud3DSymbol *symb = dynamic_cast<QgsColorRampPointCloud3DSymbol *>( symbol );
145
146 // we will be restoring the existing ramp classes -- we don't want to regenerate any automatically!
147 mBlockSetMinMaxFromLayer = true;
148 mRenderingParameterComboBox->setAttribute( symb->attribute() );
149
150 mColorRampShaderMinEdit->setValue( symb->colorRampShaderMin() );
151 mColorRampShaderMaxEdit->setValue( symb->colorRampShaderMax() );
152
153 whileBlocking( mColorRampShaderWidget )->setFromShader( symb->colorRampShader() );
154 whileBlocking( mColorRampShaderWidget )->setMinimumMaximum( symb->colorRampShaderMin(), symb->colorRampShaderMax() );
155 mBlockSetMinMaxFromLayer = false;
156 }
157 else if ( symbol->symbolType() == QLatin1String( "rgb" ) )
158 {
159 mStackedWidget->setCurrentIndex( 3 );
160
161 QgsRgbPointCloud3DSymbol *symb = dynamic_cast<QgsRgbPointCloud3DSymbol *>( symbol );
162 mRedAttributeComboBox->setAttribute( symb->redAttribute() );
163 mGreenAttributeComboBox->setAttribute( symb->greenAttribute() );
164 mBlueAttributeComboBox->setAttribute( symb->blueAttribute() );
165
166 mDisableMinMaxWidgetRefresh++;
167 setMinMaxValue( symb->redContrastEnhancement(), mRedMinLineEdit, mRedMaxLineEdit );
168 setMinMaxValue( symb->greenContrastEnhancement(), mGreenMinLineEdit, mGreenMaxLineEdit );
169 setMinMaxValue( symb->blueContrastEnhancement(), mBlueMinLineEdit, mBlueMaxLineEdit );
170 mDisableMinMaxWidgetRefresh--;
171 }
172 else if ( symbol->symbolType() == QLatin1String( "classification" ) )
173 {
174 mStackedWidget->setCurrentIndex( 4 );
175 QgsClassificationPointCloud3DSymbol *symb = dynamic_cast<QgsClassificationPointCloud3DSymbol *>( symbol );
176 mClassifiedRendererWidget->setFromCategories( symb->categoriesList(), symb->attribute() );
177 }
178 else
179 {
180 mStackedWidget->setCurrentIndex( 0 );
181 }
182
183 mBlockChangedSignals--;
184 }
185
setDockMode(bool dockMode)186 void QgsPointCloud3DSymbolWidget::setDockMode( bool dockMode )
187 {
188 if ( mClassifiedRendererWidget )
189 mClassifiedRendererWidget->setDockMode( dockMode );
190 }
191
symbol() const192 QgsPointCloud3DSymbol *QgsPointCloud3DSymbolWidget::symbol() const
193 {
194 QgsPointCloud3DSymbol *retSymb = nullptr;
195 const QString symbolType = mRenderingStyleComboBox->currentData().toString();
196
197 if ( symbolType == QLatin1String( "single-color" ) )
198 {
199 QgsSingleColorPointCloud3DSymbol *symb = new QgsSingleColorPointCloud3DSymbol;
200 symb->setPointSize( mPointSizeSpinBox->value() );
201 symb->setSingleColor( mSingleColorBtn->color() );
202 retSymb = symb;
203 }
204 else if ( symbolType == QLatin1String( "color-ramp" ) )
205 {
206 QgsColorRampPointCloud3DSymbol *symb = new QgsColorRampPointCloud3DSymbol;
207 symb->setAttribute( mRenderingParameterComboBox->currentText() );
208 symb->setPointSize( mPointSizeSpinBox->value() );
209 symb->setColorRampShader( mColorRampShaderWidget->shader() );
210 symb->setColorRampShaderMinMax( mColorRampShaderMinEdit->value(), mColorRampShaderMaxEdit->value() );
211 retSymb = symb;
212 }
213 else if ( symbolType == QLatin1String( "rgb" ) )
214 {
215 QgsRgbPointCloud3DSymbol *symb = new QgsRgbPointCloud3DSymbol;
216 symb->setPointSize( mPointSizeSpinBox->value() );
217
218 symb->setRedAttribute( mRedAttributeComboBox->currentAttribute() );
219 symb->setGreenAttribute( mGreenAttributeComboBox->currentAttribute() );
220 symb->setBlueAttribute( mBlueAttributeComboBox->currentAttribute() );
221
222 setCustomMinMaxValues( symb );
223 retSymb = symb;
224 }
225 else if ( symbolType == QLatin1String( "classification" ) )
226 {
227 QgsClassificationPointCloud3DSymbol *symb = new QgsClassificationPointCloud3DSymbol;
228 symb->setPointSize( mPointSizeSpinBox->value() );
229
230 symb->setAttribute( mClassifiedRendererWidget->attribute() );
231 symb->setCategoriesList( mClassifiedRendererWidget->categoriesList() );
232 retSymb = symb;
233 }
234
235 return retSymb;
236 }
237
setColorRampMinMax(double min,double max)238 void QgsPointCloud3DSymbolWidget::setColorRampMinMax( double min, double max )
239 {
240 whileBlocking( mColorRampShaderMinEdit )->setValue( min );
241 whileBlocking( mColorRampShaderMaxEdit )->setValue( max );
242 }
243
createValidators()244 void QgsPointCloud3DSymbolWidget::createValidators()
245 {
246 mRedMinLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
247 mRedMaxLineEdit->setValidator( new QgsDoubleValidator( mRedMinLineEdit ) );
248 mGreenMinLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
249 mGreenMaxLineEdit->setValidator( new QgsDoubleValidator( mGreenMinLineEdit ) );
250 mBlueMinLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
251 mBlueMaxLineEdit->setValidator( new QgsDoubleValidator( mBlueMinLineEdit ) );
252 }
253
setCustomMinMaxValues(QgsRgbPointCloud3DSymbol * symbol) const254 void QgsPointCloud3DSymbolWidget::setCustomMinMaxValues( QgsRgbPointCloud3DSymbol *symbol ) const
255 {
256 if ( !symbol )
257 {
258 return;
259 }
260
261 if ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ==
262 QgsContrastEnhancement::NoEnhancement )
263 {
264 symbol->setRedContrastEnhancement( nullptr );
265 symbol->setGreenContrastEnhancement( nullptr );
266 symbol->setBlueContrastEnhancement( nullptr );
267 return;
268 }
269
270 QgsContrastEnhancement *redEnhancement = nullptr;
271 QgsContrastEnhancement *greenEnhancement = nullptr;
272 QgsContrastEnhancement *blueEnhancement = nullptr;
273
274 bool redMinOk, redMaxOk;
275 const double redMin = QgsDoubleValidator::toDouble( mRedMinLineEdit->text(), &redMinOk );
276 const double redMax = QgsDoubleValidator::toDouble( mRedMaxLineEdit->text(), &redMaxOk );
277 if ( redMinOk && redMaxOk && !mRedAttributeComboBox->currentAttribute().isEmpty() )
278 {
279 redEnhancement = new QgsContrastEnhancement( Qgis::DataType::UnknownDataType );
280 redEnhancement->setMinimumValue( redMin );
281 redEnhancement->setMaximumValue( redMax );
282 }
283
284 bool greenMinOk, greenMaxOk;
285 const double greenMin = QgsDoubleValidator::toDouble( mGreenMinLineEdit->text(), &greenMinOk );
286 const double greenMax = QgsDoubleValidator::toDouble( mGreenMaxLineEdit->text(), &greenMaxOk );
287 if ( greenMinOk && greenMaxOk && !mGreenAttributeComboBox->currentAttribute().isEmpty() )
288 {
289 greenEnhancement = new QgsContrastEnhancement( Qgis::DataType::UnknownDataType );
290 greenEnhancement->setMinimumValue( greenMin );
291 greenEnhancement->setMaximumValue( greenMax );
292 }
293
294 bool blueMinOk, blueMaxOk;
295 const double blueMin = QgsDoubleValidator::toDouble( mBlueMinLineEdit->text(), &blueMinOk );
296 const double blueMax = QgsDoubleValidator::toDouble( mBlueMaxLineEdit->text(), &blueMaxOk );
297 if ( blueMinOk && blueMaxOk && !mBlueAttributeComboBox->currentAttribute().isEmpty() )
298 {
299 blueEnhancement = new QgsContrastEnhancement( Qgis::DataType::UnknownDataType );
300 blueEnhancement->setMinimumValue( blueMin );
301 blueEnhancement->setMaximumValue( blueMax );
302 }
303
304 if ( redEnhancement )
305 {
306 redEnhancement->setContrastEnhancementAlgorithm( static_cast< QgsContrastEnhancement::ContrastEnhancementAlgorithm >(
307 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
308 }
309 if ( greenEnhancement )
310 {
311 greenEnhancement->setContrastEnhancementAlgorithm( static_cast< QgsContrastEnhancement::ContrastEnhancementAlgorithm >(
312 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
313 }
314 if ( blueEnhancement )
315 {
316 blueEnhancement->setContrastEnhancementAlgorithm( static_cast< QgsContrastEnhancement::ContrastEnhancementAlgorithm >(
317 ( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) ) );
318 }
319 symbol->setRedContrastEnhancement( redEnhancement );
320 symbol->setGreenContrastEnhancement( greenEnhancement );
321 symbol->setBlueContrastEnhancement( blueEnhancement );
322 }
323
minMaxModified()324 void QgsPointCloud3DSymbolWidget::minMaxModified()
325 {
326 if ( !mDisableMinMaxWidgetRefresh )
327 {
328 if ( ( QgsContrastEnhancement::ContrastEnhancementAlgorithm )( mContrastEnhancementAlgorithmComboBox->currentData().toInt() ) == QgsContrastEnhancement::NoEnhancement )
329 {
330 mContrastEnhancementAlgorithmComboBox->setCurrentIndex(
331 mContrastEnhancementAlgorithmComboBox->findData( ( int ) QgsContrastEnhancement::StretchToMinimumMaximum ) );
332 }
333 emitChangedSignal();
334 }
335 }
336
setMinMaxValue(const QgsContrastEnhancement * ce,QLineEdit * minEdit,QLineEdit * maxEdit)337 void QgsPointCloud3DSymbolWidget::setMinMaxValue( const QgsContrastEnhancement *ce, QLineEdit *minEdit, QLineEdit *maxEdit )
338 {
339 if ( !minEdit || !maxEdit )
340 {
341 return;
342 }
343
344 if ( !ce )
345 {
346 minEdit->clear();
347 maxEdit->clear();
348 return;
349 }
350
351 minEdit->setText( QLocale().toString( ce->minimumValue() ) );
352 maxEdit->setText( QLocale().toString( ce->maximumValue() ) );
353
354 // QgsMultiBandColorRenderer is using individual contrast enhancements for each
355 // band, but this widget GUI has one for all
356 mContrastEnhancementAlgorithmComboBox->setCurrentIndex( mContrastEnhancementAlgorithmComboBox->findData(
357 static_cast< int >( ce->contrastEnhancementAlgorithm() ) ) );
358 }
359
reloadColorRampShaderMinMax()360 void QgsPointCloud3DSymbolWidget::reloadColorRampShaderMinMax()
361 {
362 const double min = mColorRampShaderMinEdit->value();
363 const double max = mColorRampShaderMaxEdit->value();
364 mColorRampShaderWidget->setMinimumMaximum( min, max );
365 mColorRampShaderWidget->classify();
366 }
367
onRenderingStyleChanged()368 void QgsPointCloud3DSymbolWidget::onRenderingStyleChanged()
369 {
370 if ( mBlockChangedSignals )
371 return;
372
373 mStackedWidget->setCurrentIndex( mRenderingStyleComboBox->currentIndex() );
374
375 // copy settings from 2d renderer, if possible!
376 if ( mLayer )
377 {
378 const QString newSymbolType = mRenderingStyleComboBox->currentData().toString();
379 if ( newSymbolType == QLatin1String( "color-ramp" ) && mLayer->renderer()->type() == QLatin1String( "ramp" ) )
380 {
381 const QgsPointCloudAttributeByRampRenderer *renderer2d = dynamic_cast< const QgsPointCloudAttributeByRampRenderer * >( mLayer->renderer() );
382 mBlockChangedSignals++;
383 mRenderingParameterComboBox->setAttribute( renderer2d->attribute() );
384 mColorRampShaderMinEdit->setValue( renderer2d->minimum() );
385 mColorRampShaderMaxEdit->setValue( renderer2d->maximum() );
386 whileBlocking( mColorRampShaderWidget )->setFromShader( renderer2d->colorRampShader() );
387 whileBlocking( mColorRampShaderWidget )->setMinimumMaximum( renderer2d->minimum(), renderer2d->maximum() );
388 mBlockChangedSignals--;
389 }
390 else if ( newSymbolType == QLatin1String( "rgb" ) )
391 {
392 const QgsPointCloudRgbRenderer *renderer2d = dynamic_cast< const QgsPointCloudRgbRenderer * >( mLayer->renderer() );
393 mBlockChangedSignals++;
394 if ( renderer2d )
395 {
396 mRedAttributeComboBox->setAttribute( renderer2d->redAttribute() );
397 mGreenAttributeComboBox->setAttribute( renderer2d->greenAttribute() );
398 mBlueAttributeComboBox->setAttribute( renderer2d->blueAttribute() );
399
400 mDisableMinMaxWidgetRefresh++;
401 setMinMaxValue( renderer2d->redContrastEnhancement(), mRedMinLineEdit, mRedMaxLineEdit );
402 setMinMaxValue( renderer2d->greenContrastEnhancement(), mGreenMinLineEdit, mGreenMaxLineEdit );
403 setMinMaxValue( renderer2d->blueContrastEnhancement(), mBlueMinLineEdit, mBlueMaxLineEdit );
404 mDisableMinMaxWidgetRefresh--;
405 }
406 else
407 {
408 if ( mRedAttributeComboBox->findText( QStringLiteral( "Red" ) ) > -1 && mRedAttributeComboBox->findText( QStringLiteral( "Green" ) ) > -1 &&
409 mRedAttributeComboBox->findText( QStringLiteral( "Blue" ) ) > -1 )
410 {
411 mRedAttributeComboBox->setAttribute( QStringLiteral( "Red" ) );
412 mGreenAttributeComboBox->setAttribute( QStringLiteral( "Green" ) );
413 mBlueAttributeComboBox->setAttribute( QStringLiteral( "Blue" ) );
414 }
415 else
416 {
417 mRedAttributeComboBox->setCurrentIndex( mRedAttributeComboBox->count() > 1 ? 1 : 0 );
418 mGreenAttributeComboBox->setCurrentIndex( mGreenAttributeComboBox->count() > 2 ? 2 : 0 );
419 mBlueAttributeComboBox->setCurrentIndex( mBlueAttributeComboBox->count() > 3 ? 3 : 0 );
420 }
421 redAttributeChanged();
422 greenAttributeChanged();
423 blueAttributeChanged();
424 }
425
426 ( void )( renderer2d );
427 mBlockChangedSignals--;
428 }
429 else if ( newSymbolType == QLatin1String( "classification" ) )
430 {
431 const QgsPointCloudClassifiedRenderer *renderer2d = dynamic_cast< const QgsPointCloudClassifiedRenderer * >( mLayer->renderer() );
432 mBlockChangedSignals++;
433 if ( renderer2d )
434 {
435 mClassifiedRendererWidget->setFromCategories( renderer2d->categories(), renderer2d->attribute() );
436 }
437 else
438 {
439 mClassifiedRendererWidget->setFromCategories( QgsPointCloudClassifiedRenderer::defaultCategories(), QString() );
440 }
441
442 ( void )( renderer2d );
443 mBlockChangedSignals--;
444 }
445 }
446
447 emitChangedSignal();
448 }
449
emitChangedSignal()450 void QgsPointCloud3DSymbolWidget::emitChangedSignal()
451 {
452 if ( mBlockChangedSignals )
453 return;
454
455 emit changed();
456 }
457
rampAttributeChanged()458 void QgsPointCloud3DSymbolWidget::rampAttributeChanged()
459 {
460 if ( mLayer && mLayer->dataProvider() )
461 {
462 const QVariant min = mLayer->dataProvider()->metadataStatistic( mRenderingParameterComboBox->currentAttribute(), QgsStatisticalSummary::Min );
463 const QVariant max = mLayer->dataProvider()->metadataStatistic( mRenderingParameterComboBox->currentAttribute(), QgsStatisticalSummary::Max );
464 if ( min.isValid() && max.isValid() )
465 {
466 mProviderMin = min.toDouble();
467 mProviderMax = max.toDouble();
468 }
469 else
470 {
471 mProviderMin = std::numeric_limits< double >::quiet_NaN();
472 mProviderMax = std::numeric_limits< double >::quiet_NaN();
473 }
474
475 if ( mRenderingParameterComboBox->currentAttribute() == QLatin1String( "Z" ) )
476 {
477 const double zScale = static_cast< const QgsPointCloudLayerElevationProperties * >( mLayer->elevationProperties() )->zScale();
478 const double zOffset = static_cast< const QgsPointCloudLayerElevationProperties * >( mLayer->elevationProperties() )->zOffset();
479 mProviderMin = mProviderMin * zScale + zOffset;
480 mProviderMax = mProviderMax * zScale + zOffset;
481 }
482 }
483 if ( !mBlockSetMinMaxFromLayer )
484 setMinMaxFromLayer();
485 mScalarRecalculateMinMaxButton->setEnabled( !std::isnan( mProviderMin ) && !std::isnan( mProviderMax ) );
486 emitChangedSignal();
487 }
488
setMinMaxFromLayer()489 void QgsPointCloud3DSymbolWidget::setMinMaxFromLayer()
490 {
491 if ( std::isnan( mProviderMin ) || std::isnan( mProviderMax ) )
492 return;
493
494 mBlockMinMaxChanged = true;
495 mColorRampShaderMinEdit->setValue( mProviderMin );
496 mColorRampShaderMaxEdit->setValue( mProviderMax );
497 mBlockMinMaxChanged = false;
498
499 minMaxChanged();
500 }
501
minMaxChanged()502 void QgsPointCloud3DSymbolWidget::minMaxChanged()
503 {
504 if ( mBlockMinMaxChanged )
505 return;
506
507 mColorRampShaderWidget->setMinimumMaximumAndClassify( mColorRampShaderMinEdit->value(), mColorRampShaderMaxEdit->value() );
508 }
509
mRedMinLineEdit_textChanged(const QString &)510 void QgsPointCloud3DSymbolWidget::mRedMinLineEdit_textChanged( const QString & )
511 {
512 minMaxModified();
513 }
514
mRedMaxLineEdit_textChanged(const QString &)515 void QgsPointCloud3DSymbolWidget::mRedMaxLineEdit_textChanged( const QString & )
516 {
517 minMaxModified();
518 }
519
mGreenMinLineEdit_textChanged(const QString &)520 void QgsPointCloud3DSymbolWidget::mGreenMinLineEdit_textChanged( const QString & )
521 {
522 minMaxModified();
523 }
524
mGreenMaxLineEdit_textChanged(const QString &)525 void QgsPointCloud3DSymbolWidget::mGreenMaxLineEdit_textChanged( const QString & )
526 {
527 minMaxModified();
528 }
529
mBlueMinLineEdit_textChanged(const QString &)530 void QgsPointCloud3DSymbolWidget::mBlueMinLineEdit_textChanged( const QString & )
531 {
532 minMaxModified();
533 }
534
mBlueMaxLineEdit_textChanged(const QString &)535 void QgsPointCloud3DSymbolWidget::mBlueMaxLineEdit_textChanged( const QString & )
536 {
537 minMaxModified();
538 }
539
redAttributeChanged()540 void QgsPointCloud3DSymbolWidget::redAttributeChanged()
541 {
542 if ( mLayer && mLayer->dataProvider() )
543 {
544 const QVariant max = mLayer->dataProvider()->metadataStatistic( mRedAttributeComboBox->currentAttribute(), QgsStatisticalSummary::Max );
545 if ( max.isValid() )
546 {
547 const int maxValue = max.toInt();
548 mDisableMinMaxWidgetRefresh++;
549 mRedMinLineEdit->setText( QLocale().toString( 0 ) );
550
551 // 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
552 // likely to be 8 bit or 16 bit color values
553 mRedMaxLineEdit->setText( QLocale().toString( maxValue > 255 ? 65535 : 255 ) );
554 mDisableMinMaxWidgetRefresh--;
555 emitChangedSignal();
556 }
557 }
558 }
559
greenAttributeChanged()560 void QgsPointCloud3DSymbolWidget::greenAttributeChanged()
561 {
562 if ( mLayer && mLayer->dataProvider() )
563 {
564 const QVariant max = mLayer->dataProvider()->metadataStatistic( mGreenAttributeComboBox->currentAttribute(), QgsStatisticalSummary::Max );
565 if ( max.isValid() )
566 {
567 const int maxValue = max.toInt();
568 mDisableMinMaxWidgetRefresh++;
569 mGreenMinLineEdit->setText( QLocale().toString( 0 ) );
570
571 // 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
572 // likely to be 8 bit or 16 bit color values
573 mGreenMaxLineEdit->setText( QLocale().toString( maxValue > 255 ? 65535 : 255 ) );
574 mDisableMinMaxWidgetRefresh--;
575 emitChangedSignal();
576 }
577 }
578 }
579
blueAttributeChanged()580 void QgsPointCloud3DSymbolWidget::blueAttributeChanged()
581 {
582 if ( mLayer && mLayer->dataProvider() )
583 {
584 const QVariant max = mLayer->dataProvider()->metadataStatistic( mBlueAttributeComboBox->currentAttribute(), QgsStatisticalSummary::Max );
585 if ( max.isValid() )
586 {
587 const int maxValue = max.toInt();
588 mDisableMinMaxWidgetRefresh++;
589 mBlueMinLineEdit->setText( QLocale().toString( 0 ) );
590
591 // 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
592 // likely to be 8 bit or 16 bit color values
593 mBlueMaxLineEdit->setText( QLocale().toString( maxValue > 255 ? 65535 : 255 ) );
594 mDisableMinMaxWidgetRefresh--;
595 emitChangedSignal();
596 }
597 }
598 }
599
setMaximumScreenError(double maxScreenError)600 void QgsPointCloud3DSymbolWidget::setMaximumScreenError( double maxScreenError )
601 {
602 whileBlocking( mMaxScreenErrorSpinBox )->setValue( maxScreenError );
603 }
604
maximumScreenError() const605 double QgsPointCloud3DSymbolWidget::maximumScreenError() const
606 {
607 return mMaxScreenErrorSpinBox->value();
608 }
609
setShowBoundingBoxes(bool showBoundingBoxes)610 void QgsPointCloud3DSymbolWidget::setShowBoundingBoxes( bool showBoundingBoxes )
611 {
612 whileBlocking( mShowBoundingBoxesCheckBox )->setChecked( showBoundingBoxes );
613 }
614
setPointBudget(double budget)615 void QgsPointCloud3DSymbolWidget::setPointBudget( double budget )
616 {
617 whileBlocking( mPointBudgetSpinBox )->setValue( budget );
618 }
619
pointBudget() const620 double QgsPointCloud3DSymbolWidget::pointBudget() const
621 {
622 return mPointBudgetSpinBox->value();
623 }
624
setPointCloudSize(int size)625 void QgsPointCloud3DSymbolWidget::setPointCloudSize( int size )
626 {
627 mPointCloudSizeLabel->setText( QStringLiteral( "%1 points" ).arg( size ) );
628 }
629
showBoundingBoxes() const630 bool QgsPointCloud3DSymbolWidget::showBoundingBoxes() const
631 {
632 return mShowBoundingBoxesCheckBox->isChecked();
633 }
634
connectChildPanels(QgsPanelWidget * parent)635 void QgsPointCloud3DSymbolWidget::connectChildPanels( QgsPanelWidget *parent )
636 {
637 parent->connectChildPanel( mClassifiedRendererWidget );
638 }
639