Skip to content
Permalink
Browse files

Generate more descriptive legends for raster layers

- include band name details where its useful
- create a legend for multiband raster renderer
  • Loading branch information
nyalldawson committed Dec 16, 2020
1 parent d76ec1c commit 0d7b95fa67e4a1cf2b3102c709efc6d589ef52b4
@@ -121,6 +121,8 @@ Ownership of the enhancement is transferred.

virtual QList<int> usesBands() const;

virtual QList<QgsLayerTreeModelLegendNode *> createLegendNodes( QgsLayerTreeLayer *nodeLayer ) /Factory/;


virtual void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props = QgsStringMap() ) const;

@@ -88,6 +88,8 @@ Returns the raster band used for rendering the raster.

virtual QList< QPair< QString, QColor > > legendSymbologyItems() const;

virtual QList<QgsLayerTreeModelLegendNode *> createLegendNodes( QgsLayerTreeLayer *nodeLayer ) /Factory/;

virtual QList<int> usesBands() const;

virtual void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props = QgsStringMap() ) const;
@@ -148,6 +148,7 @@ Reload data (data could change)

virtual QString colorInterpretationName( int bandNo ) const;


virtual double bandScale( int bandNo ) const;
%Docstring
Read band scale for raster value
@@ -223,6 +223,20 @@ Gets raster size
virtual QString generateBandName( int bandNumber ) const;
%Docstring
helper function to create zero padded band names
%End

virtual QString colorInterpretationName( int bandNumber ) const;
%Docstring
Returns the name of the color interpretation for the specified ``bandNumber``.

.. versionadded:: 3.18
%End

QString displayBandName( int bandNumber ) const;
%Docstring
Generates a friendly, descriptive name for the specified ``bandNumber``.

.. versionadded:: 3.18
%End

virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback = 0 ) = 0 /Factory/;
@@ -19,6 +19,7 @@
#include "qgscontrastenhancement.h"
#include "qgsrastertransparency.h"
#include "qgsrasterviewport.h"
#include "qgslayertreemodellegendnode.h"

#include <QDomDocument>
#include <QDomElement>
@@ -418,6 +419,25 @@ QList<int> QgsMultiBandColorRenderer::usesBands() const
return bandList;
}

QList<QgsLayerTreeModelLegendNode *> QgsMultiBandColorRenderer::createLegendNodes( QgsLayerTreeLayer *nodeLayer )
{
QList<QgsLayerTreeModelLegendNode *> res;
if ( mRedBand != -1 )
{
res << new QgsRasterSymbolLegendNode( nodeLayer, QColor( 255, 0, 0 ), displayBandName( mRedBand ) );
}
if ( mGreenBand != -1 )
{
res << new QgsRasterSymbolLegendNode( nodeLayer, QColor( 0, 255, 0 ), displayBandName( mGreenBand ) );
}
if ( mBlueBand != -1 )
{
res << new QgsRasterSymbolLegendNode( nodeLayer, QColor( 0, 0, 255 ), displayBandName( mBlueBand ) );
}

return res;
}

void QgsMultiBandColorRenderer::toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
{
// create base structure
@@ -118,6 +118,7 @@ class CORE_EXPORT QgsMultiBandColorRenderer: public QgsRasterRenderer
void writeXml( QDomDocument &doc, QDomElement &parentElem ) const override;

QList<int> usesBands() const override;
QList<QgsLayerTreeModelLegendNode *> createLegendNodes( QgsLayerTreeLayer *nodeLayer ) SIP_FACTORY override;

void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props = QgsStringMap() ) const override;

@@ -22,6 +22,7 @@
#include "qgsstyleentityvisitor.h"
#include "qgsmessagelog.h"
#include "qgsrasteriterator.h"
#include "qgslayertreemodellegendnode.h"

#include <QColor>
#include <QDomDocument>
@@ -328,6 +329,28 @@ QList< QPair< QString, QColor > > QgsPalettedRasterRenderer::legendSymbologyItem
return symbolItems;
}


