Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE] Initial implementation of QEP 158: Support of 3d stacked me…
…shes in QGIS.

Stacked 3D meshes store values on the volumes that are regularly stacked over base 2d mesh. User can select various 3d to 2d averaging/interpolation method to convert values on volumes (3d) to values on faces (2d) that can be shown in mesh layer. This is achieved by new tab in the mesh layer properties dialog.
  • Loading branch information
PeterPetrik committed Dec 5, 2019
1 parent c1acb01 commit a30bda6
Show file tree
Hide file tree
Showing 34 changed files with 1,468 additions and 167 deletions.
1 change: 1 addition & 0 deletions images/images.qrc
Expand Up @@ -565,6 +565,7 @@
<file>themes/default/propertyicons/labeltext.svg</file>
<file>themes/default/propertyicons/locale.svg</file>
<file>themes/default/propertyicons/map_tools.svg</file>
<file>themes/default/propertyicons/meshaveraging.svg</file>
<file>themes/default/propertyicons/meshcontours.svg</file>
<file>themes/default/propertyicons/meshcontoursoff.svg</file>
<file>themes/default/propertyicons/meshframe.svg</file>
Expand Down
1 change: 1 addition & 0 deletions images/themes/default/propertyicons/meshaveraging.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 113 additions & 7 deletions python/core/auto_generated/mesh/qgsmeshdataprovider.sip.in
Expand Up @@ -215,6 +215,79 @@ For scalar and vector 2d the behavior is undefined



};

class QgsMesh3dDataBlock
{
%Docstring

QgsMesh3dDataBlock is a block of 3d stacked mesh data related N
faces defined on base mesh frame.

data are implicitly shared, so the class can be quickly copied
std.numeric_limits<double>.quiet_NaN() represents NODATA value

.. versionadded:: 3.12
%End

%TypeHeaderCode
#include "qgsmeshdataprovider.h"
%End
public:
enum DataType
{
ActiveFlagInteger,
ScalarDouble,
VectorDouble,
VerticalLevelsCount,
VerticalLevels,
FaceToVolumeIndex
};

QgsMesh3dDataBlock();
%Docstring
Constructs an invalid block
%End

~QgsMesh3dDataBlock();

QgsMesh3dDataBlock( int count, int maximumVerticalLevels, bool isVector );
%Docstring
Constructs a new block for count faces
%End

void setIsValid();
%Docstring
Sets block as valid
%End

bool isValid() const;
%Docstring
Whether the block is valid
%End

bool isVector() const;
%Docstring
Whether we store vector values
%End

int count() const;
%Docstring
Number of items stored in the block
%End

int firstVolumeIndex() const;
%Docstring
Index of the first volume stored in the buffer
%End

int lastVolumeIndex() const;
%Docstring
Index of the last volume stored in the buffer
%End



};

class QgsMeshDatasetGroupMetadata
Expand All @@ -239,7 +312,8 @@ such as whether the data is vector or scalar, name
enum DataType
{
DataOnFaces,
DataOnVertices
DataOnVertices,
DataOnVolumes
};

QgsMeshDatasetGroupMetadata();
Expand All @@ -249,7 +323,7 @@ Constructs an empty metadata object

QgsMeshDatasetGroupMetadata( const QString &name,
bool isScalar,
bool isOnVertices,
DataType dataType,
double minimum,
double maximum,
const QMap<QString, QString> &extraOptions );
Expand All @@ -258,7 +332,7 @@ Constructs a valid metadata object

:param name: name of the dataset group
:param isScalar: dataset contains scalar data, specifically the y-value of QgsMeshDatasetValue is NaN
:param isOnVertices: dataset values are defined on mesh's vertices. If ``False``, values are defined on faces.
:param dataType: where the data are defined on (vertices, faces or volumes)
:param minimum: minimum value (magnitude for vectors) present among all group's dataset values
:param maximum: maximum value (magnitude for vectors) present among all group's dataset values
:param extraOptions: dataset's extra options stored by the provider. Usually contains the name, time value, time units, data file vendor, ...
Expand Down Expand Up @@ -286,7 +360,9 @@ Returns whether dataset group has scalar data

DataType dataType() const;
%Docstring
Returns whether dataset group data is defined on vertices or faces
Returns whether dataset group data is defined on vertices or faces or volumes

.. versionadded:: 3.12
%End

