Skip to content

Commit 419ec1f

Browse files
PeterPetrikwonder-sk
authored andcommittedAug 20, 2018
[mesh] fix bug in rendering datasets with inactive faces
1 parent b39ee5a commit 419ec1f

15 files changed

+207
-39
lines changed
 

‎python/core/auto_generated/mesh/qgsmeshdataprovider.sip.in

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,18 @@ Returns dataset metadata
359359
Returns vector/scalar value associated with the index from the dataset
360360

361361
See QgsMeshDatasetMetadata.isVector() to check if the returned value is vector or scalar
362+
%End
363+
364+
virtual bool faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const = 0;
365+
%Docstring
366+
Returns whether the face is active for particular dataset
367+
368+
For example to represent the situation when F1 and F3 are flooded, but F2 is dry,
369+
some solvers store water depth on vertices V1-V8 (all non-zero values) and
370+
set active flag for F2 to false.
371+
V1 ---- V2 ---- V5-----V7
372+
| F1 | F2 | F3 |
373+
V3 ---- V4 ---- V6-----V8
362374
%End
363375
};
364376

‎src/core/mesh/qgsmeshdataprovider.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,18 @@ class CORE_EXPORT QgsMeshDatasetSourceInterface SIP_ABSTRACT
337337
* See QgsMeshDatasetMetadata::isVector() to check if the returned value is vector or scalar
338338
*/
339339
virtual QgsMeshDatasetValue datasetValue( QgsMeshDatasetIndex index, int valueIndex ) const = 0;
340+
341+
/**
342+
* \brief Returns whether the face is active for particular dataset
343+
*
344+
* For example to represent the situation when F1 and F3 are flooded, but F2 is dry,
345+
* some solvers store water depth on vertices V1-V8 (all non-zero values) and
346+
* set active flag for F2 to false.
347+
* V1 ---- V2 ---- V5-----V7
348+
* | F1 | F2 | F3 |
349+
* V3 ---- V4 ---- V6-----V8
350+
*/
351+
virtual bool faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const = 0;
340352
};
341353

342354

‎src/core/mesh/qgsmeshlayer.cpp

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -127,29 +127,36 @@ QgsMeshDatasetValue QgsMeshLayer::datasetValue( const QgsMeshDatasetIndex &index
127127
int faceIndex = mTriangularMesh->faceIndexForPoint( point ) ;
128128
if ( faceIndex >= 0 )
129129
{
130-
if ( dataProvider()->datasetGroupMetadata( index ).dataType() == QgsMeshDatasetGroupMetadata::DataOnFaces )
130+
int nativeFaceIndex = mTriangularMesh->trianglesToNativeFaces().at( faceIndex );
131+
if ( dataProvider()->faceIsActive( index, nativeFaceIndex ) )
131132
{
132-
int nativeFaceIndex = mTriangularMesh->trianglesToNativeFaces().at( faceIndex );
133-
return dataProvider()->datasetValue( index, nativeFaceIndex );
134-
}
135-
else
136-
{
137-
const QgsMeshFace &face = mTriangularMesh->triangles()[faceIndex];
138-
const int v1 = face[0], v2 = face[1], v3 = face[2];
139-
const QgsPoint p1 = mTriangularMesh->vertices()[v1], p2 = mTriangularMesh->vertices()[v2], p3 = mTriangularMesh->vertices()[v3];
140-
const QgsMeshDatasetValue val1 = dataProvider()->datasetValue( index, v1 );
141-
const QgsMeshDatasetValue val2 = dataProvider()->datasetValue( index, v2 );
142-
const QgsMeshDatasetValue val3 = dataProvider()->datasetValue( index, v3 );
143-
const double x = QgsMeshLayerInterpolator::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point );
144-
double y = std::numeric_limits<double>::quiet_NaN();
145-
bool isVector = dataProvider()->datasetGroupMetadata( index ).isVector();
146-
if ( isVector )
147-
y = QgsMeshLayerInterpolator::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point );
148-
149-
return QgsMeshDatasetValue( x, y );
133+
134+
if ( dataProvider()->datasetGroupMetadata( index ).dataType() == QgsMeshDatasetGroupMetadata::DataOnFaces )
135+
{
136+
int nativeFaceIndex = mTriangularMesh->trianglesToNativeFaces().at( faceIndex );
137+
value = dataProvider()->datasetValue( index, nativeFaceIndex );
138+
}
139+
else
140+
{
141+
const QgsMeshFace &face = mTriangularMesh->triangles()[faceIndex];
142+
const int v1 = face[0], v2 = face[1], v3 = face[2];
143+
const QgsPoint p1 = mTriangularMesh->vertices()[v1], p2 = mTriangularMesh->vertices()[v2], p3 = mTriangularMesh->vertices()[v3];
144+
const QgsMeshDatasetValue val1 = dataProvider()->datasetValue( index, v1 );
145+
const QgsMeshDatasetValue val2 = dataProvider()->datasetValue( index, v2 );
146+
const QgsMeshDatasetValue val3 = dataProvider()->datasetValue( index, v3 );
147+
const double x = QgsMeshLayerInterpolator::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point );
148+
double y = std::numeric_limits<double>::quiet_NaN();
149+
bool isVector = dataProvider()->datasetGroupMetadata( index ).isVector();
150+
if ( isVector )
151+
y = QgsMeshLayerInterpolator::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point );
152+
153+
value = QgsMeshDatasetValue( x, y );
154+
}
155+
150156
}
151157
}
152158
}
159+
153160
return value;
154161
}
155162

