Skip to content

Commit

Permalink
[FEATURE] Scalar/vector data in mesh data providers
Browse files Browse the repository at this point in the history
Reading and processing scalar (e.g. water depth) and vector (e.g.
velocity) data from mesh data providers (e.g. MDAL)
  • Loading branch information
PeterPetrik committed May 16, 2018
1 parent bfbc64c commit 3154102
Show file tree
Hide file tree
Showing 21 changed files with 966 additions and 43 deletions.
96 changes: 93 additions & 3 deletions python/core/auto_generated/mesh/qgsmeshdataprovider.sip.in
Expand Up @@ -10,8 +10,44 @@



typedef QgsPoint QgsMeshVertex; //xyz coords of vertex
typedef QVector<int> QgsMeshFace; //list of vertex indexes
typedef QgsPoint QgsMeshVertex;

typedef QVector<int> QgsMeshFace;

typedef QMap<QString, QString> QgsMeshDatasetMetadata;

class QgsMeshDatasetValue
{
%Docstring

QgsMeshDatasetValue is a vector or a scalar value on vertex or face of the mesh with
support of nodata values

.. versionadded:: 3.2
%End

%TypeHeaderCode
#include "qgsmeshdataprovider.h"
%End
public:
QgsMeshDatasetValue( double x,
double y );
QgsMeshDatasetValue( double scalar );
QgsMeshDatasetValue( );

~QgsMeshDatasetValue();
void setNodata( bool nodata = true );
bool isNodata() const;
bool isScalar() const;
double scalar() const; //length for vectors, value for scalars
void set( double scalar );
void setX( double x );
void setY( double y );
double x() const;
double y() const;
bool operator==( const QgsMeshDatasetValue &other ) const;

};

class QgsMeshSource /Abstract/
{
Expand Down Expand Up @@ -61,7 +97,61 @@ read on demand
%End
};

class QgsMeshDataProvider: QgsDataProvider, QgsMeshSource
class QgsMeshDatasetSource /Abstract/
{
%Docstring
Dataset is a collection of vector or scalar values on vertices or faces of the mesh

Base on the underlying data provider/format, whole dataset is either stored in memory or
read on demand

.. versionadded:: 3.2
%End

%TypeHeaderCode
#include "qgsmeshdataprovider.h"
%End
public:
virtual ~QgsMeshDatasetSource();

virtual bool addDataset( const QString &uri ) = 0;
%Docstring
Associate dataset with the mesh
%End

virtual int datasetCount() const = 0;
%Docstring
Return number of datasets loaded
%End

virtual bool datasetHasScalarData( int index ) const = 0;
%Docstring
Whether dataset has scalar data associated
%End

virtual bool datasetIsOnVertices( int index ) const = 0;
%Docstring
Whether dataset is on vertices
%End

virtual QgsMeshDatasetMetadata datasetMetadata( int index ) const = 0;
%Docstring
Return dataset metadata
%End

virtual QgsMeshDatasetValue datasetValue( int datasetIndex, int valueIndex ) const = 0;
%Docstring
Return value associated with the index from the dataset
%End

virtual bool datasetIsValid( int index ) const = 0;
%Docstring
Return whether dataset is valid
%End
};


class QgsMeshDataProvider: QgsDataProvider, QgsMeshSource, QgsMeshDatasetSource
{
%Docstring
Base class for providing data for :py:class:`QgsMeshLayer`
Expand Down
5 changes: 5 additions & 0 deletions python/core/auto_generated/mesh/qgsmeshlayer.sip.in
Expand Up @@ -52,6 +52,8 @@ E.g. to create mesh with one quad and one triangle
);
QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch layer", "memory_mesh");

Add datasets by adding them through data provider, :py:func:`QgsMeshDatasetSource.addDataset`

\subsection mdal MDAL data provider (mdal)

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

void setActiveScalarDataset( int index = -1 );
void setActiveVectorDataset( int index = -1 );

private: // Private methods
QgsMeshLayer( const QgsMeshLayer &rhs );
};
Expand Down
98 changes: 98 additions & 0 deletions src/core/mesh/qgsmeshdataprovider.cpp
Expand Up @@ -16,6 +16,7 @@
***************************************************************************/

#include "qgsmeshdataprovider.h"
#include "qgis.h"

QgsMeshDataProvider::QgsMeshDataProvider( const QString &uri )
: QgsDataProvider( uri )
Expand All @@ -38,3 +39,100 @@ QgsRectangle QgsMeshDataProvider::extent() const
return rec;

}

QgsMeshDatasetValue::QgsMeshDatasetValue( double x, double y )
{
setX( x );
setY( y );
}

QgsMeshDatasetValue::QgsMeshDatasetValue( double scalar )
{
set( scalar );
}

void QgsMeshDatasetValue::setNodata( bool nodata )
{
mIsNodata = nodata;
}

bool QgsMeshDatasetValue::isNodata() const
{return mIsNodata;}

bool QgsMeshDatasetValue::isScalar() const
{
return mIsScalar;
}

double QgsMeshDatasetValue::scalar() const
{
if ( isNodata() )
{
return std::numeric_limits<double>::quiet_NaN();
}

if ( isScalar() )
{
return mX;
}
else
{
return std::sqrt( ( mX ) * ( mX ) + ( mY ) * ( mY ) );
}
}

void QgsMeshDatasetValue::set( double scalar )
{
setX( scalar );
mIsScalar = true;
}

