Skip to content

Commit

Permalink
Cleanup duplicate code and add tests for graduated range resolving
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Nov 11, 2019
1 parent 5eeba90 commit 06f36dd
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 12 deletions.
Expand Up @@ -497,6 +497,14 @@ Will return ``None`` if the functionality is disabled.
Updates the labels of the ranges

.. versionadded:: 3.10
%End

const QgsRendererRange *rangeForValue( double value ) const;
%Docstring
Returns the renderer range matching the provided ``value``, or ``None`` if no
range matches the value.

.. versionadded:: 3.10.1
%End

protected:
Expand Down
27 changes: 16 additions & 11 deletions src/core/symbology/qgsgraduatedsymbolrenderer.cpp
Expand Up @@ -17,6 +17,7 @@
#include <QDomElement>

#include <ctime>
#include <cmath>

#include "qgsgraduatedsymbolrenderer.h"

Expand Down Expand Up @@ -70,14 +71,15 @@ QgsGraduatedSymbolRenderer::~QgsGraduatedSymbolRenderer()
mRanges.clear(); // should delete all the symbols
}

QgsSymbol *QgsGraduatedSymbolRenderer::symbolForValue( double value ) const

const QgsRendererRange *QgsGraduatedSymbolRenderer::rangeForValue( double value ) const
{
for ( const QgsRendererRange &range : mRanges )
{
if ( range.lowerValue() <= value && range.upperValue() >= value )
{
if ( range.renderState() || mCounting )
return range.symbol();
return &range;
else
return nullptr;
}
Expand All @@ -86,21 +88,25 @@ QgsSymbol *QgsGraduatedSymbolRenderer::symbolForValue( double value ) const
return nullptr;
}

QgsSymbol *QgsGraduatedSymbolRenderer::symbolForValue( double value ) const
{
if ( const QgsRendererRange *range = rangeForValue( value ) )
return range->symbol();
return nullptr;
}

QString QgsGraduatedSymbolRenderer::legendKeyForValue( double value ) const
{
int i = 0;
for ( const QgsRendererRange &range : mRanges )
if ( const QgsRendererRange *matchingRange = rangeForValue( value ) )
{
if ( range.lowerValue() <= value && range.upperValue() >= value )
int i = 0;
for ( const QgsRendererRange &range : mRanges )
{
if ( range.renderState() || mCounting )
if ( matchingRange == &range )
return QString::number( i );
else
return QString();
i++;
}
i++;
}
// the value is out of the range: return NULL
return QString();
}

Expand Down Expand Up @@ -1054,7 +1060,6 @@ void QgsGraduatedSymbolRenderer::updateRangeLabels()
}
}


void QgsGraduatedSymbolRenderer::calculateLabelPrecision( bool updateRanges )
{
// Find the minimum size of a class
Expand Down
11 changes: 11 additions & 0 deletions src/core/symbology/qgsgraduatedsymbolrenderer.h
Expand Up @@ -429,6 +429,14 @@ class CORE_EXPORT QgsGraduatedSymbolRenderer : public QgsFeatureRenderer
*/
void updateRangeLabels();

/**
* Returns the renderer range matching the provided \a value, or NULLPTR if no
* range matches the value.
*
* \since QGIS 3.10.1
*/
const QgsRendererRange *rangeForValue( double value ) const;

protected:
QString mAttrName;
QgsRangeList mRanges;
Expand Down Expand Up @@ -479,6 +487,9 @@ class CORE_EXPORT QgsGraduatedSymbolRenderer : public QgsFeatureRenderer
QgsGraduatedSymbolRenderer( const QgsGraduatedSymbolRenderer & );
QgsGraduatedSymbolRenderer &operator=( const QgsGraduatedSymbolRenderer & );
#endif

friend class TestQgsGraduatedSymbolRenderer;

};

#endif // QGSGRADUATEDSYMBOLRENDERER_H
97 changes: 96 additions & 1 deletion tests/src/core/testqgsgraduatedsymbolrenderer.cpp
Expand Up @@ -21,6 +21,8 @@
#include "qgsgraduatedsymbolrenderer.h"
#include "qgsclassificationequalinterval.h"
#include "qgssymbollayerutils.h"
#include "qgsvectorlayer.h"
#include "qgsclassificationquantile.h"