double minimum() const;
Expand Down Expand Up @@ -327,7 +403,8 @@ Constructs an empty metadata object
QgsMeshDatasetMetadata( double time,
bool isValid,
double minimum,
double maximum
double maximum,
int maximumVerticalLevelsCount
);
%Docstring
Constructs a valid metadata object
Expand All @@ -336,6 +413,7 @@ Constructs a valid metadata object
:param isValid: dataset is loadad and valid for fetching the data
:param minimum: minimum value (magnitude for vectors) present among dataset values
:param maximum: maximum value (magnitude for vectors) present among dataset values
:param maximumVerticalLevelsCount: maximum number of vertical levels for 3d stacked meshes, 0 for 2d meshes
%End

double time() const;
Expand All @@ -356,6 +434,13 @@ Returns minimum scalar value/vector magnitude present for the dataset
double maximum() const;
%Docstring
Returns maximum scalar value/vector magnitude present for the dataset
%End

int maximumVerticalLevelsCount() const;
%Docstring
Returns maximum number of vertical levels for 3d stacked meshes

.. versionadded:: 3.12
%End

};
Expand Down Expand Up @@ -478,19 +563,40 @@ Returns dataset metadata
virtual QgsMeshDatasetValue datasetValue( QgsMeshDatasetIndex index, int valueIndex ) const = 0;
%Docstring
Returns vector/scalar value associated with the index from the dataset
To read multiple continuous values, use :py:func:`QgsMeshDatasetSourceInterface.datasetValues()`
To read multiple continuous values, use datasetValues()

See QgsMeshDatasetMetadata.isVector() or :py:func:`QgsMeshDataBlock.type()`
to check if the returned value is vector or scalar

Returns invalid value for DataOnVolumes

.. seealso:: :py:func:`datasetValues`
%End

virtual QgsMeshDataBlock datasetValues( QgsMeshDatasetIndex index, int valueIndex, int count ) const = 0;
%Docstring
Returns N vector/scalar values from the index from the dataset

See QgsMeshDatasetMetadata.isVector() to check if the returned value is vector or scalar
See QgsMeshDatasetMetadata.isVector() or :py:func:`QgsMeshDataBlock.type()`
to check if the returned value is vector or scalar

Returns invalid block for DataOnVolumes. Use QgsMeshLayerUtils.datasetValues() if you
need block for any type of data typ

.. versionadded:: 3.6
%End

virtual QgsMesh3dDataBlock dataset3dValues( QgsMeshDatasetIndex index, int faceIndex, int count ) const = 0;
%Docstring
Returns N vector/scalar values from the face index from the dataset for 3d stacked meshes

See QgsMeshDatasetMetadata.isVector() to check if the returned value is vector or scalar

returns invalid block for DataOnFaces and DataOnVertices.

.. seealso:: :py:func:`datasetValues`

.. versionadded:: 3.12
%End

virtual bool isFaceActive( QgsMeshDatasetIndex index, int faceIndex ) const = 0;
Expand Down
2 changes: 2 additions & 0 deletions python/core/auto_generated/mesh/qgsmeshlayer.sip.in
Expand Up @@ -157,6 +157,8 @@ Returns renderer settings
Sets new renderer settings
%End



QgsMeshTimeSettings timeSettings() const;
%Docstring
Returns time format settings
Expand Down
100 changes: 100 additions & 0 deletions python/core/auto_generated/mesh/qgsmeshrenderersettings.sip.in
Expand Up @@ -546,6 +546,97 @@ Reads configuration from the given DOM element
%End


};

class QgsMeshRendererAveragingSingleVerticalLayerSettings
{
%Docstring

Represents mesh renderer settings for averaging method :py:class:`QgsMeshSingleLevelAverageMethod`

.. note::

The API is considered EXPERIMENTAL and can be changed without a notice

.. versionadded:: 3.12
%End

%TypeHeaderCode
#include "qgsmeshrenderersettings.h"
%End
public:

int verticalLayer() const;
%Docstring
Returns index of vertical layer to show (indexed from 0, from top layer)
%End
void setVerticalLayer( int verticalLayer );
%Docstring
Sets index of vertical layer to show (indexed from 0, from top layer)
%End

QDomElement writeXml( QDomDocument &doc ) const;
%Docstring
Writes configuration to a new DOM element
%End
void readXml( const QDomElement &elem );
%Docstring
Reads configuration from the given DOM element
%End
};

