Make scalar/vector rendering settings per dataset group

Until now there was just one scalar and vector configuration
for a mesh layer. It is however most useful to have different
rendering settings for each dataset group (quantity).
This commit is contained in:
Martin Dobias 2018-08-14 13:48:20 +02:00
parent feddb3d3e6
commit 9fc2e3e148
26 changed files with 334 additions and 213 deletions

View File

@ -392,6 +392,12 @@ Ctor
Returns the extent of the layer
:return: QgsRectangle containing the extent of the layer
%End
signals:
void datasetGroupsAdded( int count );
%Docstring
Emitted when some new dataset groups have been added
%End
};

View File

@ -83,12 +83,6 @@ Returns color ramp shader function
Sets color ramp shader function
%End
bool isEnabled() const;
%Docstring
Returns whether color ramp has any items assigned
%End
void setEnabled( bool enabled );
};
class QgsMeshRendererVectorSettings
@ -109,15 +103,6 @@ Represents a mesh renderer settings for vector datasets
%End
public:
bool isEnabled() const;
%Docstring
Returns whether rendering of vectors is enabled
%End
void setEnabled( bool enabled );
%Docstring
Sets whether rendering of vectors is enabled
%End
enum ArrowScalingMethod
{
@ -299,20 +284,20 @@ Returns renderer settings
Sets new renderer settings
%End
QgsMeshRendererScalarSettings scalarSettings() const;
QgsMeshRendererScalarSettings scalarSettings( int groupIndex ) const;
%Docstring
Returns renderer settings
%End
void setScalarSettings( const QgsMeshRendererScalarSettings &settings );
void setScalarSettings( int groupIndex, const QgsMeshRendererScalarSettings &settings );
%Docstring
Sets new renderer settings
%End
QgsMeshRendererVectorSettings vectorSettings() const;
QgsMeshRendererVectorSettings vectorSettings( int groupIndex ) const;
%Docstring
Returns renderer settings
%End
void setVectorSettings( const QgsMeshRendererVectorSettings &settings );
void setVectorSettings( int groupIndex, const QgsMeshRendererVectorSettings &settings );
%Docstring
Sets new renderer settings
%End

View File

@ -283,11 +283,6 @@ int QgsMeshDatasetGroupTreeView::setActiveGroupFromActiveDataset()
{
group = activeDataset.group();
}
else if ( !mGroups.empty() )
{
// not found, select first item
group = 0;
}
if ( mActiveGroup != group )
{

View File

@ -67,6 +67,8 @@ void QgsMeshRendererActiveDatasetWidget::onActiveGroupChanged()
mDatasetSlider->setValue( val );
onActiveDatasetChanged( val );
mActiveDatasetGroup = mDatasetGroupTreeView->activeGroup();
emit activeDatasetGroupChanged( mActiveDatasetGroup );
}
void QgsMeshRendererActiveDatasetWidget::onActiveDatasetChanged( int value )

View File

@ -46,6 +46,12 @@ class APP_EXPORT QgsMeshRendererActiveDatasetWidget : public QWidget, private Ui
//! Associates mesh layer with the widget
void setLayer( QgsMeshLayer *layer );
//! Returns index of the active scalar dataset group
int activeScalarDatasetGroup() const { return mActiveDatasetGroup; }
//! Returns index of the active vector dataset group
int activeVectorDatasetGroup() const { return mActiveDatasetGroup; }
//! Gets index of the selected/active scalar dataset
QgsMeshDatasetIndex activeScalarDataset() const;
@ -63,6 +69,9 @@ class APP_EXPORT QgsMeshRendererActiveDatasetWidget : public QWidget, private Ui
//! Emitted when active vector dataset changed
void activeVectorDatasetChanged( QgsMeshDatasetIndex index );
//! Emitted when the current group gets changed
void activeDatasetGroupChanged( int groupIndex );
//! Emitted when any settings related to rendering changed
void widgetChanged();
@ -76,6 +85,7 @@ class APP_EXPORT QgsMeshRendererActiveDatasetWidget : public QWidget, private Ui
void setSliderRange();
QgsMeshLayer *mMeshLayer = nullptr; // not owned
int mActiveDatasetGroup = -1;
QgsMeshDatasetIndex mActiveScalarDataset;
QgsMeshDatasetIndex mActiveVectorDataset;
};

View File