‎src/core/mesh/qgsmeshlayerinterpolator.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,14 @@ double interpolateFromFacesData( const QgsPointXY &p1, const QgsPointXY &p2, con
107107
return val;
108108
}
109109

110-
QgsMeshLayerInterpolator::QgsMeshLayerInterpolator(
111-
const QgsTriangularMesh &m,
112-
const QVector<double> &datasetValues,
113-
bool dataIsOnVertices,
114-
const QgsRenderContext &context,
115-
const QSize &size )
110+
QgsMeshLayerInterpolator::QgsMeshLayerInterpolator( const QgsTriangularMesh &m,
111+
const QVector<double> &datasetValues, const QVector<bool> &activeFaceFlagValues,
112+
bool dataIsOnVertices,
113+
const QgsRenderContext &context,
114+
const QSize &size )
116115
: mTriangularMesh( m ),
117116
mDatasetValues( datasetValues ),
117+
mActiveFaceFlagValues( activeFaceFlagValues ),
118118
mContext( context ),
119119
mDataOnVertices( dataIsOnVertices ),
120120
mOutputSize( size )
@@ -162,6 +162,11 @@ QgsRasterBlock *QgsMeshLayerInterpolator::block( int, const QgsRectangle &extent
162162
const int v1 = face[0], v2 = face[1], v3 = face[2];
163163
const QgsPoint p1 = vertices[v1], p2 = vertices[v2], p3 = vertices[v3];
164164

165+
const int nativeFaceIndex = mTriangularMesh.trianglesToNativeFaces()[i];
166+
const bool isActive = mActiveFaceFlagValues[nativeFaceIndex];
167+
if ( !isActive )
168+
continue;
169+
165170
QgsRectangle bbox;
166171
bbox.combineExtentWith( p1.x(), p1.y() );
167172
bbox.combineExtentWith( p2.x(), p2.y() );

‎src/core/mesh/qgsmeshlayerinterpolator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class QgsMeshLayerInterpolator : public QgsRasterInterface
4949
//! Ctor
5050
QgsMeshLayerInterpolator( const QgsTriangularMesh &m,
5151
const QVector<double> &datasetValues,
52+
const QVector<bool> &activeFaceFlagValues,
5253
bool dataIsOnVertices,
5354
const QgsRenderContext &context,
5455
const QSize &size );
@@ -78,6 +79,7 @@ class QgsMeshLayerInterpolator : public QgsRasterInterface
7879
private:
7980
const QgsTriangularMesh &mTriangularMesh;
8081
const QVector<double> &mDatasetValues;
82+
const QVector<bool> &mActiveFaceFlagValues;
8183
const QgsRenderContext &mContext;
8284
bool mDataOnVertices = true;
8385
QSize mOutputSize;

‎src/core/mesh/qgsmeshlayerrenderer.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
110110
mScalarDatasetValues[i] = v;
111111
}
112112

113+
// populate face active flag, always defined on faces
114+
mScalarActiveFaceFlagValues.resize( mNativeMesh.faces.count() );
115+
for ( int i = 0; i < mNativeMesh.faces.count(); ++i )
116+
{
117+
bool active = layer->dataProvider()->faceIsActive( datasetIndex, i );
118+
mScalarActiveFaceFlagValues[i] = active;
119+
}
120+
113121
QgsMeshLayerUtils::calculateMinimumMaximum( mScalarDatasetMinimum, mScalarDatasetMaximum, mScalarDatasetValues );
114122
}
115123
}
@@ -209,7 +217,8 @@ void QgsMeshLayerRenderer::renderScalarDataset()
209217
QgsColorRampShader *fcn = new QgsColorRampShader( scalarSettings.colorRampShader() );
210218
QgsRasterShader *sh = new QgsRasterShader();
211219
sh->setRasterShaderFunction( fcn ); // takes ownership of fcn
212-
QgsMeshLayerInterpolator interpolator( mTriangularMesh, mScalarDatasetValues, mScalarDataOnVertices, mContext, mOutputSize );
220+
QgsMeshLayerInterpolator interpolator( mTriangularMesh, mScalarDatasetValues, mScalarActiveFaceFlagValues,
221+
mScalarDataOnVertices, mContext, mOutputSize );
213222
QgsSingleBandPseudoColorRenderer renderer( &interpolator, 0, sh ); // takes ownership of sh
214223
renderer.setClassificationMin( scalarSettings.classificationMinimum() );
215224
renderer.setClassificationMax( scalarSettings.classificationMaximum() );

