QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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 <QPixmap>
20
22
23#include "qgis.h"
24#include "qgsmeshlayer.h"
26#include "qgsmesh3daveraging.h"
27#include "qgsapplication.h"
28#include "qgsscreenhelper.h"
29
30
32 : QWidget( parent )
33
34{
35 setupUi( this );
36
37 mScreenHelper = new QgsScreenHelper( this );
38
39 connect( mAveragingMethodComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
40 this, &QgsMeshRenderer3DAveragingWidget::onAveragingMethodChanged );
41
42 // Single Level Average Method (top)
43 connect( mSingleVerticalLayerIndexTopSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
45
46 // Single Level Average Method (bottom)
47 connect( mSingleVerticalLayerIndexBottomSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
49
50 // Multi Levels Averaging Method (top)
51 connect( mMultiTopVerticalLayerStartIndexSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
53 connect( mMultiTopVerticalLayerEndIndexSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
55
56 // MultiLevels Averaging Method (bottom)
57 connect( mMultiBottomVerticalLayerStartIndexSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
59 connect( mMultiBottomVerticalLayerEndIndexSpinBox, qOverload<int>( &QgsSpinBox::valueChanged ),
61
62 // Sigma Averaging Method
63 connect( mSigmaStartFractionSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
65 connect( mSigmaEndFractionSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
67
68 // Depth Averaging Method
69 connect( mDepthStartSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
71 connect( mDepthEndSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
73
74 // Height Averaging Method
75 connect( mHeightStartSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
77 connect( mHeightEndSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
79
80
81 // Elevation Averaging Method
82 connect( mElevationStartSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
84 connect( mElevationEndSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
86
87 updateGraphics();
88 connect( mScreenHelper, &QgsScreenHelper::screenDpiChanged, this, &QgsMeshRenderer3DAveragingWidget::updateGraphics );
89}
90
92{
93 mMeshLayer = layer;
94}
95
96std::unique_ptr<QgsMesh3DAveragingMethod> QgsMeshRenderer3DAveragingWidget::averagingMethod() const
97{
98 std::unique_ptr<QgsMesh3DAveragingMethod> averaging;
99
100 switch ( mAveragingMethodComboBox->currentIndex() )
101 {
102 case 0: // single level from top
103 {
104 const int verticalLevel = mSingleVerticalLayerIndexTopSpinBox->value();
105 averaging.reset( new QgsMeshMultiLevelsAveragingMethod( verticalLevel, true ) );
106 break;
107 }
108 case 1: // single level from bottom
109 {
110 const int verticalLevel = mSingleVerticalLayerIndexBottomSpinBox->value();
111 averaging.reset( new QgsMeshMultiLevelsAveragingMethod( verticalLevel, false ) );
112 break;
113 }
114 case 2: // multi level from top
115 {
116 const int startVerticalLevel = mMultiTopVerticalLayerStartIndexSpinBox->value();
117 const int endVerticalLevel = mMultiTopVerticalLayerEndIndexSpinBox->value();
118 averaging.reset( new QgsMeshMultiLevelsAveragingMethod( startVerticalLevel, endVerticalLevel, true ) );
119 break;
120 }
121 case 3: // multi level from bottom
122 {
123 const int startVerticalLevel = mMultiBottomVerticalLayerStartIndexSpinBox->value();
124 const int endVerticalLevel = mMultiBottomVerticalLayerEndIndexSpinBox->value();
125 averaging.reset( new QgsMeshMultiLevelsAveragingMethod( startVerticalLevel, endVerticalLevel, false ) );
126 break;
127 }
128 case 4: // sigma
129 {
130 const double startFraction = mSigmaStartFractionSpinBox->value();
131 const double endFraction = mSigmaEndFractionSpinBox->value();
132 averaging.reset( new QgsMeshSigmaAveragingMethod( startFraction, endFraction ) );
133 break;
134 }
135 case 5: // depth (from surface)
136 {
137 const double startDepth = mDepthStartSpinBox->value();
138 const double endDepth = mDepthEndSpinBox->value();
139 averaging.reset( new QgsMeshRelativeHeightAveragingMethod( startDepth, endDepth, true ) );
140 break;
141 }
142 case 6: // height (from bed elevation)
143 {
144 const double startHeight = mHeightStartSpinBox->value();
145 const double endHeight = mHeightEndSpinBox->value();
146 averaging.reset( new QgsMeshRelativeHeightAveragingMethod( startHeight, endHeight, false ) );
147 break;
148 }
149 case 7: // elevation
150 {
151 const double startVerticalLevel = mElevationStartSpinBox->value();
152 const double endVerticalLevel = mElevationEndSpinBox->value();
153 averaging.reset( new QgsMeshElevationAveragingMethod( startVerticalLevel, endVerticalLevel ) );
154 break;
155 }
156 }
157 return averaging;
158}
159
161{
162 if ( !mMeshLayer )
163 return;
164
165 const QgsMeshRendererSettings rendererSettings = mMeshLayer->rendererSettings();
166 const QgsMesh3DAveragingMethod *method = rendererSettings.averagingMethod();
167 if ( method )
168 {
169 const QgsMesh3DAveragingMethod::Method type = method->method();
170 int pageIndex = 0;
171
172 switch ( type )
173 {
175 {
177 if ( averagingMethod->isSingleLevel() )
178 {
179 if ( averagingMethod->countedFromTop() )
180 {
181 // Single Vertical Layer settings from top
182 whileBlocking( mSingleVerticalLayerIndexTopSpinBox )->setValue( averagingMethod->startVerticalLevel() );
183 pageIndex = 0;
184 }
185 else
186 {
187 // Single Vertical Layer settings from bottom
188 whileBlocking( mSingleVerticalLayerIndexBottomSpinBox )->setValue( averagingMethod->startVerticalLevel() );
189 pageIndex = 1;
190 }
191 }
192 else
193 {
194 if ( averagingMethod->countedFromTop() )
195 {
196 // Multi Vertical Layer settings from top
197 whileBlocking( mMultiTopVerticalLayerStartIndexSpinBox )->setValue( averagingMethod->startVerticalLevel() );
198 whileBlocking( mMultiTopVerticalLayerEndIndexSpinBox )->setValue( averagingMethod->endVerticalLevel() );
199 pageIndex = 2;
200 }
201 else
202 {
203 // Multi Vertical Layer settings from bottom
204 whileBlocking( mMultiBottomVerticalLayerStartIndexSpinBox )->setValue( averagingMethod->startVerticalLevel() );
205 whileBlocking( mMultiBottomVerticalLayerEndIndexSpinBox )->setValue( averagingMethod->endVerticalLevel() );
206 pageIndex = 3;
207 }
208 }
209 break;
210 }
212 {
213 const QgsMeshSigmaAveragingMethod *sigmaAveragingMethod = static_cast<const QgsMeshSigmaAveragingMethod *>( method );
214 whileBlocking( mSigmaStartFractionSpinBox )->setValue( sigmaAveragingMethod->startFraction() );
215 whileBlocking( mSigmaEndFractionSpinBox )->setValue( sigmaAveragingMethod->endFraction() );
216 pageIndex = 4;
217 break;
218 }
220 {
222 if ( averagingMethod->countedFromTop() )
223 {
224 whileBlocking( mDepthStartSpinBox )->setValue( averagingMethod->startHeight() );
225 whileBlocking( mDepthEndSpinBox )->setValue( averagingMethod->endHeight() );
226 pageIndex = 5;
227 }
228 else
229 {
230 whileBlocking( mHeightStartSpinBox )->setValue( averagingMethod->startHeight() );
231 whileBlocking( mHeightEndSpinBox )->setValue( averagingMethod->endHeight() );
232 pageIndex = 6;
233 }
234 break;
235 }
237 {
238 const QgsMeshElevationAveragingMethod *elevationAveragingMethod = static_cast<const QgsMeshElevationAveragingMethod *>( method );
239 whileBlocking( mElevationStartSpinBox )->setValue( elevationAveragingMethod->startElevation() );
240 whileBlocking( mElevationEndSpinBox )->setValue( elevationAveragingMethod->endElevation() );
241 pageIndex = 7;
242 break;
243 }
244 }
245 whileBlocking( mAveragingMethodComboBox )->setCurrentIndex( pageIndex );
246 whileBlocking( mAveragingMethodStackedWidget )->setCurrentIndex( pageIndex );
247 }
248}
249
250void QgsMeshRenderer3DAveragingWidget::onAveragingMethodChanged( int methodIndex )
251{
252 whileBlocking( mAveragingMethodStackedWidget )->setCurrentIndex( methodIndex );
253 emit widgetChanged();
254}
255
256void QgsMeshRenderer3DAveragingWidget::updateGraphics()
257{
258 setLabelSvg( mSingleTopPngLabel, QStringLiteral( "SingleTop.svg" ) );
259 mSingleTopGroup->adjustSize();
260
261 setLabelSvg( mSingleBottomPngLabel, QStringLiteral( "SingleBottom.svg" ) );
262 setLabelSvg( mMultiTopPngLabel, QStringLiteral( "MultiTop.svg" ) );
263 setLabelSvg( mMultiBottomPngLabel, QStringLiteral( "MultiBottom.svg" ) );
264 setLabelSvg( mSigmaPngLabel, QStringLiteral( "Sigma.svg" ) );
265 setLabelSvg( mDepthPngLabel, QStringLiteral( "Depth.svg" ) );
266 setLabelSvg( mHeightPngLabel, QStringLiteral( "Height.svg" ) );
267 setLabelSvg( mElevationPngLabel, QStringLiteral( "Elevation.svg" ) );
268}
269
270void QgsMeshRenderer3DAveragingWidget::setLabelSvg( QLabel *imageLabel, const QString &imgName )
271{
272 const qreal dpi = mScreenHelper->screenDpi();
273 const int desiredWidth = static_cast<int>( 100 * dpi / 25.4 );
274
275 QSvgRenderer renderer( QStringLiteral( ":/images/themes/default/mesh/%1" ).arg( imgName ) );
276 if ( renderer.isValid() )
277 {
278 const QSize defaultSvgSize = renderer.defaultSize();
279 const int desiredHeight = defaultSvgSize.height() * desiredWidth / defaultSvgSize.width();
280
281 QPixmap pixmap( QSize( desiredWidth, desiredHeight ) );
282 pixmap.fill( Qt::transparent );
283 QPainter painter;
284
285 painter.begin( &pixmap );
286 renderer.render( &painter );
287 painter.end();
288 imageLabel->setPixmap( pixmap );
289 }
290}
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:101
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...
void setLayer(QgsMeshLayer *layer)
Associates mesh layer with the widget.
QgsMeshRenderer3DAveragingWidget(QWidget *parent=nullptr)
A widget to hold the renderer Vector settings for a mesh layer.
void widgetChanged()
Mesh rendering settings changed.
std::unique_ptr< QgsMesh3DAveragingMethod > averagingMethod() const
Returns selected averaging method.
void syncToLayer()
Synchronizes widgets state with associated mesh layer.
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.
A utility class for dynamic handling of changes to screen properties.
double screenDpi() const
Returns the current screen DPI for the screen that the parent widget appears on.
void screenDpiChanged(double dpi)
Emitted whenever the screen dpi associated with the widget is changed.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:5111