From 419ec1f736f0a96d30a54f4861b634e6e00bcc05 Mon Sep 17 00:00:00 2001 From: Peter Petrik Date: Fri, 17 Aug 2018 14:05:27 +0200 Subject: [PATCH] [mesh] fix bug in rendering datasets with inactive faces --- .../mesh/qgsmeshdataprovider.sip.in | 12 ++++ src/core/mesh/qgsmeshdataprovider.h | 12 ++++ src/core/mesh/qgsmeshlayer.cpp | 43 ++++++++------ src/core/mesh/qgsmeshlayerinterpolator.cpp | 17 ++++-- src/core/mesh/qgsmeshlayerinterpolator.h | 2 + src/core/mesh/qgsmeshlayerrenderer.cpp | 11 +++- src/core/mesh/qgsmeshlayerrenderer.h | 3 +- src/core/mesh/qgsmeshmemorydataprovider.cpp | 7 +++ src/core/mesh/qgsmeshmemorydataprovider.h | 1 + src/providers/mdal/qgsmdalprovider.cpp | 13 +++++ src/providers/mdal/qgsmdalprovider.h | 1 + tests/src/core/testqgsmeshlayer.cpp | 44 +++++++++++++++ tests/src/core/testqgsmeshlayerrenderer.cpp | 53 ++++++++++++++---- ...rtex_scalar_dataset_with_inactive_face.png | Bin 0 -> 80307 bytes ...angle_vertex_scalar_with_inactive_face.dat | 25 +++++++++ 15 files changed, 206 insertions(+), 38 deletions(-) create mode 100644 tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_scalar_dataset_with_inactive_face/expected_quad_and_triangle_vertex_scalar_dataset_with_inactive_face.png create mode 100644 tests/testdata/mesh/quad_and_triangle_vertex_scalar_with_inactive_face.dat diff --git a/python/core/auto_generated/mesh/qgsmeshdataprovider.sip.in b/python/core/auto_generated/mesh/qgsmeshdataprovider.sip.in index bf741925740..d8b78c831b1 100644 --- a/python/core/auto_generated/mesh/qgsmeshdataprovider.sip.in +++ b/python/core/auto_generated/mesh/qgsmeshdataprovider.sip.in @@ -359,6 +359,18 @@ Returns dataset metadata Returns vector/scalar value associated with the index from the dataset See QgsMeshDatasetMetadata.isVector() to check if the returned value is vector or scalar +%End + + virtual bool faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const = 0; +%Docstring +Returns whether the face is active for particular dataset + +For example to represent the situation when F1 and F3 are flooded, but F2 is dry, +some solvers store water depth on vertices V1-V8 (all non-zero values) and +set active flag for F2 to false. +V1 ---- V2 ---- V5-----V7 +| F1 | F2 | F3 | +V3 ---- V4 ---- V6-----V8 %End }; diff --git a/src/core/mesh/qgsmeshdataprovider.h b/src/core/mesh/qgsmeshdataprovider.h index 1a362a44ab9..25b31b2c6a3 100644 --- a/src/core/mesh/qgsmeshdataprovider.h +++ b/src/core/mesh/qgsmeshdataprovider.h @@ -337,6 +337,18 @@ class CORE_EXPORT QgsMeshDatasetSourceInterface SIP_ABSTRACT * See QgsMeshDatasetMetadata::isVector() to check if the returned value is vector or scalar */ virtual QgsMeshDatasetValue datasetValue( QgsMeshDatasetIndex index, int valueIndex ) const = 0; + + /** + * \brief Returns whether the face is active for particular dataset + * + * For example to represent the situation when F1 and F3 are flooded, but F2 is dry, + * some solvers store water depth on vertices V1-V8 (all non-zero values) and + * set active flag for F2 to false. + * V1 ---- V2 ---- V5-----V7 + * | F1 | F2 | F3 | + * V3 ---- V4 ---- V6-----V8 + */ + virtual bool faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const = 0; }; diff --git a/src/core/mesh/qgsmeshlayer.cpp b/src/core/mesh/qgsmeshlayer.cpp index 17a1b16e880..73675c78ccc 100644 --- a/src/core/mesh/qgsmeshlayer.cpp +++ b/src/core/mesh/qgsmeshlayer.cpp @@ -127,29 +127,36 @@ QgsMeshDatasetValue QgsMeshLayer::datasetValue( const QgsMeshDatasetIndex &index int faceIndex = mTriangularMesh->faceIndexForPoint( point ) ; if ( faceIndex >= 0 ) { - if ( dataProvider()->datasetGroupMetadata( index ).dataType() == QgsMeshDatasetGroupMetadata::DataOnFaces ) + int nativeFaceIndex = mTriangularMesh->trianglesToNativeFaces().at( faceIndex ); + if ( dataProvider()->faceIsActive( index, nativeFaceIndex ) ) { - int nativeFaceIndex = mTriangularMesh->trianglesToNativeFaces().at( faceIndex ); - return dataProvider()->datasetValue( index, nativeFaceIndex ); - } - else - { - const QgsMeshFace &face = mTriangularMesh->triangles()[faceIndex]; - const int v1 = face[0], v2 = face[1], v3 = face[2]; - const QgsPoint p1 = mTriangularMesh->vertices()[v1], p2 = mTriangularMesh->vertices()[v2], p3 = mTriangularMesh->vertices()[v3]; - const QgsMeshDatasetValue val1 = dataProvider()->datasetValue( index, v1 ); - const QgsMeshDatasetValue val2 = dataProvider()->datasetValue( index, v2 ); - const QgsMeshDatasetValue val3 = dataProvider()->datasetValue( index, v3 ); - const double x = QgsMeshLayerInterpolator::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point ); - double y = std::numeric_limits::quiet_NaN(); - bool isVector = dataProvider()->datasetGroupMetadata( index ).isVector(); - if ( isVector ) - y = QgsMeshLayerInterpolator::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point ); - return QgsMeshDatasetValue( x, y ); + if ( dataProvider()->datasetGroupMetadata( index ).dataType() == QgsMeshDatasetGroupMetadata::DataOnFaces ) + { + int nativeFaceIndex = mTriangularMesh->trianglesToNativeFaces().at( faceIndex ); + value = dataProvider()->datasetValue( index, nativeFaceIndex ); + } + else + { + const QgsMeshFace &face = mTriangularMesh->triangles()[faceIndex]; + const int v1 = face[0], v2 = face[1], v3 = face[2]; + const QgsPoint p1 = mTriangularMesh->vertices()[v1], p2 = mTriangularMesh->vertices()[v2], p3 = mTriangularMesh->vertices()[v3]; + const QgsMeshDatasetValue val1 = dataProvider()->datasetValue( index, v1 ); + const QgsMeshDatasetValue val2 = dataProvider()->datasetValue( index, v2 ); + const QgsMeshDatasetValue val3 = dataProvider()->datasetValue( index, v3 ); + const double x = QgsMeshLayerInterpolator::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point ); + double y = std::numeric_limits::quiet_NaN(); + bool isVector = dataProvider()->datasetGroupMetadata( index ).isVector(); + if ( isVector ) + y = QgsMeshLayerInterpolator::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point ); + + value = QgsMeshDatasetValue( x, y ); + } + } } } + return value; } diff --git a/src/core/mesh/qgsmeshlayerinterpolator.cpp b/src/core/mesh/qgsmeshlayerinterpolator.cpp index 07148032414..ef17466a8e7 100644 --- a/src/core/mesh/qgsmeshlayerinterpolator.cpp +++ b/src/core/mesh/qgsmeshlayerinterpolator.cpp @@ -107,14 +107,14 @@ double interpolateFromFacesData( const QgsPointXY &p1, const QgsPointXY &p2, con return val; } -QgsMeshLayerInterpolator::QgsMeshLayerInterpolator( - const QgsTriangularMesh &m, - const QVector &datasetValues, - bool dataIsOnVertices, - const QgsRenderContext &context, - const QSize &size ) +QgsMeshLayerInterpolator::QgsMeshLayerInterpolator( const QgsTriangularMesh &m, + const QVector &datasetValues, const QVector &activeFaceFlagValues, + bool dataIsOnVertices, + const QgsRenderContext &context, + const QSize &size ) : mTriangularMesh( m ), mDatasetValues( datasetValues ), + mActiveFaceFlagValues( activeFaceFlagValues ), mContext( context ), mDataOnVertices( dataIsOnVertices ), mOutputSize( size ) @@ -162,6 +162,11 @@ QgsRasterBlock *QgsMeshLayerInterpolator::block( int, const QgsRectangle &extent const int v1 = face[0], v2 = face[1], v3 = face[2]; const QgsPoint p1 = vertices[v1], p2 = vertices[v2], p3 = vertices[v3]; + const int nativeFaceIndex = mTriangularMesh.trianglesToNativeFaces()[i]; + const bool isActive = mActiveFaceFlagValues[nativeFaceIndex]; + if ( !isActive ) + continue; + QgsRectangle bbox; bbox.combineExtentWith( p1.x(), p1.y() ); bbox.combineExtentWith( p2.x(), p2.y() ); diff --git a/src/core/mesh/qgsmeshlayerinterpolator.h b/src/core/mesh/qgsmeshlayerinterpolator.h index c2b5bcca7a2..83c5818af8e 100644 --- a/src/core/mesh/qgsmeshlayerinterpolator.h +++ b/src/core/mesh/qgsmeshlayerinterpolator.h @@ -49,6 +49,7 @@ class QgsMeshLayerInterpolator : public QgsRasterInterface //! Ctor QgsMeshLayerInterpolator( const QgsTriangularMesh &m, const QVector &datasetValues, + const QVector &activeFaceFlagValues, bool dataIsOnVertices, const QgsRenderContext &context, const QSize &size ); @@ -78,6 +79,7 @@ class QgsMeshLayerInterpolator : public QgsRasterInterface private: const QgsTriangularMesh &mTriangularMesh; const QVector &mDatasetValues; + const QVector &mActiveFaceFlagValues; const QgsRenderContext &mContext; bool mDataOnVertices = true; QSize mOutputSize; diff --git a/src/core/mesh/qgsmeshlayerrenderer.cpp b/src/core/mesh/qgsmeshlayerrenderer.cpp index 664b9401fb0..d4f2a9bd697 100644 --- a/src/core/mesh/qgsmeshlayerrenderer.cpp +++ b/src/core/mesh/qgsmeshlayerrenderer.cpp @@ -110,6 +110,14 @@ void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer ) mScalarDatasetValues[i] = v; } + // populate face active flag, always defined on faces + mScalarActiveFaceFlagValues.resize( mNativeMesh.faces.count() ); + for ( int i = 0; i < mNativeMesh.faces.count(); ++i ) + { + bool active = layer->dataProvider()->faceIsActive( datasetIndex, i ); + mScalarActiveFaceFlagValues[i] = active; + } + QgsMeshLayerUtils::calculateMinimumMaximum( mScalarDatasetMinimum, mScalarDatasetMaximum, mScalarDatasetValues ); } } @@ -209,7 +217,8 @@ void QgsMeshLayerRenderer::renderScalarDataset() QgsColorRampShader *fcn = new QgsColorRampShader( scalarSettings.colorRampShader() ); QgsRasterShader *sh = new QgsRasterShader(); sh->setRasterShaderFunction( fcn ); // takes ownership of fcn - QgsMeshLayerInterpolator interpolator( mTriangularMesh, mScalarDatasetValues, mScalarDataOnVertices, mContext, mOutputSize ); + QgsMeshLayerInterpolator interpolator( mTriangularMesh, mScalarDatasetValues, mScalarActiveFaceFlagValues, + mScalarDataOnVertices, mContext, mOutputSize ); QgsSingleBandPseudoColorRenderer renderer( &interpolator, 0, sh ); // takes ownership of sh renderer.setClassificationMin( scalarSettings.classificationMinimum() ); renderer.setClassificationMax( scalarSettings.classificationMaximum() ); diff --git a/src/core/mesh/qgsmeshlayerrenderer.h b/src/core/mesh/qgsmeshlayerrenderer.h index aeef67c9e6f..98cda456096 100644 --- a/src/core/mesh/qgsmeshlayerrenderer.h +++ b/src/core/mesh/qgsmeshlayerrenderer.h @@ -34,6 +34,7 @@ class QgsSymbol; #include "qgstriangularmesh.h" #include "qgsmeshlayer.h" #include "qgssymbol.h" +#include "qgsmeshdataprovider.h" ///@cond PRIVATE @@ -69,7 +70,6 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer void renderVectorDataset(); void copyScalarDatasetValues( QgsMeshLayer *layer ); void copyVectorDatasetValues( QgsMeshLayer *layer ); - void createMeshSymbol( std::unique_ptr &symbol, const QgsMeshRendererMeshSettings &settings ); void calculateOutputSize(); @@ -85,6 +85,7 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer // copy of the scalar dataset QVector mScalarDatasetValues; + QVector mScalarActiveFaceFlagValues; bool mScalarDataOnVertices = true; double mScalarDatasetMinimum = std::numeric_limits::quiet_NaN(); double mScalarDatasetMaximum = std::numeric_limits::quiet_NaN(); diff --git a/src/core/mesh/qgsmeshmemorydataprovider.cpp b/src/core/mesh/qgsmeshmemorydataprovider.cpp index 7c2a12da03f..bd6894ceb0a 100644 --- a/src/core/mesh/qgsmeshmemorydataprovider.cpp +++ b/src/core/mesh/qgsmeshmemorydataprovider.cpp @@ -407,5 +407,12 @@ QgsMeshDatasetValue QgsMeshMemoryDataProvider::datasetValue( QgsMeshDatasetIndex } } +bool QgsMeshMemoryDataProvider::faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const +{ + Q_UNUSED( index ); + Q_UNUSED( faceIndex ); + return true; +} + ///@endcond diff --git a/src/core/mesh/qgsmeshmemorydataprovider.h b/src/core/mesh/qgsmeshmemorydataprovider.h index 2881ed0650c..4864c576d37 100644 --- a/src/core/mesh/qgsmeshmemorydataprovider.h +++ b/src/core/mesh/qgsmeshmemorydataprovider.h @@ -128,6 +128,7 @@ class QgsMeshMemoryDataProvider: public QgsMeshDataProvider QgsMeshDatasetGroupMetadata datasetGroupMetadata( int groupIndex ) const override; QgsMeshDatasetMetadata datasetMetadata( QgsMeshDatasetIndex index ) const override; QgsMeshDatasetValue datasetValue( QgsMeshDatasetIndex index, int valueIndex ) const override; + bool faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const override; //! Returns the memory provider key static QString providerKey(); diff --git a/src/providers/mdal/qgsmdalprovider.cpp b/src/providers/mdal/qgsmdalprovider.cpp index 601e3ea1d45..c668922352f 100644 --- a/src/providers/mdal/qgsmdalprovider.cpp +++ b/src/providers/mdal/qgsmdalprovider.cpp @@ -216,6 +216,19 @@ QgsMeshDatasetValue QgsMdalProvider::datasetValue( QgsMeshDatasetIndex index, in return val; } +bool QgsMdalProvider::faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const +{ + DatasetGroupH group = MDAL_M_datasetGroup( mMeshH, index.group() ); + if ( !group ) + return false; + + DatasetH dataset = MDAL_G_dataset( group, index.dataset() ); + if ( !dataset ) + return false; + + return MDAL_D_active( dataset, faceIndex ); +} + /*----------------------------------------------------------------------------------------------*/ /** diff --git a/src/providers/mdal/qgsmdalprovider.h b/src/providers/mdal/qgsmdalprovider.h index a5a29f7aef7..b119b1d38e5 100644 --- a/src/providers/mdal/qgsmdalprovider.h +++ b/src/providers/mdal/qgsmdalprovider.h @@ -64,6 +64,7 @@ class QgsMdalProvider : public QgsMeshDataProvider QgsMeshDatasetGroupMetadata datasetGroupMetadata( int groupIndex ) const override; QgsMeshDatasetMetadata datasetMetadata( QgsMeshDatasetIndex index ) const override; QgsMeshDatasetValue datasetValue( QgsMeshDatasetIndex index, int valueIndex ) const override; + bool faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const override; private: MeshH mMeshH; diff --git a/tests/src/core/testqgsmeshlayer.cpp b/tests/src/core/testqgsmeshlayer.cpp index 504a5c67f3b..491f012e02b 100644 --- a/tests/src/core/testqgsmeshlayer.cpp +++ b/tests/src/core/testqgsmeshlayer.cpp @@ -55,6 +55,7 @@ class TestQgsMeshLayer : public QObject void test_read_vertex_vector_dataset(); void test_read_face_scalar_dataset(); void test_read_face_vector_dataset(); + void test_read_vertex_scalar_dataset_with_inactive_face(); void test_extent(); }; @@ -178,6 +179,8 @@ void TestQgsMeshLayer::test_read_vertex_scalar_dataset() QCOMPARE( QgsMeshDatasetValue( 3.0 + i ), dp->datasetValue( ds, 2 ) ); QCOMPARE( QgsMeshDatasetValue( 2.0 + i ), dp->datasetValue( ds, 3 ) ); QCOMPARE( QgsMeshDatasetValue( 1.0 + i ), dp->datasetValue( ds, 4 ) ); + + QVERIFY( dp->faceIsActive( ds, 0 ) ); } } } @@ -216,6 +219,8 @@ void TestQgsMeshLayer::test_read_vertex_vector_dataset() QCOMPARE( QgsMeshDatasetValue( 3 + i, 2 + i ), dp->datasetValue( ds, 2 ) ); QCOMPARE( QgsMeshDatasetValue( 2 + i, 2 + i ), dp->datasetValue( ds, 3 ) ); QCOMPARE( QgsMeshDatasetValue( 1 + i, -2 + i ), dp->datasetValue( ds, 4 ) ); + + QVERIFY( dp->faceIsActive( ds, 0 ) ); } } } @@ -251,6 +256,8 @@ void TestQgsMeshLayer::test_read_face_scalar_dataset() // We have 2 values, since dp->faceCount() = 2 QCOMPARE( QgsMeshDatasetValue( 1 + i ), dp->datasetValue( ds, 0 ) ); QCOMPARE( QgsMeshDatasetValue( 2 + i ), dp->datasetValue( ds, 1 ) ); + + QVERIFY( dp->faceIsActive( ds, 0 ) ); } } } @@ -287,10 +294,47 @@ void TestQgsMeshLayer::test_read_face_vector_dataset() // We have 2 values, since dp->faceCount() = 2 QCOMPARE( QgsMeshDatasetValue( 1 + i, 1 + i ), dp->datasetValue( ds, 0 ) ); QCOMPARE( QgsMeshDatasetValue( 2 + i, 2 + i ), dp->datasetValue( ds, 1 ) ); + + QVERIFY( dp->faceIsActive( ds, 0 ) ); } } } +void TestQgsMeshLayer::test_read_vertex_scalar_dataset_with_inactive_face() +{ + QString uri( mDataDir + "/quad_and_triangle.2dm" ); + QgsMeshLayer layer( uri, "Triangle and Quad MDAL", "mdal" ); + layer.dataProvider()->addDataset( mDataDir + "/quad_and_triangle_vertex_scalar_with_inactive_face.dat" ); + QgsMeshDataProvider *dp = layer.dataProvider(); + QVERIFY( dp != nullptr ); + QVERIFY( dp->isValid() ); + QCOMPARE( 1, dp->datasetGroupCount() ); + + for ( int i = 0; i < 2 ; ++i ) + { + QgsMeshDatasetIndex ds( 0, i ); + + const QgsMeshDatasetGroupMetadata meta = dp->datasetGroupMetadata( ds ); + QCOMPARE( meta.name(), QString( "VertexScalarDatasetWithInactiveFace1" ) ); + QVERIFY( meta.isScalar() ); + QVERIFY( meta.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices ); + + const QgsMeshDatasetMetadata dmeta = dp->datasetMetadata( ds ); + QVERIFY( qgsDoubleNear( dmeta.time(), i ) ); + QVERIFY( dmeta.isValid() ); + + // We have 5 values, since dp->vertexCount() = 5 + QCOMPARE( QgsMeshDatasetValue( 1.0 + i ), dp->datasetValue( ds, 0 ) ); + QCOMPARE( QgsMeshDatasetValue( 2.0 + i ), dp->datasetValue( ds, 1 ) ); + QCOMPARE( QgsMeshDatasetValue( 3.0 + i ), dp->datasetValue( ds, 2 ) ); + QCOMPARE( QgsMeshDatasetValue( 2.0 + i ), dp->datasetValue( ds, 3 ) ); + QCOMPARE( QgsMeshDatasetValue( 1.0 + i ), dp->datasetValue( ds, 4 ) ); + + // We have 2 faces + QVERIFY( !dp->faceIsActive( ds, 0 ) ); + QVERIFY( dp->faceIsActive( ds, 1 ) ); + } +} void TestQgsMeshLayer::test_extent() { diff --git a/tests/src/core/testqgsmeshlayerrenderer.cpp b/tests/src/core/testqgsmeshlayerrenderer.cpp index 4c9cdebc0a0..ad4c7a125eb 100644 --- a/tests/src/core/testqgsmeshlayerrenderer.cpp +++ b/tests/src/core/testqgsmeshlayerrenderer.cpp @@ -52,6 +52,7 @@ class TestQgsMeshRenderer : public QObject private: QString mDataDir; QgsMeshLayer *mMemoryLayer = nullptr; + QgsMeshLayer *mMdalLayer = nullptr; QgsMapSettings *mMapSettings = nullptr; QString mReport; @@ -60,7 +61,7 @@ class TestQgsMeshRenderer : public QObject void cleanupTestCase();// will be called after the last testfunction was executed. void init(); // will be called before each testfunction is executed. void cleanup() {} // will be called after every testfunction. - bool imageCheck( const QString &testType ); + bool imageCheck( const QString &testType, QgsMeshLayer *layer ); QString readFile( const QString &fname ) const; @@ -71,6 +72,7 @@ class TestQgsMeshRenderer : public QObject void test_vertex_vector_dataset_rendering(); void test_face_scalar_dataset_rendering(); void test_face_vector_dataset_rendering(); + void test_vertex_scalar_dataset_with_inactive_face_rendering(); void test_signals(); }; @@ -83,6 +85,13 @@ void TestQgsMeshRenderer::init() rendererSettings.setNativeMeshSettings( QgsMeshRendererMeshSettings() ); rendererSettings.setTriangularMeshSettings( QgsMeshRendererMeshSettings() ); mMemoryLayer->setRendererSettings( rendererSettings ); + + rendererSettings = mMdalLayer->rendererSettings(); + rendererSettings.setActiveScalarDataset(); + rendererSettings.setActiveVectorDataset(); + rendererSettings.setNativeMeshSettings( QgsMeshRendererMeshSettings() ); + rendererSettings.setTriangularMeshSettings( QgsMeshRendererMeshSettings() ); + mMdalLayer->setRendererSettings( rendererSettings ); } void TestQgsMeshRenderer::initTestCase() @@ -98,6 +107,11 @@ void TestQgsMeshRenderer::initTestCase() mMapSettings = new QgsMapSettings(); + // Mdal layer + mMdalLayer = new QgsMeshLayer( mDataDir + "/quad_and_triangle.2dm", "Triangle and Quad Mdal", "mdal" ); + mMdalLayer->dataProvider()->addDataset( mDataDir + "/quad_and_triangle_vertex_scalar_with_inactive_face.dat" ); + QVERIFY( mMdalLayer->isValid() ); + // Memory layer mMemoryLayer = new QgsMeshLayer( readFile( "/quad_and_triangle.txt" ), "Triangle and Quad Memory", "mesh_memory" ); mMemoryLayer->dataProvider()->addDataset( readFile( "/quad_and_triangle_vertex_scalar.txt" ) ); @@ -105,10 +119,12 @@ void TestQgsMeshRenderer::initTestCase() mMemoryLayer->dataProvider()->addDataset( readFile( "/quad_and_triangle_face_scalar.txt" ) ); mMemoryLayer->dataProvider()->addDataset( readFile( "/quad_and_triangle_face_vector.txt" ) ); QVERIFY( mMemoryLayer->isValid() ); + + // Add layers QgsProject::instance()->addMapLayers( - QList() << mMemoryLayer ); + QList() << mMemoryLayer << mMdalLayer ); mMapSettings->setLayers( - QList() << mMemoryLayer ); + QList() << mMemoryLayer << mMdalLayer ); // here we check that datasets automatically get our default color ramp applied ("Plasma") QgsMeshDatasetIndex ds( 0, 0 ); @@ -143,11 +159,11 @@ QString TestQgsMeshRenderer::readFile( const QString &fname ) const return uri; } -bool TestQgsMeshRenderer::imageCheck( const QString &testType ) +bool TestQgsMeshRenderer::imageCheck( const QString &testType, QgsMeshLayer *layer ) { mReport += "

" + testType + "

\n"; - mMapSettings->setExtent( mMemoryLayer->extent() ); - mMapSettings->setDestinationCrs( mMemoryLayer->crs() ); + mMapSettings->setExtent( layer->extent() ); + mMapSettings->setDestinationCrs( layer->crs() ); mMapSettings->setOutputDpi( 96 ); QgsRenderChecker myChecker; myChecker.setControlPathPrefix( QStringLiteral( "mesh" ) ); @@ -167,7 +183,7 @@ void TestQgsMeshRenderer::test_native_mesh_rendering() settings.setLineWidth( 1. ); rendererSettings.setNativeMeshSettings( settings ); mMemoryLayer->setRendererSettings( rendererSettings ); - QVERIFY( imageCheck( "quad_and_triangle_native_mesh" ) ); + QVERIFY( imageCheck( "quad_and_triangle_native_mesh", mMemoryLayer ) ); } void TestQgsMeshRenderer::test_triangular_mesh_rendering() @@ -179,7 +195,7 @@ void TestQgsMeshRenderer::test_triangular_mesh_rendering() settings.setLineWidth( 0.26 ); rendererSettings.setTriangularMeshSettings( settings ); mMemoryLayer->setRendererSettings( rendererSettings ); - QVERIFY( imageCheck( "quad_and_triangle_triangular_mesh" ) ); + QVERIFY( imageCheck( "quad_and_triangle_triangular_mesh", mMemoryLayer ) ); } void TestQgsMeshRenderer::test_vertex_scalar_dataset_rendering() @@ -192,7 +208,7 @@ void TestQgsMeshRenderer::test_vertex_scalar_dataset_rendering() rendererSettings.setActiveScalarDataset( ds ); mMemoryLayer->setRendererSettings( rendererSettings ); - QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset" ) ); + QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset", mMemoryLayer ) ); } void TestQgsMeshRenderer::test_vertex_vector_dataset_rendering() @@ -208,7 +224,7 @@ void TestQgsMeshRenderer::test_vertex_vector_dataset_rendering() rendererSettings.setActiveVectorDataset( ds ); mMemoryLayer->setRendererSettings( rendererSettings ); - QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_dataset" ) ); + QVERIFY( imageCheck( "quad_and_triangle_vertex_vector_dataset", mMemoryLayer ) ); } void TestQgsMeshRenderer::test_face_scalar_dataset_rendering() @@ -221,7 +237,7 @@ void TestQgsMeshRenderer::test_face_scalar_dataset_rendering() rendererSettings.setActiveScalarDataset( ds ); mMemoryLayer->setRendererSettings( rendererSettings ); - QVERIFY( imageCheck( "quad_and_triangle_face_scalar_dataset" ) ); + QVERIFY( imageCheck( "quad_and_triangle_face_scalar_dataset", mMemoryLayer ) ); } void TestQgsMeshRenderer::test_face_vector_dataset_rendering() @@ -234,7 +250,20 @@ void TestQgsMeshRenderer::test_face_vector_dataset_rendering() rendererSettings.setActiveVectorDataset( ds ); mMemoryLayer->setRendererSettings( rendererSettings ); - QVERIFY( imageCheck( "quad_and_triangle_face_vector_dataset" ) ); + QVERIFY( imageCheck( "quad_and_triangle_face_vector_dataset", mMemoryLayer ) ); +} + +void TestQgsMeshRenderer::test_vertex_scalar_dataset_with_inactive_face_rendering() +{ + QgsMeshDatasetIndex ds( 0, 1 ); + const QgsMeshDatasetGroupMetadata metadata = mMdalLayer->dataProvider()->datasetGroupMetadata( ds ); + QVERIFY( metadata.name() == "VertexScalarDatasetWithInactiveFace1" ); + + QgsMeshRendererSettings rendererSettings = mMdalLayer->rendererSettings(); + rendererSettings.setActiveScalarDataset( ds ); + mMdalLayer->setRendererSettings( rendererSettings ); + + QVERIFY( imageCheck( "quad_and_triangle_vertex_scalar_dataset_with_inactive_face", mMdalLayer ) ); } void TestQgsMeshRenderer::test_signals() diff --git a/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_scalar_dataset_with_inactive_face/expected_quad_and_triangle_vertex_scalar_dataset_with_inactive_face.png b/tests/testdata/control_images/mesh/expected_quad_and_triangle_vertex_scalar_dataset_with_inactive_face/expected_quad_and_triangle_vertex_scalar_dataset_with_inactive_face.png new file mode 100644 index 0000000000000000000000000000000000000000..1503cbf78ba7254ed95d2e0eb89ac24817f8584b GIT binary patch literal 80307 zcmeI4S!`5Q7{_nX5TK$&j3V(tA54s*;*Q`}9Hiq?5KEVt>8$tOsEN@8AABp(#6%x_ zR)cXtDk_L;UE)Fn6crUUiaW+7;1V$!jg1DJNj0|9d#86f%Xhx>pQN;N?>XP{`_3;- z;10Jf?^-%@#@rc>(a{Z?Av3)27z{+;Zz+d;Qz=8#?<}IZpfR##ftj_nJA5 zbF7oibada;=44k754PR;*~o$VLcE9&=)NcKY^bdxQVq(O0tEC3th_fzuP93^f*?c( z-*aC-(aP*93xW`ychCKOgsZcoGzda`&b<#n5}hN0AUf$s%-y@TH{wbx6HNeuh$bp2 zUf+W~k|HB)D*_Ot6&+&t`qn`b)gyr*s)?t}*FUr}Wdv-GLjZ!rp+#hE|3lqGD&b#- zVS+5WeNX3q&jRotPSg%_>mf{3R%zB5CQF)D`R&a;d=f) z2%?w2lt4Lk`+(gKGdX$eNyzw7vgTPZvX zF!0pn5vs+KFanSzj0~ge#iuW0)Q#F!Ac$Jt+OidgAxRSW5F`mTL-!P)z0}ak^_2}l z^s(2Hx%6CCOI}lxLJ(6Ym!j^{^YzaX;1!7g1c`)+-=fkBkR-}fAxIQTOxKiOT*|aF zacw~maV(9DRDS6aBkNXGGz3vansA=-%a9~&JP;&|jAhp=uPkZmc*pnGWGFlf&{USj zw~$36d}^sHo9lMqHI4uT8HWRJDz9D)2xAC9kTEdu<0ygZmc>BvF98UGqYy}-x)qW% zz(A0|fr+FR$7?)+;1j$P881<0-*9)vNZ=TEb^+78;* zh@=KVMAEbOnck-45f|z(JiPh}Bw~$yx z;>v*_;#gW8$$kG^miN;m=US3QzIknoupcc-{-|0-La z1#o|xr+hw;MLBXLOhdr^U9BV#B+az2R|^664|S425G^A{(zFEJKh;PALDEhN`?V2p zN90QaL9~q*iA4}_|B@>S1Q9VM#L!Bh_V-EB@c1%Xm~d`Tck3!u2gk3i{=c#=R6erEt3O+uh}X!OtaLXb&d;xzLqoS*JAdu<*EP0hmvm(wTU@^R9~)h}L;wH) literal 0 HcmV?d00001 diff --git a/tests/testdata/mesh/quad_and_triangle_vertex_scalar_with_inactive_face.dat b/tests/testdata/mesh/quad_and_triangle_vertex_scalar_with_inactive_face.dat new file mode 100644 index 00000000000..0d2572663cd --- /dev/null +++ b/tests/testdata/mesh/quad_and_triangle_vertex_scalar_with_inactive_face.dat @@ -0,0 +1,25 @@ +DATASET +OBJTYPE "mesh2d" +RT_JULIAN 2433282.500000 +BEGSCL +ND 5 +NC 2 +NAME "VertexScalarDatasetWithInactiveFace1" +TIMEUNITS se +TS 1 0.000000 +0 +1 +1 +2 +3 +2 +1 +TS 1 3600.000000 +0 +1 +2 +3 +4 +3 +2 +ENDDS