Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[mesh] [bugfix] do not try to render NODATA values
  • Loading branch information
PeterPetrik authored and wonder-sk committed Jul 13, 2018
1 parent ade3325 commit be99819
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 8 deletions.
44 changes: 39 additions & 5 deletions src/core/mesh/qgsmeshlayerrenderer.cpp
Expand Up @@ -16,6 +16,7 @@
***************************************************************************/

#include <memory>
#include <limits>

#include "qgsmeshlayerrenderer.h"

Expand All @@ -34,6 +35,32 @@
#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() )
, mFeedback( new QgsMeshLayerRendererFeedback )
Expand Down Expand Up @@ -65,14 +92,10 @@ void QgsMeshLayerRenderer::assignDefaultScalarShader( )
if ( mScalarDatasetValues.isEmpty() || mRendererScalarSettings.isEnabled() )
return; // no need for default shader, either rendering is off or we already have some shader

auto bounds = std::minmax_element( mScalarDatasetValues.constBegin(), mScalarDatasetValues.constEnd() );
double vMin = *bounds.first;
double vMax = *bounds.second;

QgsSettings settings;
QString defaultPalette = settings.value( QStringLiteral( "/Raster/defaultPalette" ), "Spectral" ).toString();
std::unique_ptr<QgsColorRamp> colorRamp( QgsStyle::defaultStyle()->colorRamp( defaultPalette ) );
QgsColorRampShader fcn( vMin, vMax, colorRamp.release() );
QgsColorRampShader fcn( mScalarDatasetMinimum, mScalarDatasetMaximum, colorRamp.release() );
fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );

mRendererScalarSettings.setColorRampShader( fcn );
Expand Down Expand Up @@ -130,6 +153,8 @@ void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
double v = layer->dataProvider()->datasetValue( datasetIndex, i ).scalar();
mScalarDatasetValues[i] = v;
}

calculateMinimumMaximum( mScalarDatasetMinimum, mScalarDatasetMaximum, mScalarDatasetValues );
}
}

Expand Down Expand Up @@ -169,6 +194,8 @@ void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )
mVectorDatasetValuesMag[i] = mag;
}
}

calculateMinimumMaximum( mVectorDatasetMagMinimum, mVectorDatasetMagMaximum, mVectorDatasetValuesMag );
}
}

Expand Down Expand Up @@ -225,6 +252,9 @@ void QgsMeshLayerRenderer::renderScalarDataset()
if ( mScalarDatasetValues.isEmpty() )
return; // activeScalarDataset == NO_ACTIVE_MESH_DATASET

if ( std::isnan( mScalarDatasetMinimum ) || std::isnan( mScalarDatasetMaximum ) )
return; // only NODATA values

if ( !mRendererScalarSettings.isEnabled() )
return; // no shader

Expand All @@ -247,11 +277,15 @@ void QgsMeshLayerRenderer::renderVectorDataset()
if ( mVectorDatasetValuesX.isEmpty() )
return;

if ( std::isnan( mVectorDatasetMagMinimum ) || std::isnan( mVectorDatasetMagMaximum ) )
return; // only NODATA values

if ( mVectorDatasetValuesX.size() != mVectorDatasetValuesY.size() )
return;

QgsMeshVectorRenderer renderer( mTriangularMesh,
mVectorDatasetValuesX, mVectorDatasetValuesY, mVectorDatasetValuesMag,
mVectorDatasetMagMinimum, mVectorDatasetMagMaximum,
mVectorDataOnVertices, mRendererVectorSettings, mContext, mOutputSize );

renderer.draw();
Expand Down
5 changes: 5 additions & 0 deletions src/core/mesh/qgsmeshlayerrenderer.h
Expand Up @@ -24,6 +24,7 @@ class QgsSymbol;
#define SIP_NO_FILE

#include <memory>
#include <limits>

#include "qgis.h"