@ -17,6 +17,7 @@
#include "qgis.h"
#include "qgsmeshlayer.h"
#include "qgsmeshlayerutils.h"
#include "qgsmessagelog.h"
@ -52,14 +53,15 @@ void QgsMeshRendererScalarSettingsWidget::syncToLayer( )
if ( !mMeshLayer )
return;
const QgsMeshRendererScalarSettings settings = mMeshLayer->rendererSettings().scalarSettings();
if ( settings.isEnabled() )
{
const QgsColorRampShader shader = settings.colorRampShader();
whileBlocking( mScalarMinLineEdit )->setText( QString::number( shader.minimumValue() ) );
whileBlocking( mScalarMaxLineEdit )->setText( QString::number( shader.maximumValue() ) );
whileBlocking( mScalarColorRampShaderWidget )->setFromShader( shader );
}
if ( mActiveDatasetGroup < 0 )
return;
const QgsMeshRendererSettings rendererSettings = mMeshLayer->rendererSettings();
const QgsMeshRendererScalarSettings settings = rendererSettings.scalarSettings( mActiveDatasetGroup );
const QgsColorRampShader shader = settings.colorRampShader();
whileBlocking( mScalarMinLineEdit )->setText( QString::number( shader.minimumValue() ) );
whileBlocking( mScalarMaxLineEdit )->setText( QString::number( shader.maximumValue() ) );
whileBlocking( mScalarColorRampShaderWidget )->setFromShader( shader );
}
double QgsMeshRendererScalarSettingsWidget::lineEditValue( const QLineEdit *lineEdit ) const
@ -89,54 +91,8 @@ void QgsMeshRendererScalarSettingsWidget::minMaxEdited()
void QgsMeshRendererScalarSettingsWidget::recalculateMinMaxButtonClicked()
{
double min, max;
calcMinMax( mActiveDataset, min, max );
QgsMeshLayerUtils::calculateMinMaxForDatasetGroup( min, max, mMeshLayer->dataProvider(), mActiveDatasetGroup );
whileBlocking( mScalarMinLineEdit )->setText( QString::number( min ) );
whileBlocking( mScalarMaxLineEdit )->setText( QString::number( max ) );
mScalarColorRampShaderWidget->setMinimumMaximumAndClassify( min, max );
}
void QgsMeshRendererScalarSettingsWidget::setActiveDataset( QgsMeshDatasetIndex activeDataset )
{
mActiveDataset = activeDataset;
}
void QgsMeshRendererScalarSettingsWidget::calcMinMax( QgsMeshDatasetIndex datasetIndex, double &min, double &max ) const
{
if ( !mMeshLayer )
return;
if ( !mMeshLayer->dataProvider() )
return;
const QgsMeshDatasetGroupMetadata metadata = mMeshLayer->dataProvider()->datasetGroupMetadata( datasetIndex );
bool scalarDataOnVertices = metadata.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices;
int count;
if ( scalarDataOnVertices )
count = mMeshLayer->dataProvider()->vertexCount();
else
count = mMeshLayer->dataProvider()->faceCount();
bool myFirstIterationFlag = true;
for ( int i = 0; i < count; ++i )
{
double myValue = mMeshLayer->dataProvider()->datasetValue( datasetIndex, i ).scalar();
if ( std::isnan( myValue ) ) continue; // NULL
if ( myFirstIterationFlag )
{
myFirstIterationFlag = false;
min = myValue;
max = myValue;
}
else
{
if ( myValue < min )
{
min = myValue;
}
if ( myValue > max )
{
max = myValue;
}
}
}
}

View File

@ -45,6 +45,9 @@ class APP_EXPORT QgsMeshRendererScalarSettingsWidget : public QWidget, private U
//! Associates mesh layer with the widget
void setLayer( QgsMeshLayer *layer );
//! Associates a dataset group with the widget (should be set before syncToLayer())
void setActiveDatasetGroup( int groupIndex ) { mActiveDatasetGroup = groupIndex; }
//! Returns scalar settings
QgsMeshRendererScalarSettings settings() const;
@ -55,10 +58,6 @@ class APP_EXPORT QgsMeshRendererScalarSettingsWidget : public QWidget, private U
//! Mesh rendering settings changed
void widgetChanged();
public slots:
//! Set active scalar dataset to be used
void setActiveDataset( QgsMeshDatasetIndex activeDataset );
private slots:
void minMaxChanged();
void minMaxEdited();
@ -66,10 +65,9 @@ class APP_EXPORT QgsMeshRendererScalarSettingsWidget : public QWidget, private U
private:
double lineEditValue( const QLineEdit *lineEdit ) const;
void calcMinMax( QgsMeshDatasetIndex datasetIndex, double &min, double &max ) const;
QgsMeshLayer *mMeshLayer = nullptr; // not owned
QgsMeshDatasetIndex mActiveDataset;
int mActiveDatasetGroup = -1;
};
#endif // QGSMESHRENDERERSCALARSETTINGSWIDGET_H

View File