/**
* \ingroup UnitTests
Expand All @@ -39,7 +41,7 @@ class TestQgsGraduatedSymbolRenderer: public QObject
void rangesOverlap();
void rangesHaveGaps();
void classifySymmetric();

void testMatchingRangeForValue();

private:
};
Expand Down Expand Up @@ -216,5 +218,98 @@ void TestQgsGraduatedSymbolRenderer::classifySymmetric()
}
}

void TestQgsGraduatedSymbolRenderer::testMatchingRangeForValue()
{
QgsGraduatedSymbolRenderer renderer;
//test with no ranges
QVERIFY( !renderer.rangeForValue( 1 ) );
QVERIFY( !renderer.rangeForValue( 12 ) );
QVERIFY( !renderer.rangeForValue( -1 ) );
QVERIFY( !renderer.symbolForValue( 1 ) );
QVERIFY( renderer.legendKeyForValue( 1 ).isEmpty() );

QgsMarkerSymbol ms;
ms.setColor( QColor( 255, 0, 0 ) );
QgsRendererRange r1( 1.1, 3.2, ms.clone(), QStringLiteral( "r1" ) );
renderer.addClass( r1 );

QVERIFY( !renderer.rangeForValue( 1 ) );
QVERIFY( !renderer.rangeForValue( 12 ) );
QVERIFY( !renderer.rangeForValue( -1 ) );
QCOMPARE( renderer.rangeForValue( 1.1 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 2.1 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 3.2 )->label(), QStringLiteral( "r1" ) );
QVERIFY( !renderer.symbolForValue( 1 ) );
QCOMPARE( renderer.symbolForValue( 2.1 )->color().name(), QStringLiteral( "#ff0000" ) );
QVERIFY( renderer.legendKeyForValue( 1 ).isEmpty() );
QCOMPARE( renderer.legendKeyForValue( 2.1 ), QStringLiteral( "0" ) );

ms.setColor( QColor( 255, 255, 0 ) );
QgsRendererRange r2( 3.2, 3.3, ms.clone(), QStringLiteral( "r2" ) );
renderer.addClass( r2 );

QVERIFY( !renderer.rangeForValue( 1 ) );
QVERIFY( !renderer.rangeForValue( 12 ) );
QVERIFY( !renderer.rangeForValue( -1 ) );
QCOMPARE( renderer.rangeForValue( 1.1 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 2.1 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 3.2 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 3.25 )->label(), QStringLiteral( "r2" ) );
QCOMPARE( renderer.rangeForValue( 3.3 )->label(), QStringLiteral( "r2" ) );
QVERIFY( !renderer.symbolForValue( 1 ) );
QCOMPARE( renderer.symbolForValue( 2.1 )->color().name(), QStringLiteral( "#ff0000" ) );
QCOMPARE( renderer.symbolForValue( 3.25 )->color().name(), QStringLiteral( "#ffff00" ) );
QVERIFY( renderer.legendKeyForValue( 1 ).isEmpty() );
QCOMPARE( renderer.legendKeyForValue( 2.1 ), QStringLiteral( "0" ) );
QCOMPARE( renderer.legendKeyForValue( 3.25 ), QStringLiteral( "1" ) );

// disabled range
ms.setColor( QColor( 255, 0, 255 ) );
QgsRendererRange r3( 3.3, 3.6, ms.clone(), QStringLiteral( "r3" ), false );
renderer.addClass( r3 );
QVERIFY( !renderer.rangeForValue( 1 ) );
QVERIFY( !renderer.rangeForValue( 12 ) );
QVERIFY( !renderer.rangeForValue( -1 ) );
QCOMPARE( renderer.rangeForValue( 1.1 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 2.1 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 3.2 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 3.25 )->label(), QStringLiteral( "r2" ) );
QCOMPARE( renderer.rangeForValue( 3.3 )->label(), QStringLiteral( "r2" ) );
QVERIFY( !renderer.rangeForValue( 3.5 ) );
QVERIFY( !renderer.symbolForValue( 1 ) );
QCOMPARE( renderer.symbolForValue( 2.1 )->color().name(), QStringLiteral( "#ff0000" ) );
QCOMPARE( renderer.symbolForValue( 3.25 )->color().name(), QStringLiteral( "#ffff00" ) );
QVERIFY( !renderer.symbolForValue( 3.5 ) );
QVERIFY( renderer.legendKeyForValue( 1 ).isEmpty() );
QCOMPARE( renderer.legendKeyForValue( 2.1 ), QStringLiteral( "0" ) );
QCOMPARE( renderer.legendKeyForValue( 3.25 ), QStringLiteral( "1" ) );
QVERIFY( renderer.legendKeyForValue( 3.5 ).isEmpty() );

// zero width range
ms.setColor( QColor( 0, 255, 255 ) );
QgsRendererRange r4( 3.7, 3.7, ms.clone(), QStringLiteral( "r4" ) );
renderer.addClass( r4 );
QVERIFY( !renderer.rangeForValue( 1 ) );
QVERIFY( !renderer.rangeForValue( 12 ) );
QVERIFY( !renderer.rangeForValue( -1 ) );
QCOMPARE( renderer.rangeForValue( 1.1 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 2.1 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 3.2 )->label(), QStringLiteral( "r1" ) );
QCOMPARE( renderer.rangeForValue( 3.25 )->label(), QStringLiteral( "r2" ) );
QCOMPARE( renderer.rangeForValue( 3.3 )->label(), QStringLiteral( "r2" ) );
QCOMPARE( renderer.rangeForValue( 3.7 )->label(), QStringLiteral( "r4" ) );
QVERIFY( !renderer.rangeForValue( 3.5 ) );
QVERIFY( !renderer.symbolForValue( 1 ) );
QCOMPARE( renderer.symbolForValue( 2.1 )->color().name(), QStringLiteral( "#ff0000" ) );
QCOMPARE( renderer.symbolForValue( 3.25 )->color().name(), QStringLiteral( "#ffff00" ) );
QCOMPARE( renderer.symbolForValue( 3.7 )->color().name(), QStringLiteral( "#00ffff" ) );
QVERIFY( !renderer.symbolForValue( 3.5 ) );
QVERIFY( renderer.legendKeyForValue( 1 ).isEmpty() );
QCOMPARE( renderer.legendKeyForValue( 2.1 ), QStringLiteral( "0" ) );
QCOMPARE( renderer.legendKeyForValue( 3.25 ), QStringLiteral( "1" ) );
QCOMPARE( renderer.legendKeyForValue( 3.7 ), QStringLiteral( "3" ) );
QVERIFY( renderer.legendKeyForValue( 3.5 ).isEmpty() );
}

QGSTEST_MAIN( TestQgsGraduatedSymbolRenderer )
#include "testqgsgraduatedsymbolrenderer.moc"

0 comments on commit 06f36dd

Please sign in to comment.