class QgsMeshRenderer3dAveragingSettings
{
%Docstring

Represents mesh renderer settings for averaging method

.. note::

The API is considered EXPERIMENTAL and can be changed without a notice

.. versionadded:: 3.12
%End

%TypeHeaderCode
#include "qgsmeshrenderersettings.h"
%End
public:

enum Method
{
SingleVerticalLayer,
};

Method averagingMethod() const;
%Docstring
Returns averaging method
%End

void setAveragingMethod( const Method &averagingMethod );
%Docstring
Sets averaging method
%End

QgsMeshRendererAveragingSingleVerticalLayerSettings singleVerticalLayerSettings() const;
%Docstring
Returns settings for :py:class:`QgsMeshSingleLevelAverageMethod`
%End

void setSingleVerticalLayerSettings( const QgsMeshRendererAveragingSingleVerticalLayerSettings &singleVerticalLayerSettings );
%Docstring
Sets settings for :py:class:`QgsMeshSingleLevelAverageMethod`
%End

QDomElement writeXml( QDomDocument &doc ) const;
%Docstring
Writes configuration to a new DOM element
%End
void readXml( const QDomElement &elem );
%Docstring
Reads configuration from the given DOM element
%End

};

class QgsMeshRendererSettings
Expand Down Expand Up @@ -599,6 +690,15 @@ Returns renderer settings
void setVectorSettings( int groupIndex, const QgsMeshRendererVectorSettings &settings );
%Docstring
Sets new renderer settings
%End

QgsMeshRenderer3dAveragingSettings averagingSettings( ) const;
%Docstring
Returns renderer settings
%End
void setAveragingSettings( const QgsMeshRenderer3dAveragingSettings &settings );
%Docstring
Sets new renderer settings
%End

QgsMeshDatasetIndex activeScalarDataset() const;
Expand Down
5 changes: 3 additions & 2 deletions src/analysis/mesh/qgsmeshcalcutils.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgsmeshmemorydataprovider.h"
#include "qgstriangularmesh.h"
#include "qgsmapsettings.h"
#include "qgsmeshlayerutils.h"

const double D_TRUE = 1.0;
const double D_FALSE = 0.0;
Expand All @@ -45,7 +46,7 @@ std::shared_ptr<QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::create( const QStri
grp->minimum = meta.minimum();
grp->name = meta.name();

int count = ( meta.dataType() == QgsMeshDatasetGroupMetadata::DataOnFaces ) ? dp->faceCount() : dp->vertexCount();
int count = ( meta.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices ) ? dp->vertexCount() : dp->faceCount();
for ( int dataset_i = 0; dataset_i < dp->datasetCount( group_i ); ++dataset_i )
{
const QgsMeshDatasetIndex index( group_i, dataset_i );
Expand All @@ -56,7 +57,7 @@ std::shared_ptr<QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::create( const QStri
ds->time = dsMeta.time();
ds->valid = dsMeta.isValid();

const QgsMeshDataBlock block = dp->datasetValues( index, 0, count );
const QgsMeshDataBlock block = QgsMeshLayerUtils::datasetValues( dp, index, 0, count, mMeshLayer->averagingMethod() );
Q_ASSERT( block.count() == count );
for ( int value_i = 0; value_i < count; ++value_i )
ds->values[value_i] = block.value( value_i );
Expand Down
8 changes: 5 additions & 3 deletions src/analysis/mesh/qgsmeshcontours.cpp
Expand Up @@ -357,14 +357,16 @@ void QgsMeshContours::populateCache( const QgsMeshDatasetIndex &index, QgsMeshRe
{
if ( mCachedIndex != index )
{
bool scalarDataOnVertices = mMeshLayer->dataProvider()->datasetGroupMetadata( index ).dataType() != QgsMeshDatasetGroupMetadata::DataOnFaces;
bool scalarDataOnVertices = mMeshLayer->dataProvider()->datasetGroupMetadata( index ).dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices;
int count = scalarDataOnVertices ? mNativeMesh->vertices.count() : mNativeMesh->faces.count();

// populate scalar values
QgsMeshDataBlock vals = mMeshLayer->dataProvider()->datasetValues(
QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues(
mMeshLayer->dataProvider(),
index,
0,
count );
count,
mMeshLayer->averagingMethod() );

// vals could be scalar or vectors, for contour rendering we want always magnitude
mDatasetValues = QgsMeshLayerUtils::calculateMagnitudes( vals );
Expand Down
1 change: 1 addition & 0 deletions src/app/CMakeLists.txt
Expand Up @@ -252,6 +252,7 @@ SET(QGIS_APP_SRCS

mesh/qgsmeshlayerproperties.cpp
mesh/qgsrenderermeshpropertieswidget.cpp
mesh/qgsmeshrenderer3daveragingwidget.cpp
mesh/qgsmeshrenderermeshsettingswidget.cpp
mesh/qgsmeshrendererscalarsettingswidget.cpp
mesh/qgsmeshrenderervectorsettingswidget.cpp
Expand Down

0 comments on commit a30bda6

Please sign in to comment.