‎src/core/mesh/qgsmeshlayerrenderer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class QgsSymbol;
3434
#include "qgstriangularmesh.h"
3535
#include "qgsmeshlayer.h"
3636
#include "qgssymbol.h"
37+
#include "qgsmeshdataprovider.h"
3738

3839
///@cond PRIVATE
3940

@@ -69,7 +70,6 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer
6970
void renderVectorDataset();
7071
void copyScalarDatasetValues( QgsMeshLayer *layer );
7172
void copyVectorDatasetValues( QgsMeshLayer *layer );
72-
7373
void createMeshSymbol( std::unique_ptr<QgsSymbol> &symbol, const QgsMeshRendererMeshSettings &settings );
7474
void calculateOutputSize();
7575

@@ -85,6 +85,7 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer
8585

8686
// copy of the scalar dataset
8787
QVector<double> mScalarDatasetValues;
88+
QVector<bool> mScalarActiveFaceFlagValues;
8889
bool mScalarDataOnVertices = true;
8990
double mScalarDatasetMinimum = std::numeric_limits<double>::quiet_NaN();
9091
double mScalarDatasetMaximum = std::numeric_limits<double>::quiet_NaN();

‎src/core/mesh/qgsmeshmemorydataprovider.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,5 +407,12 @@ QgsMeshDatasetValue QgsMeshMemoryDataProvider::datasetValue( QgsMeshDatasetIndex
407407
}
408408
}
409409

410+
bool QgsMeshMemoryDataProvider::faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const
411+
{
412+
Q_UNUSED( index );
413+
Q_UNUSED( faceIndex );
414+
return true;
415+
}
416+
410417

411418
///@endcond

‎src/core/mesh/qgsmeshmemorydataprovider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class QgsMeshMemoryDataProvider: public QgsMeshDataProvider
128128
QgsMeshDatasetGroupMetadata datasetGroupMetadata( int groupIndex ) const override;
129129
QgsMeshDatasetMetadata datasetMetadata( QgsMeshDatasetIndex index ) const override;
130130
QgsMeshDatasetValue datasetValue( QgsMeshDatasetIndex index, int valueIndex ) const override;
131+
bool faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const override;
131132

132133
//! Returns the memory provider key
133134
static QString providerKey();

‎src/providers/mdal/qgsmdalprovider.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,19 @@ QgsMeshDatasetValue QgsMdalProvider::datasetValue( QgsMeshDatasetIndex index, in
216216
return val;
217217
}
218218

219+
bool QgsMdalProvider::faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const
220+
{
221+
DatasetGroupH group = MDAL_M_datasetGroup( mMeshH, index.group() );
222+
if ( !group )
223+
return false;
224+
225+
DatasetH dataset = MDAL_G_dataset( group, index.dataset() );
226+
if ( !dataset )
227+
return false;
228+
229+
return MDAL_D_active( dataset, faceIndex );
230+
}
231+
219232
/*----------------------------------------------------------------------------------------------*/
220233

