Skip to content

Commit 3154102

Browse files
committed
[FEATURE] Scalar/vector data in mesh data providers
Reading and processing scalar (e.g. water depth) and vector (e.g. velocity) data from mesh data providers (e.g. MDAL)
1 parent bfbc64c commit 3154102

21 files changed

+966
-43
lines changed

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

+93-3
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,44 @@
1010

1111

1212

13-
typedef QgsPoint QgsMeshVertex; //xyz coords of vertex
14-
typedef QVector<int> QgsMeshFace; //list of vertex indexes
13+
typedef QgsPoint QgsMeshVertex;
14+
15+
typedef QVector<int> QgsMeshFace;
16+
17+
typedef QMap<QString, QString> QgsMeshDatasetMetadata;
18+
19+
class QgsMeshDatasetValue
20+
{
21+
%Docstring
22+
23+
QgsMeshDatasetValue is a vector or a scalar value on vertex or face of the mesh with
24+
support of nodata values
25+
26+
.. versionadded:: 3.2
27+
%End
28+
29+
%TypeHeaderCode
30+
#include "qgsmeshdataprovider.h"
31+
%End
32+
public:
33+
QgsMeshDatasetValue( double x,
34+
double y );
35+
QgsMeshDatasetValue( double scalar );
36+
QgsMeshDatasetValue( );
37+
38+
~QgsMeshDatasetValue();
39+
void setNodata( bool nodata = true );
40+
bool isNodata() const;
41+
bool isScalar() const;
42+
double scalar() const; //length for vectors, value for scalars
43+
void set( double scalar );
44+
void setX( double x );
45+
void setY( double y );
46+
double x() const;
47+
double y() const;
48+
bool operator==( const QgsMeshDatasetValue &other ) const;
49+
50+
};
1551

1652
class QgsMeshSource /Abstract/
1753
{
@@ -61,7 +97,61 @@ read on demand
6197
%End
6298
};
6399

64-
class QgsMeshDataProvider: QgsDataProvider, QgsMeshSource
100+
class QgsMeshDatasetSource /Abstract/
101+
{
102+
%Docstring
103+
Dataset is a collection of vector or scalar values on vertices or faces of the mesh
104+
105+
Base on the underlying data provider/format, whole dataset is either stored in memory or
106+
read on demand
107+
108+
.. versionadded:: 3.2
109+
%End
110+
111+
%TypeHeaderCode
112+
#include "qgsmeshdataprovider.h"
113+
%End
114+
public:
115+
virtual ~QgsMeshDatasetSource();
116+
117+
virtual bool addDataset( const QString &uri ) = 0;
118+
%Docstring
119+
Associate dataset with the mesh
120+
%End
121+
122+
virtual int datasetCount() const = 0;
123+
%Docstring
124+
Return number of datasets loaded
125+
%End
126+
127+
virtual bool datasetHasScalarData( int index ) const = 0;
128+
%Docstring
129+
Whether dataset has scalar data associated
130+
%End
131+
132+
virtual bool datasetIsOnVertices( int index ) const = 0;
133+
%Docstring
134+
Whether dataset is on vertices
135+
%End
136+
137+
virtual QgsMeshDatasetMetadata datasetMetadata( int index ) const = 0;
138+
%Docstring
139+
Return dataset metadata
140+
%End
141+
142+
virtual QgsMeshDatasetValue datasetValue( int datasetIndex, int valueIndex ) const = 0;
143+
%Docstring
144+
Return value associated with the index from the dataset
145+
%End
146+
147+
virtual bool datasetIsValid( int index ) const = 0;
148+
%Docstring
149+
Return whether dataset is valid
150+
%End
151+
};
152+
153+
154+
class QgsMeshDataProvider: QgsDataProvider, QgsMeshSource, QgsMeshDatasetSource
65155
{
66156
%Docstring
67157
Base class for providing data for :py:class:`QgsMeshLayer`

python/core/auto_generated/mesh/qgsmeshlayer.sip.in

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ E.g. to create mesh with one quad and one triangle
5252
);
5353
QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch layer", "memory_mesh");
5454

55+
Add datasets by adding them through data provider, :py:func:`QgsMeshDatasetSource.addDataset`
56+
5557
\subsection mdal MDAL data provider (mdal)
5658

