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