221234
/**

‎src/providers/mdal/qgsmdalprovider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class QgsMdalProvider : public QgsMeshDataProvider
6464
QgsMeshDatasetGroupMetadata datasetGroupMetadata( int groupIndex ) const override;
6565
QgsMeshDatasetMetadata datasetMetadata( QgsMeshDatasetIndex index ) const override;
6666
QgsMeshDatasetValue datasetValue( QgsMeshDatasetIndex index, int valueIndex ) const override;
67+
bool faceIsActive( QgsMeshDatasetIndex index, int faceIndex ) const override;
6768

6869
private:
6970
MeshH mMeshH;

‎tests/src/core/testqgsmeshlayer.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class TestQgsMeshLayer : public QObject
5555
void test_read_vertex_vector_dataset();
5656
void test_read_face_scalar_dataset();
5757
void test_read_face_vector_dataset();
58+
void test_read_vertex_scalar_dataset_with_inactive_face();
5859
void test_extent();
5960
};
6061

@@ -178,6 +179,8 @@ void TestQgsMeshLayer::test_read_vertex_scalar_dataset()
178179
QCOMPARE( QgsMeshDatasetValue( 3.0 + i ), dp->datasetValue( ds, 2 ) );
179180
QCOMPARE( QgsMeshDatasetValue( 2.0 + i ), dp->datasetValue( ds, 3 ) );
180181
QCOMPARE( QgsMeshDatasetValue( 1.0 + i ), dp->datasetValue( ds, 4 ) );
182+
183+
QVERIFY( dp->faceIsActive( ds, 0 ) );
181184
}
182185
}
183186
}
@@ -216,6 +219,8 @@ void TestQgsMeshLayer::test_read_vertex_vector_dataset()
216219
QCOMPARE( QgsMeshDatasetValue( 3 + i, 2 + i ), dp->datasetValue( ds, 2 ) );
217220
QCOMPARE( QgsMeshDatasetValue( 2 + i, 2 + i ), dp->datasetValue( ds, 3 ) );
218221
QCOMPARE( QgsMeshDatasetValue( 1 + i, -2 + i ), dp->datasetValue( ds, 4 ) );
222+
223+
QVERIFY( dp->faceIsActive( ds, 0 ) );
219224
}
220225
}
221226
}
@@ -251,6 +256,8 @@ void TestQgsMeshLayer::test_read_face_scalar_dataset()
251256
// We have 2 values, since dp->faceCount() = 2
252257
QCOMPARE( QgsMeshDatasetValue( 1 + i ), dp->datasetValue( ds, 0 ) );
253258
QCOMPARE( QgsMeshDatasetValue( 2 + i ), dp->datasetValue( ds, 1 ) );
259+
260+
QVERIFY( dp->faceIsActive( ds, 0 ) );
254261
}
255262
}
256263
}
@@ -287,10 +294,47 @@ void TestQgsMeshLayer::test_read_face_vector_dataset()
287294
// We have 2 values, since dp->faceCount() = 2
288295
QCOMPARE( QgsMeshDatasetValue( 1 + i, 1 + i ), dp->datasetValue( ds, 0 ) );
289296
QCOMPARE( QgsMeshDatasetValue( 2 + i, 2 + i ), dp->datasetValue( ds, 1 ) );
297+
298+
QVERIFY( dp->faceIsActive( ds, 0 ) );
290299
}
291300
}
292301
}
293302

303+
void TestQgsMeshLayer::test_read_vertex_scalar_dataset_with_inactive_face()
304+
{
305+
QString uri( mDataDir + "/quad_and_triangle.2dm" );
306+
QgsMeshLayer layer( uri, "Triangle and Quad MDAL", "mdal" );
307+
layer.dataProvider()->addDataset( mDataDir + "/quad_and_triangle_vertex_scalar_with_inactive_face.dat" );
308+
QgsMeshDataProvider *dp = layer.dataProvider();
309+
QVERIFY( dp != nullptr );
310+
QVERIFY( dp->isValid() );
311+
QCOMPARE( 1, dp->datasetGroupCount() );
312+
313+
for ( int i = 0; i < 2 ; ++i )
314+
{
315+
QgsMeshDatasetIndex ds( 0, i );
316+
317+
const QgsMeshDatasetGroupMetadata meta = dp->datasetGroupMetadata( ds );
318+
QCOMPARE( meta.name(), QString( "VertexScalarDatasetWithInactiveFace1" ) );
319+
QVERIFY( meta.isScalar() );
320+
QVERIFY( meta.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices );
321+
322+
const QgsMeshDatasetMetadata dmeta = dp->datasetMetadata( ds );
323+
QVERIFY( qgsDoubleNear( dmeta.time(), i ) );
324+
QVERIFY( dmeta.isValid() );
325+
326+
// We have 5 values, since dp->vertexCount() = 5
327+
QCOMPARE( QgsMeshDatasetValue( 1.0 + i ), dp->datasetValue( ds, 0 ) );
328+
QCOMPARE( QgsMeshDatasetValue( 2.0 + i ), dp->datasetValue( ds, 1 ) );
329+
QCOMPARE( QgsMeshDatasetValue( 3.0 + i ), dp->datasetValue( ds, 2 ) );
330+
QCOMPARE( QgsMeshDatasetValue( 2.0 + i ), dp->datasetValue( ds, 3 ) );
331+
QCOMPARE( QgsMeshDatasetValue( 1.0 + i ), dp->datasetValue( ds, 4 ) );
332+
333+
// We have 2 faces
334+
QVERIFY( !dp->faceIsActive( ds, 0 ) );
335+
QVERIFY( dp->faceIsActive( ds, 1 ) );
336+
}
337+
}
294338

295339
void TestQgsMeshLayer::test_extent()
296340
{

0 commit comments

Comments
 (0)
Please sign in to comment.