5759
Accesses data using the MDAL drivers (https://github.com/lutraconsulting/MDAL). The url
@@ -133,6 +135,9 @@ Returns a line symbol used for rendering of triangular (derived) mesh.
133135
Toggle rendering of triangular (derived) mesh. Off by default
134136
%End
135137

138+
void setActiveScalarDataset( int index = -1 );
139+
void setActiveVectorDataset( int index = -1 );
140+
136141
private: // Private methods
137142
QgsMeshLayer( const QgsMeshLayer &rhs );
138143
};

src/core/mesh/qgsmeshdataprovider.cpp

+98
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
***************************************************************************/
1717

1818
#include "qgsmeshdataprovider.h"
19+
#include "qgis.h"
1920

2021
QgsMeshDataProvider::QgsMeshDataProvider( const QString &uri )
2122
: QgsDataProvider( uri )
@@ -38,3 +39,100 @@ QgsRectangle QgsMeshDataProvider::extent() const
3839
return rec;
3940

4041
}
42+
43+
QgsMeshDatasetValue::QgsMeshDatasetValue( double x, double y )
44+
{
45+
setX( x );
46+
setY( y );
47+
}
48+
49+
QgsMeshDatasetValue::QgsMeshDatasetValue( double scalar )
50+
{
51+
set( scalar );
52+
}
53+
54+
void QgsMeshDatasetValue::setNodata( bool nodata )
55+
{
56+
mIsNodata = nodata;
57+
}
58+
59+
bool QgsMeshDatasetValue::isNodata() const
60+
{return mIsNodata;}
61+
62+
bool QgsMeshDatasetValue::isScalar() const
63+
{
64+
return mIsScalar;
65+
}
66+
67+
double QgsMeshDatasetValue::scalar() const
68+
{
69+
if ( isNodata() )
70+
{
71+
return std::numeric_limits<double>::quiet_NaN();
72+
}
73+
74+
if ( isScalar() )
75+
{
76+
return mX;
77+
}
78+
else
79+
{
80+
return std::sqrt( ( mX ) * ( mX ) + ( mY ) * ( mY ) );
81+
}
82+
}
83+
84+
void QgsMeshDatasetValue::set( double scalar )
85+
{
86+
setX( scalar );
87+
mIsScalar = true;
88+
}
89+
90+
void QgsMeshDatasetValue::setX( double x )
91+
{
92+
mX = x;
93+
if ( std::isnan( x ) )
94+
{
95+
mIsNodata = true;
96+
}
97+
}
98+
99+
void QgsMeshDatasetValue::setY( double y )
100+
{
101+
mY = y;
102+
if ( std::isnan( y ) )
103+
{
104+
mIsScalar = true;
105+
}
106+
}
107+
108+
double QgsMeshDatasetValue::x() const
109+
{
110+
return mX;
111+
}
112+
113+
double QgsMeshDatasetValue::y() const
114+
{
115+
return mY;
116+
}
117+
118+
bool QgsMeshDatasetValue::operator==( const QgsMeshDatasetValue &other ) const
119+
{
120+
bool equal = true;
121+
if ( isNodata() )
122+
equal = other.isNodata();
123+
else
124+
{
125+
if ( isScalar() )
126+
{
127+
equal &= other.isScalar();
128+
equal &= qgsDoubleNear( other.x(), mX, 1E-8 );
129+
}
130+
else
131+
{
132+
equal &= !other.isScalar();
133+
equal &= qgsDoubleNear( other.x(), mX, 1E-8 );
134+
equal &= qgsDoubleNear( other.y(), mY, 1E-8 );
135+
}
136+
}
137+
return equal;
138+
}

src/core/mesh/qgsmeshdataprovider.h

+107-10
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,54 @@
2525

2626
#include <QVector>
2727
#include <QString>
28+
#include <QMap>
29+
#include <limits>
2830

