QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsmeshrenderer3daveragingwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshrenderer3daveragingwidget.cpp
3  ------------------------------------
4  begin : November 2019
5  copyright : (C) 2019 by Peter Petrik
6  email : zilolv 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 <memory>
17 #include <QSvgRenderer>
18 #include <QPainter>
19 #include <QScreen>
20 #include <QPixmap>
21 #include <QDesktopWidget>
22 
24 
25 #include "qgis.h"
26 #include "qgsmeshlayer.h"
27 #include "qgsmessagelog.h"
29 #include "qgsmesh3daveraging.h"
30 #include "qgsapplication.h"
31 
32 static void _setSvg( QLabel *imageLabel,
33  const QString &imgName )
34 {
35  const qreal dpi = QgsApplication::instance()->desktop()->logicalDpiX();
36  const int desiredWidth = static_cast<int>( 100 * dpi / 25.4 );
37 
38  QSvgRenderer renderer( QStringLiteral( ":/images/themes/default/mesh/%1" ).arg( imgName ) );
39  if ( renderer.isValid() )
40  {
41  const QSize defaultSvgSize = renderer.defaultSize();
42  const int desiredHeight = defaultSvgSize.height() * desiredWidth / defaultSvgSize.width();
43 
44  QPixmap pixmap( QSize( desiredWidth, desiredHeight ) );
45  pixmap.fill( Qt::transparent );
46  QPainter painter;
47 
48  painter.begin( &pixmap );
49  renderer.render( &painter );
50  painter.end();
51  imageLabel->setPixmap( pixmap );
52  }
53 }
54 
56  : QWidget( parent )
57 
58 {
59  setupUi( this );
60  connect( mAveragingMethodComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
61  this, &QgsMeshRenderer3dAveragingWidget::onAveragingMethodChanged );
62 
63  // Single Level Average Method (top)
64  connect( mSingleVerticalLayerIndexTopSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
66  _setSvg( mSingleTopPngLabel,
67  QStringLiteral( "SingleTop.svg" )
68  );
69  mSingleTopGroup->adjustSize();
70 
71  // Single Level Average Method (bottom)
72  connect( mSingleVerticalLayerIndexBottomSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
74  _setSvg( mSingleBottomPngLabel,
75  QStringLiteral( "SingleBottom.svg" )
76  );
77 
78  // Multi Levels Averaging Method (top)
79  connect( mMultiTopVerticalLayerStartIndexSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
81  connect( mMultiTopVerticalLayerEndIndexSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
83  _setSvg( mMultiTopPngLabel,
84  QStringLiteral( "MultiTop.svg" )
85  );
86 
87  // MultiLevels Averaging Method (bottom)
88  connect( mMultiBottomVerticalLayerStartIndexSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
90  connect( mMultiBottomVerticalLayerEndIndexSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
92  _setSvg( mMultiBottomPngLabel,
93  QStringLiteral( "MultiBottom.svg" )
94  );
95 
96  // Sigma Averaging Method
97  connect( mSigmaStartFractionSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
99  connect( mSigmaEndFractionSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
101  _setSvg( mSigmaPngLabel,
102  QStringLiteral( "Sigma.svg" )
103  );
104 
105  // Depth Averaging Method
106  connect( mDepthStartSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
108  connect( mDepthEndSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
110  _setSvg( mDepthPngLabel,
111  QStringLiteral( "Depth.svg" )
112  );
113 
114  // Height Averaging Method
115  connect( mHeightStartSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
117  connect( mHeightEndSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
119  _setSvg( mHeightPngLabel,
120  QStringLiteral( "Height.svg" )
121  );
122 
123  // Elevation Averaging Method
124  connect( mElevationStartSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
126  connect( mElevationEndSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
128  _setSvg( mElevationPngLabel,
129  QStringLiteral( "Elevation.svg" )
130  );
131 }
132 
134 {
135  mMeshLayer = layer;
136 }
137 
138 std::unique_ptr<QgsMesh3dAveragingMethod> QgsMeshRenderer3dAveragingWidget::averagingMethod() const
139 {
140  std::unique_ptr<QgsMesh3dAveragingMethod> averaging;
141 
142  switch ( mAveragingMethodComboBox->currentIndex() )
143  {
144  case 0: // single level from top
145  {
146  const int verticalLevel = mSingleVerticalLayerIndexTopSpinBox->value();
147  averaging.reset( new QgsMeshMultiLevelsAveragingMethod( verticalLevel, true ) );
148  break;
149  }
150  case 1: // single level from bottom
151  {
152  const int verticalLevel = mSingleVerticalLayerIndexBottomSpinBox->value();
153  averaging.reset( new QgsMeshMultiLevelsAveragingMethod( verticalLevel, false ) );
154  break;
155  }
156  case 2: // multi level from top
157  {
158  const int startVerticalLevel = mMultiTopVerticalLayerStartIndexSpinBox->value();
159  const int endVerticalLevel = mMultiTopVerticalLayerEndIndexSpinBox->value();
160  averaging.reset( new QgsMeshMultiLevelsAveragingMethod( startVerticalLevel, endVerticalLevel, true ) );
161  break;
162  }
163  case 3: // multi level from bottom
164  {
165  const int startVerticalLevel = mMultiBottomVerticalLayerStartIndexSpinBox->value();
166  const int endVerticalLevel = mMultiBottomVerticalLayerEndIndexSpinBox->value();
167  averaging.reset( new QgsMeshMultiLevelsAveragingMethod( startVerticalLevel, endVerticalLevel, false ) );
168  break;
169  }
170  case 4: // sigma
171  {
172  const double startFraction = mSigmaStartFractionSpinBox->value();
173  const double endFraction = mSigmaEndFractionSpinBox->value();
174  averaging.reset( new QgsMeshSigmaAveragingMethod( startFraction, endFraction ) );
175  break;
176  }
177  case 5: // depth (from surface)
178  {
179  const double startDepth = mDepthStartSpinBox->value();
180  const double endDepth = mDepthEndSpinBox->value();
181  averaging.reset( new QgsMeshRelativeHeightAveragingMethod( startDepth, endDepth, true ) );
182  break;
183  }
184  case 6: // height (from bed elevation)
185  {
186  const double startHeight = mHeightStartSpinBox->value();
187  const double endHeight = mHeightEndSpinBox->value();
188  averaging.reset( new QgsMeshRelativeHeightAveragingMethod( startHeight, endHeight, false ) );
189  break;
190  }
191  case 7: // elevation
192  {
193  const double startVerticalLevel = mElevationStartSpinBox->value();
194  const double endVerticalLevel = mElevationEndSpinBox->value();
195  averaging.reset( new QgsMeshElevationAveragingMethod( startVerticalLevel, endVerticalLevel ) );
196  break;
197  }
198  }
199  return averaging;
200 }
201 
203 {
204  if ( !mMeshLayer )
205  return;
206 
207  const QgsMeshRendererSettings rendererSettings = mMeshLayer->rendererSettings();
208  const QgsMesh3dAveragingMethod *method = rendererSettings.averagingMethod();
209  if ( method )
210  {
211  const QgsMesh3dAveragingMethod::Method type = method->method();
212  int pageIndex = 0;
213 
214  switch ( type )
215  {
217  {
219  if ( averagingMethod->isSingleLevel() )
220  {
221  if ( averagingMethod->countedFromTop() )
222  {
223  // Single Vertical Layer settings from top
224  whileBlocking( mSingleVerticalLayerIndexTopSpinBox )->setValue( averagingMethod->startVerticalLevel() );
225  pageIndex = 0;
226  }
227  else
228  {
229  // Single Vertical Layer settings from bottom
230  whileBlocking( mSingleVerticalLayerIndexBottomSpinBox )->setValue( averagingMethod->startVerticalLevel() );
231  pageIndex = 1;
232  }
233  }
234  else
235  {
236  if ( averagingMethod->countedFromTop() )
237  {
238  // Multi Vertical Layer settings from top
239  whileBlocking( mMultiTopVerticalLayerStartIndexSpinBox )->setValue( averagingMethod->startVerticalLevel() );
240  whileBlocking( mMultiTopVerticalLayerEndIndexSpinBox )->setValue( averagingMethod->endVerticalLevel() );
241  pageIndex = 2;
242  }
243  else
244  {
245  // Multi Vertical Layer settings from bottom
246  whileBlocking( mMultiBottomVerticalLayerStartIndexSpinBox )->setValue( averagingMethod->startVerticalLevel() );
247  whileBlocking( mMultiBottomVerticalLayerEndIndexSpinBox )->setValue( averagingMethod->endVerticalLevel() );
248  pageIndex = 3;
249  }
250  }
251  break;
252  }
254  {
255  const QgsMeshSigmaAveragingMethod *sigmaAveragingMethod = static_cast<const QgsMeshSigmaAveragingMethod *>( method );
256  whileBlocking( mSigmaStartFractionSpinBox )->setValue( sigmaAveragingMethod->startFraction() );
257  whileBlocking( mSigmaEndFractionSpinBox )->setValue( sigmaAveragingMethod->endFraction() );
258  pageIndex = 4;
259  break;
260  }
262  {
264  if ( averagingMethod->countedFromTop() )
265  {
266  whileBlocking( mDepthStartSpinBox )->setValue( averagingMethod->startHeight() );
267  whileBlocking( mDepthEndSpinBox )->setValue( averagingMethod->endHeight() );
268  pageIndex = 5;
269  }
270  else
271  {
272  whileBlocking( mHeightStartSpinBox )->setValue( averagingMethod->startHeight() );
273  whileBlocking( mHeightEndSpinBox )->setValue( averagingMethod->endHeight() );
274  pageIndex = 6;
275  }
276  break;
277  }
279  {
280  const QgsMeshElevationAveragingMethod *elevationAveragingMethod = static_cast<const QgsMeshElevationAveragingMethod *>( method );
281  whileBlocking( mElevationStartSpinBox )->setValue( elevationAveragingMethod->startElevation() );
282  whileBlocking( mElevationEndSpinBox )->setValue( elevationAveragingMethod->endElevation() );
283  pageIndex = 7;
284  break;
285  }
286  }
287  whileBlocking( mAveragingMethodComboBox )->setCurrentIndex( pageIndex );
288  whileBlocking( mAveragingMethodStackedWidget )->setCurrentIndex( pageIndex );
289  }
290 }
291 
292 void QgsMeshRenderer3dAveragingWidget::onAveragingMethodChanged( int methodIndex )
293 {
294  whileBlocking( mAveragingMethodStackedWidget )->setCurrentIndex( methodIndex );
295  emit widgetChanged();
296 }
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
Abstract class to interpolate 3d stacked mesh data to 2d data.
Method method() const
Returns type of averaging method.
Method
Type of averaging method.
@ RelativeHeightAveragingMethod
Method to average values defined by range of relative length units to the surface or bed level.
@ MultiLevelsAveragingMethod
Method to average values from selected vertical layers.
@ ElevationAveragingMethod
Method to average values defined by range of absolute length units to the model's datum.
@ SigmaAveragingMethod
Method to average values between 0 (bed level) and 1 (surface)
Elevation averaging method averages the values based on range defined absolute value to the model's d...
double startElevation() const
Returns start elevation.
double endElevation() const
Returns end elevation.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:97
QgsMeshRendererSettings rendererSettings() const
Returns renderer settings.
Multi level averaging method specifies limits of vertical layers from the top layer down or reversed.
Relative height averaging method averages the values based on range defined relative to bed elevation...
QgsMeshRenderer3dAveragingWidget(QWidget *parent=nullptr)
A widget to hold the renderer Vector settings for a mesh layer.
std::unique_ptr< QgsMesh3dAveragingMethod > averagingMethod() const
Returns selected averaging method.
void setLayer(QgsMeshLayer *layer)
Associates mesh layer with the widget.
void syncToLayer()
Synchronizes widgets state with associated mesh layer.
void widgetChanged()
Mesh rendering settings changed.
Represents all mesh renderer settings.
QgsMesh3dAveragingMethod * averagingMethod() const
Returns averaging method for conversion of 3d stacked mesh data to 2d data.
Sigma averages over the values between 0 (bed level) and 1 (surface).
double endFraction() const
Returns ending fraction.
double startFraction() const
Returns starting fraction.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:1185