QList<QgsLayerTreeModelLegendNode *> QgsPalettedRasterRenderer::createLegendNodes( QgsLayerTreeLayer *nodeLayer )
{
QList<QgsLayerTreeModelLegendNode *> res;

const QString name = displayBandName( mBand );
if ( !name.isEmpty() )
{
res << new QgsSimpleLegendNode( nodeLayer, name );
}

const QList< QPair< QString, QColor > > items = legendSymbologyItems();
res.reserve( res.size() + items.size() );
for ( const QPair< QString, QColor > &item : items )
{
res << new QgsRasterSymbolLegendNode( nodeLayer, item.second, item.first );
}

return res;
}


QList<int> QgsPalettedRasterRenderer::usesBands() const
{
QList<int> bandList;
@@ -101,6 +101,7 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer

void writeXml( QDomDocument &doc, QDomElement &parentElem ) const override;
QList< QPair< QString, QColor > > legendSymbologyItems() const override;
QList<QgsLayerTreeModelLegendNode *> createLegendNodes( QgsLayerTreeLayer *nodeLayer ) SIP_FACTORY override;
QList<int> usesBands() const override;
void toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props = QgsStringMap() ) const override;
bool accept( QgsStyleEntityVisitorInterface *visitor ) const override;
@@ -247,6 +247,12 @@ QgsRasterDataProvider::ProviderCapabilities QgsRasterDataProvider::providerCapab
return QgsRasterDataProvider::NoProviderCapabilities;
}

int QgsRasterDataProvider::colorInterpretation( int bandNo ) const
{
Q_UNUSED( bandNo )
return QgsRaster::UndefinedColorInterpretation;
}

//
//Random Static convenience function
//
@@ -624,5 +630,7 @@ void QgsRasterDataProvider::writeXml( QDomDocument &doc, QDomElement &parentElem
QString::number( mMaxOversampling ) );
}


// ENDS
QString QgsRasterDataProvider::colorInterpretationName( int bandNo ) const
{
return colorName( colorInterpretation( bandNo ) );
}
@@ -152,11 +152,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
Qgis::DataType sourceDataType( int bandNo ) const override = 0;

//! Returns data type for the band specified by number
virtual int colorInterpretation( int bandNo ) const
{
Q_UNUSED( bandNo )
return QgsRaster::UndefinedColorInterpretation;
}
virtual int colorInterpretation( int bandNo ) const;