@ -93,17 +93,16 @@ QgsMeshRendererVectorSettings QgsMeshRendererVectorSettingsWidget::settings() co
return settings;
}
void QgsMeshRendererVectorSettingsWidget::setActiveDataset( QgsMeshDatasetIndex activeDataset )
{
mActiveDataset = activeDataset;
}
void QgsMeshRendererVectorSettingsWidget::syncToLayer( )
{
if ( !mMeshLayer )
return;
QgsMeshRendererVectorSettings settings = mMeshLayer->rendererSettings().vectorSettings();
if ( mActiveDatasetGroup < 0 )
return;
const QgsMeshRendererSettings rendererSettings = mMeshLayer->rendererSettings();
const QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( mActiveDatasetGroup );
// basic
mColorWidget->setColor( settings.color() );

View File

@ -46,6 +46,9 @@ class APP_EXPORT QgsMeshRendererVectorSettingsWidget : public QWidget, private U
//! Associates mesh layer with the widget
void setLayer( QgsMeshLayer *layer );
//! Associates a dataset group with the widget (should be set before syncToLayer())
void setActiveDatasetGroup( int groupIndex ) { mActiveDatasetGroup = groupIndex; }
//! Returns vector settings
QgsMeshRendererVectorSettings settings() const;
@ -56,10 +59,6 @@ class APP_EXPORT QgsMeshRendererVectorSettingsWidget : public QWidget, private U
//! Mesh rendering settings changed
void widgetChanged();
public slots:
//! Set active vector dataset to be used
void setActiveDataset( QgsMeshDatasetIndex activeDataset );
private:
/**
@ -69,7 +68,7 @@ class APP_EXPORT QgsMeshRendererVectorSettingsWidget : public QWidget, private U
double filterValue( const QString &text, double errVal ) const;
QgsMeshLayer *mMeshLayer = nullptr; //not owned
QgsMeshDatasetIndex mActiveDataset;
int mActiveDatasetGroup = -1;
};
#endif // QGSMESHRENDERERVECTORSETTINGSWIDGET_H

View File

@ -44,12 +44,8 @@ QgsRendererMeshPropertiesWidget::QgsRendererMeshPropertiesWidget( QgsMeshLayer *
mMeshRendererVectorSettingsWidget->setLayer( mMeshLayer );
syncToLayer();
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeScalarDatasetChanged,
mMeshRendererScalarSettingsWidget, &QgsMeshRendererScalarSettingsWidget::setActiveDataset );
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeVectorDatasetChanged,
mMeshRendererVectorSettingsWidget, &QgsMeshRendererVectorSettingsWidget::setActiveDataset );
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeVectorDatasetChanged,
this, &QgsRendererMeshPropertiesWidget::enableVectorRenderingTab );
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeDatasetGroupChanged,
this, &QgsRendererMeshPropertiesWidget::onActiveDatasetGroupChanged );
connect( mNativeMeshGroup, &QGroupBox::toggled, this, &QgsPanelWidget::widgetChanged );
connect( mTriangularMeshGroup, &QGroupBox::toggled, this, &QgsPanelWidget::widgetChanged );
@ -81,45 +77,54 @@ void QgsRendererMeshPropertiesWidget::apply()
triangularMeshSettings.setEnabled( triangularMeshRenderingIsEnabled );
// SCALAR
const QgsMeshDatasetIndex activeScalarDatasetIndex = mMeshRendererActiveDatasetWidget->activeScalarDataset();
QgsMeshRendererScalarSettings scalarSettings = mMeshRendererScalarSettingsWidget->settings();
scalarSettings.setEnabled( mContoursGroupBox->isChecked() );
QgsMeshDatasetIndex activeScalarDatasetIndex = mMeshRendererActiveDatasetWidget->activeScalarDataset();
if ( !mContoursGroupBox->isChecked() )
activeScalarDatasetIndex = QgsMeshDatasetIndex();
// VECTOR
const QgsMeshDatasetIndex activeVectorDatasetIndex = mMeshRendererActiveDatasetWidget->activeVectorDataset();
QgsMeshRendererVectorSettings vectorSettings = mMeshRendererVectorSettingsWidget->settings();
vectorSettings.setEnabled( mVectorsGroupBox->isChecked() );
QgsMeshDatasetIndex activeVectorDatasetIndex = mMeshRendererActiveDatasetWidget->activeVectorDataset();
if ( !mVectorsGroupBox->isChecked() )
activeVectorDatasetIndex = QgsMeshDatasetIndex();
QgsMeshRendererSettings settings;
QgsMeshRendererSettings settings = mMeshLayer->rendererSettings();
settings.setNativeMeshSettings( meshSettings );
settings.setTriangularMeshSettings( triangularMeshSettings );
settings.setScalarSettings( scalarSettings );
settings.setVectorSettings( vectorSettings );
settings.setActiveScalarDataset( activeScalarDatasetIndex );
settings.setActiveVectorDataset( activeVectorDatasetIndex );
mMeshLayer->setRendererSettings( settings );
settings.setActiveScalarDataset( activeScalarDatasetIndex );
if ( activeScalarDatasetIndex.isValid() )
settings.setScalarSettings( activeScalarDatasetIndex.group(), mMeshRendererScalarSettingsWidget->settings() );
settings.setActiveVectorDataset( activeVectorDatasetIndex );
if ( activeVectorDatasetIndex.isValid() )
settings.setVectorSettings( activeVectorDatasetIndex.group(), mMeshRendererVectorSettingsWidget->settings() );
mMeshLayer->setRendererSettings( settings );
mMeshLayer->triggerRepaint();
}
void QgsRendererMeshPropertiesWidget::syncToLayer()
{
mMeshRendererActiveDatasetWidget->syncToLayer();
mMeshRendererScalarSettingsWidget->setActiveDataset( mMeshRendererActiveDatasetWidget->activeScalarDataset() );
mMeshRendererVectorSettingsWidget->setActiveDataset( mMeshRendererActiveDatasetWidget->activeVectorDataset() );
mMeshRendererScalarSettingsWidget->syncToLayer();
mNativeMeshSettingsWidget->syncToLayer();
mTriangularMeshSettingsWidget->syncToLayer();
onActiveDatasetGroupChanged();
}
void QgsRendererMeshPropertiesWidget::onActiveDatasetGroupChanged()
{
int scalarGroup = mMeshRendererActiveDatasetWidget->activeScalarDatasetGroup();
int vectorGroup = mMeshRendererActiveDatasetWidget->activeVectorDatasetGroup();
if ( vectorGroup >= 0 && !mMeshLayer->dataProvider()->datasetGroupMetadata( vectorGroup ).isVector() )
vectorGroup = -1;
mMeshRendererScalarSettingsWidget->setActiveDatasetGroup( scalarGroup );
mMeshRendererVectorSettingsWidget->setActiveDatasetGroup( vectorGroup );
mMeshRendererScalarSettingsWidget->syncToLayer();
mMeshRendererVectorSettingsWidget->syncToLayer();
mContoursGroupBox->setChecked( mMeshLayer->rendererSettings().scalarSettings().isEnabled() );
mVectorsGroupBox->setChecked( mMeshLayer->rendererSettings().vectorSettings().isEnabled() );
enableVectorRenderingTab( mMeshRendererActiveDatasetWidget->activeVectorDataset() );
}
void QgsRendererMeshPropertiesWidget::enableVectorRenderingTab( QgsMeshDatasetIndex vectorDatasetIndex )
{
mVectorsGroupBox->setEnabled( vectorDatasetIndex.isValid() );
mContoursGroupBox->setChecked( scalarGroup >= 0 );
mVectorsGroupBox->setChecked( vectorGroup >= 0 );
mVectorsGroupBox->setEnabled( vectorGroup >= 0 );
}

View File

@ -53,7 +53,7 @@ class APP_EXPORT QgsRendererMeshPropertiesWidget : public QgsMapLayerConfigWidge
void syncToLayer();
private slots:
void enableVectorRenderingTab( QgsMeshDatasetIndex vectorDatasetIndex );
void onActiveDatasetGroupChanged();
private:
QgsMeshLayer *mMeshLayer = nullptr; //not owned

View File

@ -462,6 +462,7 @@ SET(QGIS_CORE_SRCS
mesh/qgsmeshdataprovider.cpp
mesh/qgsmeshlayer.cpp
mesh/qgsmeshlayerrenderer.cpp
mesh/qgsmeshlayerutils.cpp
mesh/qgsmeshmemorydataprovider.cpp
mesh/qgstriangularmesh.cpp
mesh/qgsmeshlayerinterpolator.cpp
@ -1075,6 +1076,7 @@ SET(QGIS_CORE_HDRS
mesh/qgstriangularmesh.h
mesh/qgsmeshlayerrenderer.h
mesh/qgsmeshlayerinterpolator.h
mesh/qgsmeshlayerutils.h
mesh/qgsmeshvectorrenderer.h
mesh/qgsmeshrenderersettings.h

View File

@ -363,6 +363,10 @@ class CORE_EXPORT QgsMeshDataProvider: public QgsDataProvider, public QgsMeshDat
* \returns QgsRectangle containing the extent of the layer
*/
QgsRectangle extent() const override;
signals:
//! Emitted when some new dataset groups have been added
void datasetGroupsAdded( int count );
};
#endif // QGSMESHDATAPROVIDER_H