Expand Down Expand Up @@ -86,11 +87,15 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer
// copy of the scalar dataset
QVector<double> mScalarDatasetValues;
bool mScalarDataOnVertices = true;
double mScalarDatasetMinimum = std::numeric_limits<double>::quiet_NaN();
double mScalarDatasetMaximum = std::numeric_limits<double>::quiet_NaN();

// copy of the vector dataset
QVector<double> mVectorDatasetValuesX;
QVector<double> mVectorDatasetValuesY;
QVector<double> mVectorDatasetValuesMag;
double mVectorDatasetMagMinimum = std::numeric_limits<double>::quiet_NaN();
double mVectorDatasetMagMaximum = std::numeric_limits<double>::quiet_NaN();
bool mVectorDataOnVertices = true;

// copy from mesh layer
Expand Down
22 changes: 19 additions & 3 deletions src/core/mesh/qgsmeshvectorrenderer.cpp
Expand Up @@ -39,25 +39,35 @@ inline double mag( double input )
return 1.0;
}

inline bool nodataValue( double x, double y )
{
return ( std::isnan( x ) || std::isnan( y ) );
}

QgsMeshVectorRenderer::QgsMeshVectorRenderer( const QgsTriangularMesh &m,
const QVector<double> &datasetValuesX,
const QVector<double> &datasetValuesY,
const QVector<double> &datasetValuesMag,
double datasetMagMinimumValue,
double datasetMagMaximumValue,
bool dataIsOnVertices,
const QgsMeshRendererVectorSettings &settings,
QgsRenderContext &context, const QSize &size )
: mTriangularMesh( m )
, mDatasetValuesX( datasetValuesX )
, mDatasetValuesY( datasetValuesY )
, mDatasetValuesMag( datasetValuesMag )
, mMinMag( datasetMagMinimumValue )
, mMaxMag( datasetMagMaximumValue )
, mContext( context )
, mCfg( settings )
, mDataOnVertices( dataIsOnVertices )
, mOutputSize( size )
{
auto bounds = std::minmax_element( mDatasetValuesMag.constBegin(), mDatasetValuesMag.constEnd() );
mMinMag = *bounds.first;
mMaxMag = *bounds.second;
// should be checked in caller
Q_ASSERT( !mDatasetValuesMag.empty() );
Q_ASSERT( !std::isnan( mMinMag ) );
Q_ASSERT( !std::isnan( mMaxMag ) );
}

QgsMeshVectorRenderer::~QgsMeshVectorRenderer() = default;
Expand Down Expand Up @@ -192,6 +202,9 @@ void QgsMeshVectorRenderer::drawVectorDataOnVertices()

double xVal = mDatasetValuesX[i];
double yVal = mDatasetValuesY[i];
if ( nodataValue( xVal, yVal ) )
continue;

double V = mDatasetValuesMag[i]; // pre-calculated magnitude
QgsPointXY lineStart = mContext.mapToPixel().transform( vertex.x(), vertex.y() );

Expand All @@ -211,6 +224,9 @@ void QgsMeshVectorRenderer::drawVectorDataOnFaces()
QgsPointXY center = centroids.at( i );
double xVal = mDatasetValuesX[i];
double yVal = mDatasetValuesY[i];
if ( nodataValue( xVal, yVal ) )
continue;

double V = mDatasetValuesMag[i]; // pre-calculated magnitude
QgsPointXY lineStart = mContext.mapToPixel().transform( center.x(), center.y() );

Expand Down
2 changes: 2 additions & 0 deletions src/core/mesh/qgsmeshvectorrenderer.h
Expand Up @@ -49,6 +49,8 @@ class QgsMeshVectorRenderer
const QVector<double> &datasetValuesX,
const QVector<double> &datasetValuesY,
const QVector<double> &datasetValuesMag,
double datasetMagMaximumValue,
double datasetMagMinimumValue,
bool dataIsOnVertices,
const QgsMeshRendererVectorSettings &settings,
QgsRenderContext &context,
Expand Down

0 comments on commit be99819

Please sign in to comment.