QString colorName( int colorInterpretation ) const
{
@@ -221,10 +217,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
//! Reload data (data could change)
virtual bool reload() { return true; }

virtual QString colorInterpretationName( int bandNo ) const
{
return colorName( colorInterpretation( bandNo ) );
}
QString colorInterpretationName( int bandNo ) const override;

/**
* Read band scale for raster value
@@ -616,3 +616,30 @@ QString QgsRasterInterface::capabilitiesString() const

return abilitiesList.join( QLatin1String( ", " ) );
}

QString QgsRasterInterface::generateBandName( int bandNumber ) const
{
if ( mInput )
return mInput->generateBandName( bandNumber );

return tr( "Band" ) + QStringLiteral( " %1" ) .arg( bandNumber, 1 + static_cast< int >( std::log10( static_cast< double >( bandCount() ) ) ), 10, QChar( '0' ) );
}

QString QgsRasterInterface::colorInterpretationName( int bandNo ) const
{
if ( mInput )
return mInput->colorInterpretationName( bandNo );

return QString();
}

QString QgsRasterInterface::displayBandName( int bandNumber ) const
{
QString name = generateBandName( bandNumber );
QString colorInterp = colorInterpretationName( bandNumber );
if ( colorInterp != QLatin1String( "Undefined" ) )
{
name.append( QStringLiteral( " (%1)" ).arg( colorInterp ) );
}
return name;
}
@@ -242,10 +242,21 @@ class CORE_EXPORT QgsRasterInterface
virtual int ySize() const { return mInput ? mInput->ySize() : 0; }

//! \brief helper function to create zero padded band names
virtual QString generateBandName( int bandNumber ) const
{
return tr( "Band" ) + QStringLiteral( " %1" ) .arg( bandNumber, 1 + static_cast< int >( std::log10( static_cast< double >( bandCount() ) ) ), 10, QChar( '0' ) );
}
virtual QString generateBandName( int bandNumber ) const;

/**
* Returns the name of the color interpretation for the specified \a bandNumber.
*
* \since QGIS 3.18
*/
virtual QString colorInterpretationName( int bandNumber ) const;

/**
* Generates a friendly, descriptive name for the specified \a bandNumber.
*
* \since QGIS 3.18
*/
QString displayBandName( int bandNumber ) const;

/**
* Read block of data using given extent and size.
@@ -217,6 +217,12 @@ QList<QgsLayerTreeModelLegendNode *> QgsSingleBandGrayRenderer::createLegendNode
QList<QgsLayerTreeModelLegendNode *> res;
if ( mContrastEnhancement && mContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement )
{
const QString name = displayBandName( mGrayBand );
if ( !name.isEmpty() )
{
res << new QgsSimpleLegendNode( nodeLayer, name );
}

const QColor minColor = ( mGradient == BlackToWhite ) ? Qt::black : Qt::white;
const QColor maxColor = ( mGradient == BlackToWhite ) ? Qt::white : Qt::black;
res << new QgsColorRampLegendNode( nodeLayer, new QgsGradientColorRamp( minColor, maxColor ),
@@ -431,6 +431,13 @@ QList<QgsLayerTreeModelLegendNode *> QgsSingleBandPseudoColorRenderer::createLeg
return QList<QgsLayerTreeModelLegendNode *>();

QList<QgsLayerTreeModelLegendNode *> res;

const QString name = displayBandName( mBand );
if ( !name.isEmpty() )
{
res << new QgsSimpleLegendNode( nodeLayer, name );
}

switch ( rampShader->colorRampType() )
{
case QgsColorRampShader::Interpolated:
@@ -166,12 +166,5 @@ QString QgsRasterBandComboBox::displayBandName( QgsRasterDataProvider *provider,
if ( !provider )
return QString();

QString name = provider->generateBandName( band );

QString colorInterp = provider->colorInterpretationName( band );
if ( colorInterp != QLatin1String( "Undefined" ) )
{
name.append( QStringLiteral( " (%1)" ).arg( colorInterp ) );
}
return name;
return provider->displayBandName( band );
}
@@ -119,7 +119,30 @@ static bool _verifyImage( const QString &testName, QString &report, int diff = 3
return equal;
}

class TestRasterRenderer : public QgsPalettedRasterRenderer
{
public:

TestRasterRenderer( QgsRasterInterface *input, int bandNumber, const ClassData &classes )
: QgsPalettedRasterRenderer( input, bandNumber, classes )
{}

// don't create the default legend nodes for this layer!
QList<QgsLayerTreeModelLegendNode *> createLegendNodes( QgsLayerTreeLayer *nodeLayer ) override
{
QList<QgsLayerTreeModelLegendNode *> res;

const QList< QPair< QString, QColor > > items = legendSymbologyItems();
res.reserve( res.size() + items.size() );
for ( const QPair< QString, QColor > &item : items )
{
res << new QgsRasterSymbolLegendNode( nodeLayer, item.second, item.first );
}

return res;
}

};

class TestQgsLegendRenderer : public QObject
{
@@ -263,7 +286,7 @@ void TestQgsLegendRenderer::init()
QString rasterUri = QStringLiteral( "MEM:::DATAPOINTER=%1,PIXELS=2,LINES=2" ).arg( ( qulonglong ) RASTER_ARRAY );
mRL = new QgsRasterLayer( rasterUri, QStringLiteral( "Raster Layer" ), QStringLiteral( "gdal" ) );

std::unique_ptr< QgsPalettedRasterRenderer > rasterRenderer( new QgsPalettedRasterRenderer( mRL->dataProvider(), 1,
std::unique_ptr< TestRasterRenderer > rasterRenderer( new TestRasterRenderer( mRL->dataProvider(), 1,
{
QgsPalettedRasterRenderer::Class( 1, QColor( 0, 0, 0 ), QStringLiteral( "1" ) ),
QgsPalettedRasterRenderer::Class( 2, QColor( 255, 255, 255 ), QStringLiteral( "2" ) )

0 comments on commit 0d7b95f

Please sign in to comment.
You can’t perform that action at this time.