View File

@ -20,17 +20,19 @@
#include <QUuid>
#include "qgscolorramp.h"
#include "qgslogger.h"
#include "qgsmaplayerlegend.h"
#include "qgsmeshdataprovider.h"
#include "qgsmeshlayer.h"
#include "qgsmeshlayerrenderer.h"
#include "qgsmeshlayerutils.h"
#include "qgsproviderregistry.h"
#include "qgsreadwritecontext.h"
#include "qgstriangularmesh.h"
#include "qgsmeshlayerinterpolator.h"
QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
const QString &baseName,
const QString &providerKey,
@ -172,6 +174,36 @@ void QgsMeshLayer::fillNativeMesh()
}
}
void QgsMeshLayer::onDatasetGroupsAdded( int count )
{
// assign default style to new dataset groups
int newDatasetGroupCount = mDataProvider->datasetGroupCount();
for ( int i = newDatasetGroupCount - count; i < newDatasetGroupCount; ++i )
assignDefaultStyleToDatasetGroup( i );
}
static QgsGradientColorRamp *_createDefaultColorRamp()
{
QgsGradientStopsList stops;
stops << QgsGradientStop( 0.25, QColor( 0, 255, 255 ) );
stops << QgsGradientStop( 0.5, QColor( 0, 255, 0 ) );
stops << QgsGradientStop( 0.75, QColor( 255, 255, 0 ) );
return new QgsGradientColorRamp( QColor( 0, 0, 255 ), QColor( 255, 0, 0 ), false, stops );
}
void QgsMeshLayer::assignDefaultStyleToDatasetGroup( int groupIndex )
{
double groupMin, groupMax;
QgsMeshLayerUtils::calculateMinMaxForDatasetGroup( groupMin, groupMax, mDataProvider, groupIndex );
QgsColorRampShader fcn( groupMin, groupMax, _createDefaultColorRamp() );
fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
QgsMeshRendererScalarSettings scalarSettings;
scalarSettings.setColorRampShader( fcn );
mRendererSettings.setScalarSettings( groupIndex, scalarSettings );
}
QgsMapLayerRenderer *QgsMeshLayer::createMapRenderer( QgsRenderContext &rendererContext )
{
if ( !mNativeMesh )
@ -335,7 +367,11 @@ bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvid
mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
}
for ( int i = 0; i < mDataProvider->datasetGroupCount(); ++i )
assignDefaultStyleToDatasetGroup( i );
connect( mDataProvider, &QgsMeshDataProvider::dataChanged, this, &QgsMeshLayer::dataChanged );
connect( mDataProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshLayer::onDatasetGroupsAdded );
return true;
}

