1 /***************************************************************************
2 testqgsmeshlayer.cpp
3 --------------------
4 begin : April 2018
5 copyright : (C) 2018 by Peter Petrik
6 email : zilolv 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
18 #include "qgstest.h"
19 #include <QObject>
20 #include <QString>
21 #include <QLabel>
22 #include <QStringList>
23 #include <QApplication>
24 #include <QFileInfo>
25 #include <QDir>
26 #include <QDesktopServices>
27
28 //qgis includes...
29 #include "qgsmaplayer.h"
30 #include "qgsmeshlayer.h"
31 #include "qgsapplication.h"
32 #include "qgsmaplayerlegend.h"
33 #include "qgsproviderregistry.h"
34 #include "qgsproject.h"
35 #include "qgsmaprenderersequentialjob.h"
36 #include "qgsmeshmemorydataprovider.h"
37 #include "qgsmesh3daveraging.h"
38 #include "qgsmeshlayertemporalproperties.h"
39
40 //qgis test includes
41 #include "qgsrenderchecker.h"
42
43 /**
44 * \ingroup UnitTests
45 * This is a unit test for the different renderers for mesh layers.
46 */
47 class TestQgsMeshRenderer : public QObject
48 {
49 Q_OBJECT
50
51 public:
52 TestQgsMeshRenderer() = default;
53
54 private:
55 QString mDataDir;
56 QgsMeshLayer *mMemory1DLayer = nullptr;
57 QgsMeshLayer *mMemoryLayer = nullptr;
58 QgsMeshLayer *mMdalLayer = nullptr;
59 QgsMeshLayer *mMdal3DLayer = nullptr;
60 QgsMapSettings *mMapSettings = nullptr;
61 QString mReport;
62
63 private slots:
64 void initTestCase();// will be called before the first testfunction is executed.
65 void cleanupTestCase();// will be called after the last testfunction was executed.
66 void init(); // will be called before each testfunction is executed.
cleanup()67 void cleanup() {} // will be called after every testfunction.
68 bool imageCheck( const QString &testType, QgsMeshLayer *layer, double rotation = 0.0 );
69 QString readFile( const QString &fname ) const;
70
71
72 void test_native_mesh_rendering();
73 void test_native_mesh_renderingWithClipping();
74 void test_triangular_mesh_rendering();
75 void test_edge_mesh_rendering();
76
77 void test_1d_vertex_scalar_dataset_rendering();
78 void test_1d_vertex_vector_dataset_rendering();
79 void test_1d_edge_scalar_dataset_rendering();
80 void test_1d_edge_vector_dataset_rendering();
81
82 void test_vertex_scalar_dataset_rendering();
83 void test_vertex_vector_dataset_rendering();
84 void test_vertex_vector_dataset_colorRamp_rendering();
85 void test_face_scalar_dataset_rendering();
86 void test_face_scalar_dataset_interpolated_neighbour_average_rendering();
87 void test_face_vector_dataset_rendering();
88 void test_vertex_scalar_dataset_with_inactive_face_rendering();
89 void test_face_vector_on_user_grid();
90 void test_face_vector_on_user_grid_streamlines();
91 void test_vertex_vector_on_user_grid();
92 void test_vertex_vector_on_user_grid_streamlines();
93 void test_vertex_vector_on_user_grid_streamlines_colorRamp();
94 void test_vertex_vector_traces();
95 void test_vertex_vector_traces_colorRamp();
96 void test_stacked_3d_mesh_single_level_averaging();
97 void test_simplified_triangular_mesh_rendering();
98 void test_classified_values();
99
100 void test_signals();
101 };
102
init()103 void TestQgsMeshRenderer::init()
104 {
105 QgsMeshRendererSettings rendererSettings = mMemory1DLayer->rendererSettings();
106 rendererSettings.setNativeMeshSettings( QgsMeshRendererMeshSettings() );
107 rendererSettings.setTriangularMeshSettings( QgsMeshRendererMeshSettings() );
108 rendererSettings.setEdgeMeshSettings( QgsMeshRendererMeshSettings() );
109 rendererSettings.setAveragingMethod( nullptr );
110 mMemory1DLayer->setRendererSettings( rendererSettings );
111 mMemory1DLayer->temporalProperties()->setIsActive( false );
112 mMemory1DLayer->setStaticScalarDatasetIndex( QgsMeshDatasetIndex() );
113 mMemory1DLayer->setStaticVectorDatasetIndex( QgsMeshDatasetIndex() );
114
115 rendererSettings = mMemoryLayer->rendererSettings();
116 rendererSettings.setNativeMeshSettings( QgsMeshRendererMeshSettings() );
117 rendererSettings.setTriangularMeshSettings( QgsMeshRendererMeshSettings() );
118 rendererSettings.setEdgeMeshSettings( QgsMeshRendererMeshSettings() );
119 rendererSettings.setAveragingMethod( nullptr );
120 mMemoryLayer->setRendererSettings( rendererSettings );
121 mMemoryLayer->temporalProperties()->setIsActive( false );
122 mMemoryLayer->setStaticScalarDatasetIndex( QgsMeshDatasetIndex() );
123 mMemoryLayer->setStaticVectorDatasetIndex( QgsMeshDatasetIndex() );
124
125 rendererSettings = mMdalLayer->rendererSettings();
126 rendererSettings.setNativeMeshSettings( QgsMeshRendererMeshSettings() );
127 rendererSettings.setTriangularMeshSettings( QgsMeshRendererMeshSettings() );
128 rendererSettings.setEdgeMeshSettings( QgsMeshRendererMeshSettings() );
129 rendererSettings.setAveragingMethod( nullptr );
130 mMdalLayer->setRendererSettings( rendererSettings );
131 mMdalLayer->temporalProperties()->setIsActive( false );
132 mMdalLayer->setStaticScalarDatasetIndex( QgsMeshDatasetIndex() );
133 mMdalLayer->setStaticVectorDatasetIndex( QgsMeshDatasetIndex() );
134
135 rendererSettings = mMdal3DLayer->rendererSettings();
136 rendererSettings.setNativeMeshSettings( QgsMeshRendererMeshSettings() );
137 rendererSettings.setTriangularMeshSettings( QgsMeshRendererMeshSettings() );
138 rendererSettings.setEdgeMeshSettings( QgsMeshRendererMeshSettings() );
139 rendererSettings.setAveragingMethod( nullptr );
140 mMdal3DLayer->setRendererSettings( rendererSettings );
141 mMdal3DLayer->temporalProperties()->setIsActive( false );
142 mMdal3DLayer->setStaticScalarDatasetIndex( QgsMeshDatasetIndex() );
143 mMdal3DLayer->setStaticVectorDatasetIndex( QgsMeshDatasetIndex() );
144 }
145
initTestCase()146 void TestQgsMeshRenderer::initTestCase()
147 {
148 // init QGIS's paths - true means that all path will be inited from prefix
149 QgsApplication::init();
150 QgsApplication::initQgis();
151 QgsApplication::showSettings();
152 mDataDir = QString( TEST_DATA_DIR ); //defined in CmakeLists.txt
153 mDataDir += "/mesh";
154
155 mReport = QStringLiteral( "<h1>Mesh Layer Rendering Tests</h1>\n" );
156
157 mMapSettings = new QgsMapSettings();
158
159 // Memory 1D layer
160 mMemory1DLayer = new QgsMeshLayer( readFile( "/lines.txt" ), "Lines Memory", "mesh_memory" );
161 mMemory1DLayer->dataProvider()->addDataset( readFile( "/lines_vertex_scalar.txt" ) );
162 mMemory1DLayer->dataProvider()->addDataset( readFile( "/lines_vertex_vector.txt" ) );
163 mMemory1DLayer->dataProvider()->addDataset( readFile( "/lines_els_scalar.txt" ) );
164 mMemory1DLayer->dataProvider()->addDataset( readFile( "/lines_els_vector.txt" ) );
165 QVERIFY( mMemory1DLayer->isValid() );
166
167 // Mdal layer
168 mMdalLayer = new QgsMeshLayer( mDataDir + "/quad_and_triangle.2dm", "Triangle and Quad Mdal", "mdal" );
169 mMdalLayer->dataProvider()->addDataset( mDataDir + "/quad_and_triangle_vertex_scalar_with_inactive_face.dat" );
170 QVERIFY( mMdalLayer->isValid() );
171
172 // Memory layer
173 mMemoryLayer = new QgsMeshLayer( readFile( "/quad_and_triangle.txt" ), "Triangle and Quad Memory", "mesh_memory" );
174 mMemoryLayer->dataProvider()->addDataset( readFile( "/quad_and_triangle_vertex_scalar.txt" ) );
175 mMemoryLayer->dataProvider()->addDataset( readFile( "/quad_and_triangle_vertex_vector.txt" ) );
176 mMemoryLayer->dataProvider()->addDataset( readFile( "/quad_and_triangle_face_scalar.txt" ) );
177 mMemoryLayer->dataProvider()->addDataset( readFile( "/quad_and_triangle_face_vector.txt" ) );
178 QVERIFY( mMemoryLayer->isValid() );
179
180 // Mdal 3D layer
181 mMdal3DLayer = new QgsMeshLayer( mDataDir + "/trap_steady_05_3D.nc", "Stacked 3D Mdal", "mdal" );
182 QVERIFY( mMdal3DLayer->isValid() );
183
184 // Add layers
185 QgsProject::instance()->addMapLayers(
186 QList<QgsMapLayer *>() << mMemory1DLayer << mMemoryLayer << mMdalLayer << mMdal3DLayer );
187 mMapSettings->setLayers(
188 QList<QgsMapLayer *>() << mMemory1DLayer << mMemoryLayer << mMdalLayer << mMdal3DLayer );
189
190 // here we check that datasets automatically get our default color ramp applied ("Plasma")
191 QgsMeshDatasetIndex ds( 0, 0 );
192 QgsMeshRendererScalarSettings scalarSettings = mMemoryLayer->rendererSettings().scalarSettings( ds.group() );
193 QgsColorRampShader shader = scalarSettings.colorRampShader();
194 QList<QgsColorRampShader::ColorRampItem> lst = shader.colorRampItemList();
195 QCOMPARE( lst.count(), 52 );
196 QCOMPARE( lst.at( 0 ).value, 1. ); // min group value
197 QCOMPARE( lst.at( lst.count() - 1 ).value, 4. ); // max group value
198
199 ds = QgsMeshDatasetIndex( 1, 0 );
200 QgsMeshRendererVectorSettings vectorSettings = mMemoryLayer->rendererSettings().vectorSettings( ds.group() );
201 shader = vectorSettings.colorRampShader();
202 lst = shader.colorRampItemList();
203 QCOMPARE( lst.count(), 52 );
204 QVERIFY( fabs( lst.at( 0 ).value - 1.41421356237 ) < 0.000001 ); // min group value
205 QCOMPARE( lst.at( lst.count() - 1 ).value, 5. ); // max group value
206 }
207
cleanupTestCase()208 void TestQgsMeshRenderer::cleanupTestCase()
209 {
210 QString myReportFile = QDir::tempPath() + "/qgistest.html";
211 QFile myFile( myReportFile );
212 if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
213 {
214 QTextStream myQTextStream( &myFile );
215 myQTextStream << mReport;
216 myFile.close();
217 }
218
219 QgsApplication::exitQgis();
220 }
221
readFile(const QString & fname) const222 QString TestQgsMeshRenderer::readFile( const QString &fname ) const
223 {
224 QString uri;
225 QFile f( mDataDir + fname );
226 if ( f.open( QIODevice::ReadOnly | QIODevice::Text ) )
227 uri = f.readAll();
228 return uri;
229 }
230
imageCheck(const QString & testType,QgsMeshLayer * layer,double rotation)231 bool TestQgsMeshRenderer::imageCheck( const QString &testType, QgsMeshLayer *layer, double rotation )
232 {
233 mReport += "<h2>" + testType + "</h2>\n";
234 mMapSettings->setDestinationCrs( layer->crs() );
235 mMapSettings->setExtent( layer->extent() );
236 mMapSettings->setRotation( rotation );
237 mMapSettings->setOutputDpi( 96 );
238
239 QgsRenderChecker myChecker;
240 myChecker.setControlPathPrefix( QStringLiteral( "mesh" ) );
241 myChecker.setControlName( "expected_" + testType );
242 myChecker.setMapSettings( *mMapSettings );
243 myChecker.setColorTolerance( 15 );
244 bool myResultFlag = myChecker.runTest( testType, 0 );
245 mReport += myChecker.report();
246 return myResultFlag;
247 }
248
test_native_mesh_rendering()249 void TestQgsMeshRenderer::test_native_mesh_rendering()
250 {
251 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
252 QgsMeshRendererMeshSettings settings = rendererSettings.nativeMeshSettings();
253 settings.setEnabled( true );
254 settings.setLineWidth( 1. );
255 rendererSettings.setNativeMeshSettings( settings );
256 mMemoryLayer->setRendererSettings( rendererSettings );
257 QVERIFY( imageCheck( "quad_and_triangle_native_mesh", mMemoryLayer ) );
258 QVERIFY( imageCheck( "quad_and_triangle_native_mesh_rotated_45", mMemoryLayer, 45.0 ) );
259 }
260
test_native_mesh_renderingWithClipping()261 void TestQgsMeshRenderer::test_native_mesh_renderingWithClipping()
262 {
263 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
264 QgsMeshRendererMeshSettings settings = rendererSettings.nativeMeshSettings();
265 settings.setEnabled( true );
266 settings.setLineWidth( 1. );
267 rendererSettings.setNativeMeshSettings( settings );
268 mMemoryLayer->setRendererSettings( rendererSettings );
269
270 QgsMapClippingRegion region( QgsGeometry::fromWkt( "Polygon ((1706.47279549718587077 2907.78611632270212795, 1306.56660412757969425 2480.30018761726114462, 1665.10318949343354689 2123.73358348968167775, 2360.5065666041273289 2060.6941838649163401, 2640.24390243902416842 2669.41838649155761232, 2228.51782363977508794 2874.29643527204552811, 1706.47279549718587077 2907.78611632270212795))" ) );
271 region.setFeatureClip( QgsMapClippingRegion::FeatureClippingType::ClipPainterOnly );
272 QgsMapClippingRegion region2( QgsGeometry::fromWkt( "Polygon ((1966.51031894934340016 2925.51594746716773443, 1801.03189493433410462 2452.7204502814265652, 2057.12945590994377199 2027.20450281425951289, 2457.03564727954972113 2033.11444652908130593, 2380.20637898686709377 2957.03564727955017588, 1966.51031894934340016 2925.51594746716773443))" ) );
273 region2.setFeatureClip( QgsMapClippingRegion::FeatureClippingType::ClipToIntersection );
274 mMapSettings->addClippingRegion( region );
275 mMapSettings->addClippingRegion( region2 );
276
277 const bool res = imageCheck( "painterclip_region", mMemoryLayer );
278
279 mMapSettings->setClippingRegions( QList< QgsMapClippingRegion >() );
280 QVERIFY( res );
281 }
282
test_triangular_mesh_rendering()283 void TestQgsMeshRenderer::test_triangular_mesh_rendering()
284 {
285 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
286 QgsMeshRendererMeshSettings settings = rendererSettings.triangularMeshSettings();
287 settings.setEnabled( true );
288 settings.setColor( Qt::red );
289 settings.setLineWidth( 0.26 );
290 rendererSettings.setTriangularMeshSettings( settings );
291 mMemoryLayer->setRendererSettings( rendererSettings );
292 QVERIFY( imageCheck( "quad_and_triangle_triangular_mesh", mMemoryLayer ) );
293 QVERIFY( imageCheck( "quad_and_triangle_triangular_mesh_rotated_45", mMemoryLayer, 45.0 ) );
294 }
295
test_edge_mesh_rendering()296 void TestQgsMeshRenderer::test_edge_mesh_rendering()
297 {
298 QgsMeshRendererSettings rendererSettings = mMemory1DLayer->rendererSettings();
299 QgsMeshRendererMeshSettings settings = rendererSettings.edgeMeshSettings();
300 settings.setEnabled( true );
301 settings.setColor( Qt::red );
302 settings.setLineWidth( 0.26 );
303 rendererSettings.setEdgeMeshSettings( settings );
304 mMemory1DLayer->setRendererSettings( rendererSettings );
305 QVERIFY( imageCheck( "lines_edge_mesh", mMemory1DLayer ) );
306 }
307
test_1d_vertex_scalar_dataset_rendering()308 void TestQgsMeshRenderer::test_1d_vertex_scalar_dataset_rendering()
309 {
310 QgsMeshDatasetIndex ds( 0, 0 );
311 const QgsMeshDatasetGroupMetadata metadata = mMemory1DLayer->dataProvider()->datasetGroupMetadata( ds );
312 QVERIFY( metadata.name() == "VertexScalarDataset" );
313
314 QgsMeshRendererSettings rendererSettings = mMemory1DLayer->rendererSettings();
315 QgsMeshRendererScalarSettings scalarSettings = rendererSettings.scalarSettings( 0 );
316 QgsInterpolatedLineWidth strokeWidth = scalarSettings.edgeStrokeWidth();
317 strokeWidth.setMaximumValue( 3 );
318 strokeWidth.setMaximumWidth( 2 );
319 strokeWidth.setIsVariableWidth( true );
320 scalarSettings.setEdgeStrokeWidth( strokeWidth );
321 rendererSettings.setScalarSettings( 0, scalarSettings );
322 mMemory1DLayer->setRendererSettings( rendererSettings );
323 mMemory1DLayer->setStaticScalarDatasetIndex( ds );
324
325 QVERIFY( imageCheck( "lines_vertex_scalar_dataset", mMemory1DLayer ) );
326 QVERIFY( imageCheck( "lines_vertex_scalar_dataset_rotated_45", mMemory1DLayer, 45 ) );
327 }
328
test_1d_vertex_vector_dataset_rendering()329 void TestQgsMeshRenderer::test_1d_vertex_vector_dataset_rendering()
330 {
331 QgsMeshDatasetIndex ds( 1, 0 );
332 const QgsMeshDatasetGroupMetadata metadata = mMemory1DLayer->dataProvider()->datasetGroupMetadata( ds );
333 QVERIFY( metadata.name() == "VertexVectorDataset" );
334
335 QgsMeshRendererSettings rendererSettings = mMemory1DLayer->rendererSettings();
336 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
337 QgsMeshRendererVectorArrowSettings arrowSettings = settings.arrowSettings();
338 arrowSettings.setMinShaftLength( 15 );
339 settings.setArrowsSettings( arrowSettings );
340 rendererSettings.setVectorSettings( ds.group(), settings );
341 mMemory1DLayer->setRendererSettings( rendererSettings );
342 mMemory1DLayer->setStaticVectorDatasetIndex( ds );
343
344 QVERIFY( imageCheck( "lines_vertex_vector_dataset", mMemory1DLayer ) );
345 QVERIFY( imageCheck( "lines_vertex_vector_dataset_rotated_45", mMemory1DLayer, 45 ) );
346 }
347
test_1d_edge_scalar_dataset_rendering()348 void TestQgsMeshRenderer::test_1d_edge_scalar_dataset_rendering()
349 {
350 QgsMeshDatasetIndex ds( 2, 0 );
351 const QgsMeshDatasetGroupMetadata metadata = mMemory1DLayer->dataProvider()->datasetGroupMetadata( ds );
352 QVERIFY( metadata.name() == "EdgeScalarDataset" );
353
354 QgsMeshRendererSettings rendererSettings = mMemory1DLayer->rendererSettings();
355 QgsMeshRendererScalarSettings scalarSettings = rendererSettings.scalarSettings( 2 );
356 QgsInterpolatedLineWidth strokeWidth = scalarSettings.edgeStrokeWidth();
357 strokeWidth.setMaximumValue( 3 );
358 strokeWidth.setMaximumWidth( 2 );
359 strokeWidth.setIsVariableWidth( true );
360 scalarSettings.setEdgeStrokeWidth( strokeWidth );
361 rendererSettings.setScalarSettings( 2, scalarSettings );
362 mMemory1DLayer->setRendererSettings( rendererSettings );
363 mMemory1DLayer->setStaticScalarDatasetIndex( ds );
364
365 QVERIFY( imageCheck( "lines_edge_scalar_dataset", mMemory1DLayer ) );
366 QVERIFY( imageCheck( "lines_edge_scalar_dataset_rotated_45", mMemory1DLayer, 45 ) );
367 }
368
test_1d_edge_vector_dataset_rendering()369 void TestQgsMeshRenderer::test_1d_edge_vector_dataset_rendering()
370 {
371 QgsMeshDatasetIndex ds( 3, 0 );
372 const QgsMeshDatasetGroupMetadata metadata = mMemory1DLayer->dataProvider()->datasetGroupMetadata( ds );
373 QVERIFY( metadata.name() == "EdgeVectorDataset" );
374
375 QgsMeshRendererSettings rendererSettings = mMemory1DLayer->rendererSettings();
376 mMemory1DLayer->setRendererSettings( rendererSettings );
377 mMemory1DLayer->setStaticVectorDatasetIndex( ds );
378
379 QVERIFY( imageCheck( "lines_edge_vector_dataset", mMemory1DLayer ) );
380 QVERIFY( imageCheck( "lines_edge_vector_dataset_rotated_45", mMemory1DLayer, 45 ) );
381 }
382
test_vertex_scalar_dataset_rendering()383 void TestQgsMeshRenderer::test_vertex_scalar_dataset_rendering()
384 {
385 QgsMeshDatasetIndex ds( 0, 0 );
386 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
387 QVERIFY( metadata.name() == "VertexScalarDataset" );
388
389 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
390 mMemoryLayer->setRendererSettings( rendererSettings );
391 mMemoryLayer->setStaticScalarDatasetIndex( ds );
392
393 QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset", mMemoryLayer ) );
394 QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset_rotated_45", mMemoryLayer, 45.0 ) );
395 }
396
test_vertex_vector_dataset_rendering()397 void TestQgsMeshRenderer::test_vertex_vector_dataset_rendering()
398 {
399 QgsMeshDatasetIndex ds( 1, 0 );
400 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
401 QVERIFY( metadata.name() == "VertexVectorDataset" );
402
403 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
404 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
405 QgsMeshRendererVectorArrowSettings arrowSettings = settings.arrowSettings();
406 arrowSettings.setMinShaftLength( 15 );
407 settings.setArrowsSettings( arrowSettings );
408 rendererSettings.setVectorSettings( ds.group(), settings );
409 mMemoryLayer->setRendererSettings( rendererSettings );
410 mMemoryLayer->setStaticVectorDatasetIndex( ds );
411
412 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_dataset", mMemoryLayer ) );
413 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_dataset_rotated_45", mMemoryLayer, 45.0 ) );
414 }
415
test_vertex_vector_dataset_colorRamp_rendering()416 void TestQgsMeshRenderer::test_vertex_vector_dataset_colorRamp_rendering()
417 {
418 QgsMeshDatasetIndex ds( 1, 0 );
419 mMemoryLayer->setStaticVectorDatasetIndex( ds );
420 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
421 QVERIFY( metadata.name() == "VertexVectorDataset" );
422
423 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
424 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
425 QgsMeshRendererVectorArrowSettings arrowSettings = settings.arrowSettings();
426 arrowSettings.setMinShaftLength( 15 );
427 settings.setColoringMethod( QgsInterpolatedLineColor::ColorRamp );
428 settings.setArrowsSettings( arrowSettings );
429 rendererSettings.setVectorSettings( ds.group(), settings );
430 mMemoryLayer->setRendererSettings( rendererSettings );
431
432 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_dataset_colorRamp", mMemoryLayer ) );
433 }
434
test_face_scalar_dataset_rendering()435 void TestQgsMeshRenderer::test_face_scalar_dataset_rendering()
436 {
437 QgsMeshDatasetIndex ds( 2, 0 );
438 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
439 QVERIFY( metadata.name() == "FaceScalarDataset" );
440
441 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
442 mMemoryLayer->setRendererSettings( rendererSettings );
443 mMemoryLayer->setStaticScalarDatasetIndex( ds );
444
445 QVERIFY( imageCheck( "quad_and_triangle_face_scalar_dataset", mMemoryLayer ) );
446 QVERIFY( imageCheck( "quad_and_triangle_face_scalar_dataset_rotated_45", mMemoryLayer, 45.0 ) );
447 }
448
test_face_scalar_dataset_interpolated_neighbour_average_rendering()449 void TestQgsMeshRenderer::test_face_scalar_dataset_interpolated_neighbour_average_rendering()
450 {
451 QgsMeshDatasetIndex ds( 2, 0 );
452 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
453 QVERIFY( metadata.name() == "FaceScalarDataset" );
454
455 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
456 auto scalarRendererSettings = rendererSettings.scalarSettings( 2 );
457 scalarRendererSettings.setDataResamplingMethod( QgsMeshRendererScalarSettings::NeighbourAverage );
458 rendererSettings.setScalarSettings( 2, scalarRendererSettings );
459 mMemoryLayer->setRendererSettings( rendererSettings );
460 mMemoryLayer->setStaticScalarDatasetIndex( ds );
461
462 QVERIFY( imageCheck( "quad_and_triangle_face_scalar_interpolated_neighbour_average_dataset", mMemoryLayer ) );
463 }
464
465
test_face_vector_dataset_rendering()466 void TestQgsMeshRenderer::test_face_vector_dataset_rendering()
467 {
468 QgsMeshDatasetIndex ds( 3, 0 );
469 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
470 QVERIFY( metadata.name() == "FaceVectorDataset" );
471
472 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
473 mMemoryLayer->setRendererSettings( rendererSettings );
474 mMemoryLayer->setStaticVectorDatasetIndex( ds );
475
476 QVERIFY( imageCheck( "quad_and_triangle_face_vector_dataset", mMemoryLayer ) );
477 QVERIFY( imageCheck( "quad_and_triangle_face_vector_dataset_rotated_45", mMemoryLayer, 45.0 ) );
478 }
479
test_vertex_scalar_dataset_with_inactive_face_rendering()480 void TestQgsMeshRenderer::test_vertex_scalar_dataset_with_inactive_face_rendering()
481 {
482 QgsMeshDatasetIndex ds( 1, 1 );
483 const QgsMeshDatasetGroupMetadata metadata = mMdalLayer->dataProvider()->datasetGroupMetadata( ds );
484 QVERIFY( metadata.name() == "VertexScalarDatasetWithInactiveFace1" );
485
486 QgsMeshRendererSettings rendererSettings = mMdalLayer->rendererSettings();
487 mMdalLayer->setRendererSettings( rendererSettings );
488 mMdalLayer->setStaticScalarDatasetIndex( ds );
489
490 QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset_with_inactive_face", mMdalLayer ) );
491 }
492
test_face_vector_on_user_grid()493 void TestQgsMeshRenderer::test_face_vector_on_user_grid()
494 {
495 QgsMeshDatasetIndex ds( 3, 0 );
496 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
497 QVERIFY( metadata.name() == "FaceVectorDataset" );
498
499 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
500 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
501 settings.setOnUserDefinedGrid( true );
502 settings.setUserGridCellWidth( 30 );
503 settings.setUserGridCellHeight( 20 );
504 settings.setLineWidth( 0.8 );
505 settings.setSymbology( QgsMeshRendererVectorSettings::Arrows );
506 rendererSettings.setVectorSettings( ds.group(), settings );
507 mMemoryLayer->setRendererSettings( rendererSettings );
508 mMemoryLayer->setStaticVectorDatasetIndex( ds );
509
510 QVERIFY( imageCheck( "quad_and_triangle_face_vector_user_grid_dataset", mMemoryLayer ) );
511 QVERIFY( imageCheck( "quad_and_triangle_face_vector_user_grid_dataset_rotated_45", mMemoryLayer, 45.0 ) );
512 }
513
test_face_vector_on_user_grid_streamlines()514 void TestQgsMeshRenderer::test_face_vector_on_user_grid_streamlines()
515 {
516 QgsMeshDatasetIndex ds( 3, 0 );
517 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
518 QVERIFY( metadata.name() == "FaceVectorDataset" );
519
520 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
521 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
522 settings.setOnUserDefinedGrid( true );
523 settings.setUserGridCellWidth( 30 );
524 settings.setUserGridCellHeight( 20 );
525 settings.setLineWidth( 0.8 );
526 settings.setSymbology( QgsMeshRendererVectorSettings::Streamlines );
527 rendererSettings.setVectorSettings( ds.group(), settings );
528 mMemoryLayer->setRendererSettings( rendererSettings );
529 mMemoryLayer->setStaticVectorDatasetIndex( ds );
530
531 QVERIFY( imageCheck( "quad_and_triangle_face_vector_user_grid_dataset_streamlines", mMemoryLayer ) );
532 QVERIFY( imageCheck( "quad_and_triangle_face_vector_user_grid_dataset_streamlines_rotated_45", mMemoryLayer, 45.0 ) );
533 }
534
test_vertex_vector_on_user_grid()535 void TestQgsMeshRenderer::test_vertex_vector_on_user_grid()
536 {
537 QgsMeshDatasetIndex ds( 1, 0 );
538 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
539 QVERIFY( metadata.name() == "VertexVectorDataset" );
540
541 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
542 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
543 settings.setOnUserDefinedGrid( true );
544 settings.setUserGridCellWidth( 60 );
545 settings.setUserGridCellHeight( 40 );
546 settings.setLineWidth( 0.9 );
547 settings.setSymbology( QgsMeshRendererVectorSettings::Arrows );
548 settings.setColoringMethod( QgsInterpolatedLineColor::SingleColor );
549 rendererSettings.setVectorSettings( ds.group(), settings );
550 mMemoryLayer->setRendererSettings( rendererSettings );
551 mMemoryLayer->setStaticVectorDatasetIndex( ds );
552
553 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_user_grid_dataset", mMemoryLayer ) );
554 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_user_grid_dataset_rotated_45", mMemoryLayer, 45.0 ) );
555 }
556
test_vertex_vector_on_user_grid_streamlines()557 void TestQgsMeshRenderer::test_vertex_vector_on_user_grid_streamlines()
558 {
559 QgsMeshDatasetIndex ds( 1, 0 );
560 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
561 QVERIFY( metadata.name() == "VertexVectorDataset" );
562
563 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
564 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
565 settings.setOnUserDefinedGrid( true );
566 settings.setUserGridCellWidth( 60 );
567 settings.setUserGridCellHeight( 40 );
568 settings.setLineWidth( 0.9 );
569 settings.setColoringMethod( QgsInterpolatedLineColor::SingleColor );
570 settings.setSymbology( QgsMeshRendererVectorSettings::Streamlines );
571 rendererSettings.setVectorSettings( ds.group(), settings );
572 mMemoryLayer->setRendererSettings( rendererSettings );
573 mMemoryLayer->setStaticVectorDatasetIndex( ds );
574
575 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_user_grid_dataset_streamlines", mMemoryLayer ) );
576 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_user_grid_dataset_streamlines_rotated_45", mMemoryLayer, 45.0 ) );
577 }
578
test_vertex_vector_on_user_grid_streamlines_colorRamp()579 void TestQgsMeshRenderer::test_vertex_vector_on_user_grid_streamlines_colorRamp()
580 {
581 QgsMeshDatasetIndex ds( 1, 0 );
582 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
583 QVERIFY( metadata.name() == "VertexVectorDataset" );
584
585 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
586 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
587 settings.setOnUserDefinedGrid( true );
588 settings.setUserGridCellWidth( 60 );
589 settings.setUserGridCellHeight( 40 );
590 settings.setLineWidth( 0.9 );
591 settings.setColoringMethod( QgsInterpolatedLineColor::ColorRamp );
592 settings.setSymbology( QgsMeshRendererVectorSettings::Streamlines );
593 rendererSettings.setVectorSettings( ds.group(), settings );
594 mMemoryLayer->setRendererSettings( rendererSettings );
595 mMemoryLayer->setStaticVectorDatasetIndex( ds );
596
597 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_user_grid_dataset_streamlines_colorRamp", mMemoryLayer ) );
598 }
599
test_vertex_vector_traces()600 void TestQgsMeshRenderer::test_vertex_vector_traces()
601 {
602 QgsMeshDatasetIndex ds( 1, 0 );
603 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
604 QVERIFY( metadata.name() == "VertexVectorDataset" );
605
606 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
607 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
608 settings.setOnUserDefinedGrid( true );
609 settings.setUserGridCellWidth( 60 );
610 settings.setUserGridCellHeight( 40 );
611 settings.setLineWidth( 1 );
612 settings.setColoringMethod( QgsInterpolatedLineColor::SingleColor );
613
614 settings.setSymbology( QgsMeshRendererVectorSettings::Traces );
615 QgsMeshRendererVectorTracesSettings tracesSetting = settings.tracesSettings();
616 tracesSetting.setParticlesCount( -1 );
617 tracesSetting.setMaximumTailLength( 40 );
618 tracesSetting.setMaximumTailLengthUnit( QgsUnitTypes::RenderPixels );
619 settings.setTracesSettings( tracesSetting );
620 rendererSettings.setVectorSettings( ds.group(), settings );
621 mMemoryLayer->setRendererSettings( rendererSettings );
622 mMemoryLayer->setStaticVectorDatasetIndex( ds );
623
624 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_traces", mMemoryLayer ) );
625 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_traces_rotated_45", mMemoryLayer, 45.0 ) );
626 }
627
test_vertex_vector_traces_colorRamp()628 void TestQgsMeshRenderer::test_vertex_vector_traces_colorRamp()
629 {
630 QgsMeshDatasetIndex ds( 1, 0 );
631 const QgsMeshDatasetGroupMetadata metadata = mMemoryLayer->dataProvider()->datasetGroupMetadata( ds );
632 QVERIFY( metadata.name() == "VertexVectorDataset" );
633
634 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
635 QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
636 settings.setOnUserDefinedGrid( true );
637 settings.setUserGridCellWidth( 60 );
638 settings.setUserGridCellHeight( 40 );
639 settings.setLineWidth( 1 );
640 settings.setColoringMethod( QgsInterpolatedLineColor::ColorRamp );
641
642 settings.setSymbology( QgsMeshRendererVectorSettings::Traces );
643 QgsMeshRendererVectorTracesSettings tracesSetting = settings.tracesSettings();
644 tracesSetting.setParticlesCount( -1 );
645 tracesSetting.setMaximumTailLength( 40 );
646 tracesSetting.setMaximumTailLengthUnit( QgsUnitTypes::RenderPixels );
647 settings.setTracesSettings( tracesSetting );
648 rendererSettings.setVectorSettings( ds.group(), settings );
649 mMemoryLayer->setRendererSettings( rendererSettings );
650 mMemoryLayer->setStaticVectorDatasetIndex( ds );
651
652 QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_traces_colorRamp", mMemoryLayer ) );
653 }
654
test_signals()655 void TestQgsMeshRenderer::test_signals()
656 {
657 QSignalSpy spy1( mMemoryLayer, &QgsMapLayer::rendererChanged );
658 QSignalSpy spy2( mMemoryLayer->legend(), &QgsMapLayerLegend::itemsChanged );
659 QSignalSpy spy3( mMemoryLayer, &QgsMapLayer::legendChanged );
660
661 QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
662 mMemoryLayer->setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 1, 0 ) );
663 mMemoryLayer->setRendererSettings( rendererSettings );
664
665 QCOMPARE( spy1.count(), 1 );
666 QCOMPARE( spy2.count(), 1 );
667 QCOMPARE( spy3.count(), 1 );
668 }
669
test_stacked_3d_mesh_single_level_averaging()670 void TestQgsMeshRenderer::test_stacked_3d_mesh_single_level_averaging()
671 {
672 QgsMeshDatasetIndex ds( 1, 3 );
673 mMdal3DLayer->setStaticScalarDatasetIndex( ds );
674 QgsMeshRendererSettings rendererSettings = mMdal3DLayer->rendererSettings();
675 // we want to set active scalar dataset one defined on 3d mesh
676 QgsMeshDatasetGroupMetadata metadata = mMdal3DLayer->dataProvider()->datasetGroupMetadata( ds );
677 QVERIFY( metadata.name() == "temperature" );
678 QVERIFY( metadata.maximumVerticalLevelsCount() == 10 );
679 QgsMeshRendererScalarSettings scalarSettings = rendererSettings.scalarSettings( ds.group() );
680 scalarSettings.setDataResamplingMethod( QgsMeshRendererScalarSettings::None );
681 rendererSettings.setScalarSettings( ds.group(), scalarSettings );
682 // want to set active vector dataset one defined on 3d mesh
683 ds = QgsMeshDatasetIndex( 6, 3 );
684 metadata = mMdal3DLayer->dataProvider()->datasetGroupMetadata( ds );
685 QVERIFY( metadata.name() == "velocity" );
686 QVERIFY( metadata.maximumVerticalLevelsCount() == 10 );
687 QgsMeshRendererVectorSettings vectorSettings = rendererSettings.vectorSettings( ds.group() );
688 QgsMeshRendererVectorArrowSettings arrowSettings = vectorSettings.arrowSettings();
689 arrowSettings.setShaftLengthMethod( QgsMeshRendererVectorArrowSettings::ArrowScalingMethod::Scaled );
690 vectorSettings.setOnUserDefinedGrid( true );
691 vectorSettings.setUserGridCellWidth( 60 );
692 vectorSettings.setUserGridCellHeight( 10 );
693 arrowSettings.setScaleFactor( 35 );
694 vectorSettings.setLineWidth( 1 );
695 vectorSettings.setArrowsSettings( arrowSettings );
696 rendererSettings.setVectorSettings( ds.group(), vectorSettings );
697 // switch off mesh renderings
698 rendererSettings.setNativeMeshSettings( QgsMeshRendererMeshSettings() );
699 rendererSettings.setTriangularMeshSettings( QgsMeshRendererMeshSettings() );
700 std::unique_ptr<QgsMeshMultiLevelsAveragingMethod> method( new QgsMeshMultiLevelsAveragingMethod( 1, true ) );
701 rendererSettings.setAveragingMethod( method.get() );
702 mMdal3DLayer->setRendererSettings( rendererSettings );
703 mMdal3DLayer->setStaticVectorDatasetIndex( ds );
704
705 QVERIFY( imageCheck( "stacked_3d_mesh_single_level_averaging", mMdal3DLayer ) );
706 }
707
test_simplified_triangular_mesh_rendering()708 void TestQgsMeshRenderer::test_simplified_triangular_mesh_rendering()
709 {
710 QgsMeshSimplificationSettings simplificatationSettings;
711 simplificatationSettings.setEnabled( true );
712 simplificatationSettings.setMeshResolution( 10 );
713 simplificatationSettings.setReductionFactor( 2 );
714
715 QgsMeshRendererSettings rendererSettings = mMdal3DLayer->rendererSettings();
716 QgsMeshRendererMeshSettings meshSettings = rendererSettings.triangularMeshSettings();
717 meshSettings.setEnabled( true );
718 rendererSettings.setTriangularMeshSettings( meshSettings );
719 mMdal3DLayer->setRendererSettings( rendererSettings );
720
721 mMdal3DLayer->setMeshSimplificationSettings( simplificatationSettings );
722 QVERIFY( imageCheck( "simplified_triangular_mesh", mMdal3DLayer ) );
723 }
724
test_classified_values()725 void TestQgsMeshRenderer::test_classified_values()
726 {
727 QgsMeshLayer classifiedMesh( mDataDir + "/simplebox_clm.nc", "Mesh with classified values", "mdal" );
728 QVERIFY( classifiedMesh.isValid() );
729
730 QgsProject::instance()->addMapLayer( &classifiedMesh );
731 mMapSettings->setLayers( QList<QgsMapLayer *>() << &classifiedMesh );
732
733 classifiedMesh.temporalProperties()->setIsActive( false );
734 classifiedMesh.setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 3, 4 ) );
735
736 QVERIFY( imageCheck( "classified_values", &classifiedMesh ) );
737 }
738
739 QGSTEST_MAIN( TestQgsMeshRenderer )
740 #include "testqgsmeshlayerrenderer.moc"
741