QGIS API Documentation  3.21.0-Master (909859188c)
qgspointcloudattributebyramprendererwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointcloudattributebyramprendererwidget.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 "qgscontrastenhancement.h"
20 #include "qgspointcloudlayer.h"
22 #include "qgsdoublevalidator.h"
23 #include "qgsstyle.h"
25 
27 
28 QgsPointCloudAttributeByRampRendererWidget::QgsPointCloudAttributeByRampRendererWidget( QgsPointCloudLayer *layer, QgsStyle *style )
29  : QgsPointCloudRendererWidget( layer, style )
30 {
31  setupUi( this );
32 
33  mAttributeComboBox->setAllowEmptyAttributeName( false );
34  mAttributeComboBox->setFilters( QgsPointCloudAttributeProxyModel::AllTypes );
35 
36  mMinSpin->setShowClearButton( false );
37  mMaxSpin->setShowClearButton( false );
38 
39  if ( layer )
40  {
41  mAttributeComboBox->setLayer( layer );
42 
43  setFromRenderer( layer->renderer() );
44  }
45 
46  connect( mAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged,
47  this, &QgsPointCloudAttributeByRampRendererWidget::attributeChanged );
48  connect( mMinSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsPointCloudAttributeByRampRendererWidget::minMaxChanged );
49  connect( mMaxSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsPointCloudAttributeByRampRendererWidget::minMaxChanged );
50 
51  connect( mScalarColorRampShaderWidget, &QgsColorRampShaderWidget::widgetChanged, this, &QgsPointCloudAttributeByRampRendererWidget::emitWidgetChanged );
52  connect( mScalarRecalculateMinMaxButton, &QPushButton::clicked, this, &QgsPointCloudAttributeByRampRendererWidget::setMinMaxFromLayer );
53 }
54 
55 QgsPointCloudRendererWidget *QgsPointCloudAttributeByRampRendererWidget::create( QgsPointCloudLayer *layer, QgsStyle *style, QgsPointCloudRenderer * )
56 {
57  return new QgsPointCloudAttributeByRampRendererWidget( layer, style );
58 }
59 
60 QgsPointCloudRenderer *QgsPointCloudAttributeByRampRendererWidget::renderer()
61 {
62  if ( !mLayer )
63  {
64  return nullptr;
65  }
66 
67  std::unique_ptr< QgsPointCloudAttributeByRampRenderer > renderer = std::make_unique< QgsPointCloudAttributeByRampRenderer >();
68  renderer->setAttribute( mAttributeComboBox->currentAttribute() );
69 
70  renderer->setMinimum( mMinSpin->value() );
71  renderer->setMaximum( mMaxSpin->value() );
72 
73  renderer->setColorRampShader( mScalarColorRampShaderWidget->shader() );
74 
75  return renderer.release();
76 }
77 
78 void QgsPointCloudAttributeByRampRendererWidget::emitWidgetChanged()
79 {
80  if ( !mBlockChangedSignal )
81  emit widgetChanged();
82 }
83 
84 void QgsPointCloudAttributeByRampRendererWidget::minMaxChanged()
85 {
86  if ( mBlockMinMaxChanged )
87  return;
88 
89  mScalarColorRampShaderWidget->setMinimumMaximumAndClassify( mMinSpin->value(), mMaxSpin->value() );
90 }
91 
92 void QgsPointCloudAttributeByRampRendererWidget::attributeChanged()
93 {
94  if ( mLayer && mLayer->dataProvider() )
95  {
96  const QVariant min = mLayer->dataProvider()->metadataStatistic( mAttributeComboBox->currentAttribute(), QgsStatisticalSummary::Min );
97  const QVariant max = mLayer->dataProvider()->metadataStatistic( mAttributeComboBox->currentAttribute(), QgsStatisticalSummary::Max );
98  if ( min.isValid() && max.isValid() )
99  {
100  mProviderMin = min.toDouble();
101  mProviderMax = max.toDouble();
102  }
103  else
104  {
105  mProviderMin = std::numeric_limits< double >::quiet_NaN();
106  mProviderMax = std::numeric_limits< double >::quiet_NaN();
107  }
108 
109  if ( mAttributeComboBox->currentAttribute().compare( QLatin1String( "z" ), Qt::CaseInsensitive ) == 0 )
110  {
111  const double zScale = static_cast< const QgsPointCloudLayerElevationProperties * >( mLayer->elevationProperties() )->zScale();
112  const double zOffset = static_cast< const QgsPointCloudLayerElevationProperties * >( mLayer->elevationProperties() )->zOffset();
113  mProviderMin = mProviderMin * zScale + zOffset;
114  mProviderMax = mProviderMax * zScale + zOffset;
115  }
116 
117  }
118  if ( !mBlockSetMinMaxFromLayer )
119  setMinMaxFromLayer();
120 
121  mScalarRecalculateMinMaxButton->setEnabled( !std::isnan( mProviderMin ) && !std::isnan( mProviderMax ) );
122  emitWidgetChanged();
123 }
124 
125 void QgsPointCloudAttributeByRampRendererWidget::setMinMaxFromLayer()
126 {
127  if ( std::isnan( mProviderMin ) || std::isnan( mProviderMax ) )
128  return;
129 
130  mBlockMinMaxChanged = true;
131  mMinSpin->setValue( mProviderMin );
132  mMaxSpin->setValue( mProviderMax );
133  mBlockMinMaxChanged = false;
134 
135  minMaxChanged();
136 }
137 
138 void QgsPointCloudAttributeByRampRendererWidget::setFromRenderer( const QgsPointCloudRenderer *r )
139 {
140  mBlockChangedSignal = true;
141  const QgsPointCloudAttributeByRampRenderer *mbcr = dynamic_cast<const QgsPointCloudAttributeByRampRenderer *>( r );
142  if ( mbcr )
143  {
144  // we will be restoring the existing ramp classes -- we don't want to regenerate any automatically!
145  mBlockSetMinMaxFromLayer = true;
146 
147  mAttributeComboBox->setAttribute( mbcr->attribute() );
148 
149  mMinSpin->setValue( mbcr->minimum() );
150  mMaxSpin->setValue( mbcr->maximum() );
151 
152  whileBlocking( mScalarColorRampShaderWidget )->setFromShader( mbcr->colorRampShader() );
153  whileBlocking( mScalarColorRampShaderWidget )->setMinimumMaximum( mbcr->minimum(), mbcr->maximum() );
154  }
155  else
156  {
157  if ( mAttributeComboBox->findText( QStringLiteral( "Intensity" ) ) > -1 )
158  {
159  mAttributeComboBox->setAttribute( QStringLiteral( "Intensity" ) );
160  }
161  else
162  {
163  mAttributeComboBox->setCurrentIndex( mAttributeComboBox->count() > 1 ? 1 : 0 );
164  }
165  }
166  attributeChanged();
167  mBlockChangedSignal = false;
168  mBlockSetMinMaxFromLayer = false;
169 }
170 
void widgetChanged()
Widget changed.
An RGB renderer for 2d visualisation of point clouds using embedded red, green and blue attributes.
double maximum() const
Returns the maximum value for attributes which will be used by the color ramp shader.
QgsColorRampShader colorRampShader() const
Returns the color ramp shader function used to visualize the attribute.
double minimum() const
Returns the minimum value for attributes which will be used by the color ramp shader.
QString attribute() const
Returns the attribute to use for the renderer.
void setAttribute(const QString &attribute)
Sets the attribute to use for the renderer.
void attributeChanged(const QString &name)
Emitted when the currently selected attribute changes.
Point cloud layer specific subclass of QgsMapLayerElevationProperties.
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.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:1047