View File

@ -199,6 +199,10 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
private:
void fillNativeMesh();
void assignDefaultStyleToDatasetGroup( int groupIndex );
private slots:
void onDatasetGroupsAdded( int count );
private:
//! Pointer to data provider derived from the abastract base class QgsMeshDataProvider

View File

@ -16,7 +16,6 @@
***************************************************************************/
#include <memory>
#include <limits>
#include "qgsmeshlayerrenderer.h"
@ -30,36 +29,12 @@
#include "qgssinglebandpseudocolorrenderer.h"
#include "qgsrastershader.h"
#include "qgsmeshlayerinterpolator.h"
#include "qgsmeshlayerutils.h"
#include "qgsmeshvectorrenderer.h"
#include "qgsfillsymbollayer.h"
#include "qgssettings.h"
#include "qgsstyle.h"
static void calculateMinimumMaximum( double &min, double &max, const QVector<double> &arr )
{
bool found = false;
min = std::numeric_limits<double>::max();
max = std::numeric_limits<double>::min();
for ( const double val : arr )
{
if ( !std::isnan( val ) )
{
found = true;
if ( val < min )
min = val;
if ( val > max )
max = val;
}
}
if ( !found )
{
min = std::numeric_limits<double>::quiet_NaN();
max = std::numeric_limits<double>::quiet_NaN();
}
}
QgsMeshLayerRenderer::QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContext &context )
: QgsMapLayerRenderer( layer->id() )
@ -79,28 +54,9 @@ QgsMeshLayerRenderer::QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContex
copyScalarDatasetValues( layer );
copyVectorDatasetValues( layer );
assignDefaultScalarShader();
calculateOutputSize();
}
void QgsMeshLayerRenderer::assignDefaultScalarShader( )
{
// TODO: the assignment of default shader should be outside of the this renderer
#if 0
if ( mScalarDatasetValues.isEmpty() || mRendererSettings.scalarSettings().isEnabled() )
return; // no need for default shader, either rendering is off or we already have some shader
QgsSettings settings;
QString defaultPalette = settings.value( QStringLiteral( "/Raster/defaultPalette" ), "Spectral" ).toString();
std::unique_ptr<QgsColorRamp> colorRamp( QgsStyle::defaultStyle()->colorRamp( defaultPalette ) );
QgsColorRampShader fcn( mScalarDatasetMinimum, mScalarDatasetMaximum, colorRamp.release() );
fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
mRendererScalarSettings.setColorRampShader( fcn );
#endif
}
QgsFeedback *QgsMeshLayerRenderer::feedback() const
{
return mFeedback.get();
@ -154,7 +110,7 @@ void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
mScalarDatasetValues[i] = v;
}
calculateMinimumMaximum( mScalarDatasetMinimum, mScalarDatasetMaximum, mScalarDatasetValues );
QgsMeshLayerUtils::calculateMinimumMaximum( mScalarDatasetMinimum, mScalarDatasetMaximum, mScalarDatasetValues );
}
}
@ -195,7 +151,7 @@ void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )
}
}
calculateMinimumMaximum( mVectorDatasetMagMinimum, mVectorDatasetMagMaximum, mVectorDatasetValuesMag );
QgsMeshLayerUtils::calculateMinimumMaximum( mVectorDatasetMagMinimum, mVectorDatasetMagMaximum, mVectorDatasetValuesMag );
}
}
@ -245,10 +201,11 @@ void QgsMeshLayerRenderer::renderScalarDataset()
if ( std::isnan( mScalarDatasetMinimum ) || std::isnan( mScalarDatasetMaximum ) )
return; // only NODATA values
if ( !mRendererSettings.scalarSettings().isEnabled() )
QgsMeshDatasetIndex index = mRendererSettings.activeScalarDataset();
if ( !index.isValid() )
return; // no shader
QgsColorRampShader *fcn = new QgsColorRampShader( mRendererSettings.scalarSettings().colorRampShader() );
QgsColorRampShader *fcn = new QgsColorRampShader( mRendererSettings.scalarSettings( index.group() ).colorRampShader() );
QgsRasterShader *sh = new QgsRasterShader();
sh->setRasterShaderFunction( fcn ); // takes ownership of fcn
QgsMeshLayerInterpolator interpolator( mTriangularMesh, mScalarDatasetValues, mScalarDataOnVertices, mContext, mOutputSize );
@ -264,7 +221,8 @@ void QgsMeshLayerRenderer::renderScalarDataset()
void QgsMeshLayerRenderer::renderVectorDataset()
{
if ( !mRendererSettings.vectorSettings().isEnabled() )
QgsMeshDatasetIndex index = mRendererSettings.activeVectorDataset();
if ( !index.isValid() )
return;
if ( mVectorDatasetValuesX.isEmpty() )
@ -279,7 +237,7 @@ void QgsMeshLayerRenderer::renderVectorDataset()
QgsMeshVectorRenderer renderer( mTriangularMesh,
mVectorDatasetValuesX, mVectorDatasetValuesY, mVectorDatasetValuesMag,
mVectorDatasetMagMinimum, mVectorDatasetMagMaximum,
mVectorDataOnVertices, mRendererSettings.vectorSettings(), mContext, mOutputSize );
mVectorDataOnVertices, mRendererSettings.vectorSettings( index.group() ), mContext, mOutputSize );
renderer.draw();
}