29-
typedef QgsPoint QgsMeshVertex; //xyz coords of vertex
30-
typedef QVector<int> QgsMeshFace; //list of vertex indexes
31+
//! xyz coords of vertex
32+
typedef QgsPoint QgsMeshVertex;
33+
34+
//! List of vertex indexes
35+
typedef QVector<int> QgsMeshFace;
36+
37+
//! Dataset's metadata key:value map
38+
typedef QMap<QString, QString> QgsMeshDatasetMetadata;
39+
40+
/**
41+
* \ingroup core
42+
*
43+
* QgsMeshDatasetValue is a vector or a scalar value on vertex or face of the mesh with
44+
* support of nodata values
45+
*
46+
* \since QGIS 3.2
47+
*/
48+
class CORE_EXPORT QgsMeshDatasetValue
49+
{
50+
Q_GADGET
51+
52+
public:
53+
QgsMeshDatasetValue( double x,
54+
double y );
55+
QgsMeshDatasetValue( double scalar );
56+
QgsMeshDatasetValue( ) = default;
57+
58+
~QgsMeshDatasetValue() = default;
59+
void setNodata( bool nodata = true );
60+
bool isNodata() const;
61+
bool isScalar() const;
62+
double scalar() const; //length for vectors, value for scalars
63+
void set( double scalar );
64+
void setX( double x );
65+
void setY( double y ) ;
66+
double x() const;
67+
double y() const;
68+
bool operator==( const QgsMeshDatasetValue &other ) const;
69+
70+
private:
71+
double mX = std::numeric_limits<double>::quiet_NaN();
72+
double mY = std::numeric_limits<double>::quiet_NaN();
73+
bool mIsNodata = true;
74+
bool mIsScalar = true;
75+
};
3176

3277
/**
3378
* \ingroup core
@@ -73,14 +118,66 @@ class CORE_EXPORT QgsMeshSource SIP_ABSTRACT
73118

74119
/**
75120
* \ingroup core
76-
* Base class for providing data for QgsMeshLayer
77-
*
78-
* Responsible for reading native mesh data
79-
*
80-
* \see QgsMeshSource
81-
* \since QGIS 3.2
82-
*/
83-
class CORE_EXPORT QgsMeshDataProvider: public QgsDataProvider, public QgsMeshSource
121+
* Dataset is a collection of vector or scalar values on vertices or faces of the mesh
122+
*
123+
* Base on the underlying data provider/format, whole dataset is either stored in memory or
124+
* read on demand
125+
*
126+
* \since QGIS 3.2
127+
*/
128+
class CORE_EXPORT QgsMeshDatasetSource SIP_ABSTRACT
129+
{
130+
public:
131+
//! Dtor
132+
virtual ~QgsMeshDatasetSource() = default;
133+
134+
/**
135+
* \brief Associate dataset with the mesh
136+
*/
137+
virtual bool addDataset( const QString &uri ) = 0;
138+
139+
/**
140+
* \brief Return number of datasets loaded
141+
*/
142+
virtual int datasetCount() const = 0;
143+
144+
/**
145+
* \brief Whether dataset has scalar data associated
146+
*/
147+
virtual bool datasetHasScalarData( int index ) const = 0;
148+
149+
/**
150+
* \brief Whether dataset is on vertices
151+
*/
152+
virtual bool datasetIsOnVertices( int index ) const = 0;
153+
154+
/**
155+
* \brief Return dataset metadata
156+
*/
157+
virtual QgsMeshDatasetMetadata datasetMetadata( int index ) const = 0;
158+
159+
/**
160+
* \brief Return value associated with the index from the dataset
161+
*/
162+
virtual QgsMeshDatasetValue datasetValue( int datasetIndex, int valueIndex ) const = 0;
163+
164+
/**
165+
* \brief Return whether dataset is valid
166+
*/
167+
virtual bool datasetIsValid( int index ) const = 0;
168+
};
169+
170+
171+
/**
172+
* \ingroup core
173+
* Base class for providing data for QgsMeshLayer
174+
*
175+
* Responsible for reading native mesh data
176+
*
177+
* \see QgsMeshSource
178+
* \since QGIS 3.2
179+
*/
180+
class CORE_EXPORT QgsMeshDataProvider: public QgsDataProvider, public QgsMeshSource, public QgsMeshDatasetSource
84181
{
85182
Q_OBJECT
86183

src/core/mesh/qgsmeshlayer.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,20 @@ void QgsMeshLayer::toggleTriangularMeshRendering( bool toggle )
127127
triggerRepaint();
128128
}
129129

130+
void QgsMeshLayer::setActiveScalarDataset( int index )
131+
{
132+
Q_ASSERT( dataProvider()->datasetCount() > index );
133+
if ( dataProvider()->datasetHasScalarData( index ) )
134+
mActiveScalarDataset = index;
135+
}
136+
137+
void QgsMeshLayer::setActiveVectorDataset( int index )
138+
{
139+
Q_ASSERT( dataProvider()->datasetCount() > index );
140+
if ( !dataProvider()->datasetHasScalarData( index ) )
141+
mActiveVectorDataset = index;
142+
}
143+
130144
void QgsMeshLayer::fillNativeMesh()
131145
{
132146
Q_ASSERT( !mNativeMesh );

0 commit comments

Comments
 (0)