void QgsMeshDatasetValue::setX( double x )
{
mX = x;
if ( std::isnan( x ) )
{
mIsNodata = true;
}
}

void QgsMeshDatasetValue::setY( double y )
{
mY = y;
if ( std::isnan( y ) )
{
mIsScalar = true;
}
}

double QgsMeshDatasetValue::x() const
{
return mX;
}

double QgsMeshDatasetValue::y() const
{
return mY;
}

bool QgsMeshDatasetValue::operator==( const QgsMeshDatasetValue &other ) const
{
bool equal = true;
if ( isNodata() )
equal = other.isNodata();
else
{
if ( isScalar() )
{
equal &= other.isScalar();
equal &= qgsDoubleNear( other.x(), mX, 1E-8 );
}
else
{
equal &= !other.isScalar();
equal &= qgsDoubleNear( other.x(), mX, 1E-8 );
equal &= qgsDoubleNear( other.y(), mY, 1E-8 );
}
}
return equal;
}
117 changes: 107 additions & 10 deletions src/core/mesh/qgsmeshdataprovider.h
Expand Up @@ -25,9 +25,54 @@

#include <QVector>
#include <QString>
#include <QMap>
#include <limits>

typedef QgsPoint QgsMeshVertex; //xyz coords of vertex
typedef QVector<int> QgsMeshFace; //list of vertex indexes
//! xyz coords of vertex
typedef QgsPoint QgsMeshVertex;

//! List of vertex indexes
typedef QVector<int> QgsMeshFace;

//! Dataset's metadata key:value map
typedef QMap<QString, QString> QgsMeshDatasetMetadata;

/**
* \ingroup core
*
* QgsMeshDatasetValue is a vector or a scalar value on vertex or face of the mesh with
* support of nodata values
*
* \since QGIS 3.2
*/
class CORE_EXPORT QgsMeshDatasetValue
{
Q_GADGET

public:
QgsMeshDatasetValue( double x,
double y );
QgsMeshDatasetValue( double scalar );
QgsMeshDatasetValue( ) = default;

~QgsMeshDatasetValue() = default;
void setNodata( bool nodata = true );
bool isNodata() const;
bool isScalar() const;
double scalar() const; //length for vectors, value for scalars
void set( double scalar );
void setX( double x );
void setY( double y ) ;
double x() const;
double y() const;
bool operator==( const QgsMeshDatasetValue &other ) const;

private:
double mX = std::numeric_limits<double>::quiet_NaN();
double mY = std::numeric_limits<double>::quiet_NaN();
bool mIsNodata = true;
bool mIsScalar = true;
};

/**
* \ingroup core
Expand Down Expand Up @@ -73,14 +118,66 @@ class CORE_EXPORT QgsMeshSource SIP_ABSTRACT

/**
* \ingroup core
* Base class for providing data for QgsMeshLayer
*
* Responsible for reading native mesh data
*
* \see QgsMeshSource
* \since QGIS 3.2
*/
class CORE_EXPORT QgsMeshDataProvider: public QgsDataProvider, public QgsMeshSource
* Dataset is a collection of vector or scalar values on vertices or faces of the mesh
*
* Base on the underlying data provider/format, whole dataset is either stored in memory or
* read on demand
*
* \since QGIS 3.2
*/
class CORE_EXPORT QgsMeshDatasetSource SIP_ABSTRACT
{
public:
//! Dtor
virtual ~QgsMeshDatasetSource() = default;

/**
* \brief Associate dataset with the mesh
*/
virtual bool addDataset( const QString &uri ) = 0;

/**
* \brief Return number of datasets loaded
*/
virtual int datasetCount() const = 0;

/**
* \brief Whether dataset has scalar data associated
*/
virtual bool datasetHasScalarData( int index ) const = 0;

/**
* \brief Whether dataset is on vertices
*/
virtual bool datasetIsOnVertices( int index ) const = 0;

/**
* \brief Return dataset metadata
*/
virtual QgsMeshDatasetMetadata datasetMetadata( int index ) const = 0;

/**
* \brief Return value associated with the index from the dataset
*/
virtual QgsMeshDatasetValue datasetValue( int datasetIndex, int valueIndex ) const = 0;

/**
* \brief Return whether dataset is valid
*/
virtual bool datasetIsValid( int index ) const = 0;
};


/**
* \ingroup core
* Base class for providing data for QgsMeshLayer
*
* Responsible for reading native mesh data
*
* \see QgsMeshSource
* \since QGIS 3.2
*/
class CORE_EXPORT QgsMeshDataProvider: public QgsDataProvider, public QgsMeshSource, public QgsMeshDatasetSource
{
Q_OBJECT

Expand Down
14 changes: 14 additions & 0 deletions src/core/mesh/qgsmeshlayer.cpp
Expand Up @@ -127,6 +127,20 @@ void QgsMeshLayer::toggleTriangularMeshRendering( bool toggle )
triggerRepaint();
}

void QgsMeshLayer::setActiveScalarDataset( int index )
{
Q_ASSERT( dataProvider()->datasetCount() > index );
if ( dataProvider()->datasetHasScalarData( index ) )
mActiveScalarDataset = index;
}

void QgsMeshLayer::setActiveVectorDataset( int index )
{
Q_ASSERT( dataProvider()->datasetCount() > index );
if ( !dataProvider()->datasetHasScalarData( index ) )
mActiveVectorDataset = index;
}

void QgsMeshLayer::fillNativeMesh()
{
Q_ASSERT( !mNativeMesh );
Expand Down

0 comments on commit 3154102

Please sign in to comment.