View File

@ -69,7 +69,6 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer
void renderVectorDataset();
void copyScalarDatasetValues( QgsMeshLayer *layer );
void copyVectorDatasetValues( QgsMeshLayer *layer );
void assignDefaultScalarShader( );
void createMeshSymbol( std::unique_ptr<QgsSymbol> &symbol, const QgsMeshRendererMeshSettings &settings );
void calculateOutputSize();

View File

@ -0,0 +1,119 @@
/***************************************************************************
qgsmeshlayerutils.cpp
--------------------------
begin : August 2018
copyright : (C) 2018 by Martin Dobias
email : wonder dot sk at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsmeshlayerutils.h"
#include "qgsmeshdataprovider.h"
#include <limits>
///@cond PRIVATE
void QgsMeshLayerUtils::calculateMinimumMaximum( double &min, double &max, const QVector<double> &arr )
{
bool found = false;
min = std::numeric_limits<double>::max();
max = std::numeric_limits<double>::min();
for ( const double val : arr )
{
if ( !std::isnan( val ) )
{
found = true;
if ( val < min )
min = val;
if ( val > max )
max = val;
}
}
if ( !found )
{
min = std::numeric_limits<double>::quiet_NaN();
max = std::numeric_limits<double>::quiet_NaN();
}
}
void QgsMeshLayerUtils::calculateMinMaxForDatasetGroup( double &min, double &max, QgsMeshDataProvider *provider, int groupIndex )
{
if ( groupIndex < 0 || groupIndex >= provider->datasetGroupCount() )
{
min = std::numeric_limits<double>::quiet_NaN();
max = std::numeric_limits<double>::quiet_NaN();
return;
}
min = std::numeric_limits<double>::max();
max = std::numeric_limits<double>::min();
int count = provider->datasetCount( groupIndex );
for ( int i = 0; i < count; ++i )
{
double dMin, dMax;
calculateMinMaxForDataset( dMin, dMax, provider, QgsMeshDatasetIndex( groupIndex, i ) );
min = std::min( min, dMin );
max = std::max( max, dMax );
}
}
void QgsMeshLayerUtils::calculateMinMaxForDataset( double &min, double &max, QgsMeshDataProvider *provider, QgsMeshDatasetIndex index )
{
if ( !index.isValid() )
{
min = std::numeric_limits<double>::quiet_NaN();
max = std::numeric_limits<double>::quiet_NaN();
return;
}
const QgsMeshDatasetGroupMetadata metadata = provider->datasetGroupMetadata( index );
bool onVertices = metadata.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices;
int count;
if ( onVertices )
count = provider->vertexCount();
else
count = provider->faceCount();
bool firstIteration = true;
for ( int i = 0; i < count; ++i )
{
double v = provider->datasetValue( index, i ).scalar();
if ( std::isnan( v ) )
continue;
if ( firstIteration )
{
firstIteration = false;
min = v;
max = v;
}
else
{
if ( v < min )
{
min = v;
}
if ( v > max )
{
max = v;
}
}
}
}
///@endcond

View File

@ -0,0 +1,53 @@
/***************************************************************************
qgsmeshlayerutils.h
--------------------------
begin : August 2018
copyright : (C) 2018 by Martin Dobias
email : wonder dot sk at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSMESHLAYERUTILS_H
#define QGSMESHLAYERUTILS_H
#include "qgis_core.h"
class QgsMeshDataProvider;
class QgsMeshDatasetIndex;
#include <QVector>
///@cond PRIVATE
/**
* \ingroup core
* Misc utility functions used for mesh layer support
*
* \note not available in Python bindings
* \since QGIS 3.4
*/
class CORE_EXPORT QgsMeshLayerUtils
{
public:
//! Calculates min/max values from the given vector of values
static void calculateMinimumMaximum( double &min, double &max, const QVector<double> &arr );
//! Calculates min/max values for the whole dataset group (considering all datasets within it)
static void calculateMinMaxForDatasetGroup( double &min, double &max, QgsMeshDataProvider *provider, int groupIndex );
//! Calculates min/max values for one dataset
static void calculateMinMaxForDataset( double &min, double &max, QgsMeshDataProvider *provider, QgsMeshDatasetIndex index );
};
///@endcond
#endif // QGSMESHLAYERUTILS_H

View File

@ -331,6 +331,7 @@ bool QgsMeshMemoryDataProvider::addDataset( const QString &uri )
if ( valid )
{
mExtraDatasetUris << uri;
emit datasetGroupsAdded( 1 );
emit dataChanged();
}

View File

@ -59,17 +59,6 @@ void QgsMeshRendererScalarSettings::setColorRampShader( const QgsColorRampShader
mColorRampShader = shader;
}
bool QgsMeshRendererScalarSettings::isEnabled() const
{
return mEnabled;
}
void QgsMeshRendererScalarSettings::setEnabled( bool enabled )
{
mEnabled = enabled;
}
double QgsMeshRendererVectorSettings::lineWidth() const
{
return mLineWidth;

View File

@ -76,12 +76,7 @@ class CORE_EXPORT QgsMeshRendererScalarSettings
//! Sets color ramp shader function
void setColorRampShader( const QgsColorRampShader &shader );
//! Returns whether color ramp has any items assigned
bool isEnabled() const;
void setEnabled( bool enabled );
private:
bool mEnabled = false;
QgsColorRampShader mColorRampShader;
};
@ -98,11 +93,6 @@ class CORE_EXPORT QgsMeshRendererVectorSettings
{
public:
//! Returns whether rendering of vectors is enabled
bool isEnabled() const { return mEnabled; }
//! Sets whether rendering of vectors is enabled
void setEnabled( bool enabled ) { mEnabled = enabled; }
//! Algorithm how to transform vector magnitude to length of arrow on the device in pixels
enum ArrowScalingMethod
{
@ -233,7 +223,6 @@ class CORE_EXPORT QgsMeshRendererVectorSettings
void setArrowHeadLengthRatio( double arrowHeadLengthRatio );
private:
bool mEnabled = false;
double mLineWidth = DEFAULT_LINE_WIDTH; //in milimeters
QColor mColor = Qt::black;
double mFilterMin = -1; //disabled
@ -274,14 +263,14 @@ class CORE_EXPORT QgsMeshRendererSettings
void setTriangularMeshSettings( const QgsMeshRendererMeshSettings &settings ) { mRendererTriangularMeshSettings = settings; }
//! Returns renderer settings
QgsMeshRendererScalarSettings scalarSettings() const { return mRendererScalarSettings; }
QgsMeshRendererScalarSettings scalarSettings( int groupIndex ) const { return mRendererScalarSettings.value( groupIndex ); }
//! Sets new renderer settings
void setScalarSettings( const QgsMeshRendererScalarSettings &settings ) { mRendererScalarSettings = settings; }
void setScalarSettings( int groupIndex, const QgsMeshRendererScalarSettings &settings ) { mRendererScalarSettings[groupIndex] = settings; }
//! Returns renderer settings
QgsMeshRendererVectorSettings vectorSettings() const { return mRendererVectorSettings; }
QgsMeshRendererVectorSettings vectorSettings( int groupIndex ) const { return mRendererVectorSettings.value( groupIndex ); }
//! Sets new renderer settings
void setVectorSettings( const QgsMeshRendererVectorSettings &settings ) { mRendererVectorSettings = settings; }
void setVectorSettings( int groupIndex, const QgsMeshRendererVectorSettings &settings ) { mRendererVectorSettings[groupIndex] = settings; }
//! Returns active scalar dataset
QgsMeshDatasetIndex activeScalarDataset() const { return mActiveScalarDataset; }
@ -296,8 +285,9 @@ class CORE_EXPORT QgsMeshRendererSettings
private:
QgsMeshRendererMeshSettings mRendererNativeMeshSettings;
QgsMeshRendererMeshSettings mRendererTriangularMeshSettings;
QgsMeshRendererScalarSettings mRendererScalarSettings;
QgsMeshRendererVectorSettings mRendererVectorSettings;
QHash<int, QgsMeshRendererScalarSettings> mRendererScalarSettings; //!< Per-group scalar settings
QHash<int, QgsMeshRendererVectorSettings> mRendererVectorSettings; //!< Per-group vector settings
//! index of active scalar dataset
QgsMeshDatasetIndex mActiveScalarDataset;

View File

@ -373,9 +373,9 @@ QList<QgsLayerTreeModelLegendNode *> QgsDefaultMeshLayerLegend::createLayerTreeM
nodes << new QgsSimpleLegendNode( nodeLayer, name );
QgsMeshRendererScalarSettings settings = rendererSettings.scalarSettings();
if ( settings.isEnabled() )
if ( indexScalar.isValid() )
{
QgsMeshRendererScalarSettings settings = rendererSettings.scalarSettings( indexScalar.group() );
QgsLegendColorList items;
settings.colorRampShader().legendSymbologyItems( items );
for ( const QPair< QString, QColor > &item : qgis::as_const( items ) )

View File

@ -635,6 +635,7 @@ void QgsColorRampShaderWidget::setFromShader( const QgsColorRampShader &colorRam
mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( colorRampShader.colorRampType() ) );
mColormapTreeWidget->clear();
const QList<QgsColorRampShader::ColorRampItem> colorRampItemList = colorRampShader.colorRampItemList();
QList<QgsColorRampShader::ColorRampItem>::const_iterator it = colorRampItemList.constBegin();
for ( ; it != colorRampItemList.end(); ++it )

View File

@ -114,6 +114,7 @@ bool QgsMdalProvider::addDataset( const QString &uri )
else
{
mExtraDatasetUris << uri;
emit datasetGroupsAdded( datasetGroupCount() - datasetCount );
emit dataChanged();
return true; // Ok
}

View File

@ -101,6 +101,15 @@ void TestQgsMeshRenderer::initTestCase()
QList<QgsMapLayer *>() << mMemoryLayer );
mMapSettings->setLayers(
QList<QgsMapLayer *>() << mMemoryLayer );
// here we check that datasets automatically get some default style applied
QgsMeshDatasetIndex ds( 0, 0 );
QgsMeshRendererScalarSettings scalarSettings = mMemoryLayer->rendererSettings().scalarSettings( ds.group() );
QgsColorRampShader shader = scalarSettings.colorRampShader();
QList<QgsColorRampShader::ColorRampItem> lst = shader.colorRampItemList();
QCOMPARE( lst.count(), 5 );
QCOMPARE( lst.at( 0 ).value, 1. ); // min group value
QCOMPARE( lst.at( 4 ).value, 4. ); // max group value
}
void TestQgsMeshRenderer::cleanupTestCase()
@ -174,9 +183,9 @@ void TestQgsMeshRenderer::test_vertex_vector_dataset_rendering()
QVERIFY( metadata.name() == "VertexVectorDataset" );
QgsMeshRendererSettings rendererSettings = mMemoryLayer->rendererSettings();
QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings();
QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( ds.group() );
settings.setMinShaftLength( 15 );
rendererSettings.setVectorSettings( settings );
rendererSettings.setVectorSettings( ds.group(), settings );
rendererSettings.setActiveVectorDataset( ds );
mMemoryLayer->setRendererSettings( rendererSettings );