From 721d9f59086a15f41f36496a7c7d34251e7ba7c4 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 30 Apr 2015 06:26:20 +1000 Subject: [PATCH] Formatting and code cleanups for QgsScaleExpression --- python/core/core.sip | 1 + python/core/qgsscaleexpression.sip | 82 +++++++++++ src/core/qgsscaleexpression.cpp | 160 +++++++++++++--------- src/core/qgsscaleexpression.h | 112 ++++++++++----- tests/src/core/testqgsscaleexpression.cpp | 45 ++---- 5 files changed, 277 insertions(+), 123 deletions(-) create mode 100644 python/core/qgsscaleexpression.sip diff --git a/python/core/core.sip b/python/core/core.sip index 2d9ee357738..bb215397e2d 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -97,6 +97,7 @@ %Include qgsrendercontext.sip %Include qgsrunprocess.sip %Include qgsscalecalculator.sip +%Include qgsscaleexpression.sip %Include qgsscaleutils.sip %Include qgssimplifymethod.sip %Include qgssnapper.sip diff --git a/python/core/qgsscaleexpression.sip b/python/core/qgsscaleexpression.sip new file mode 100644 index 00000000000..d620a250914 --- /dev/null +++ b/python/core/qgsscaleexpression.sip @@ -0,0 +1,82 @@ +/** \ingroup core +* \class QgsScaleExpression +* \brief Class storing parameters of a scale expression, which is a subclass of +* QgsExpression for expressions which return a size or width. +* \note Added in version 2.9 +*/ + +class QgsScaleExpression : QgsExpression +{ +%TypeHeaderCode +#include +%End + + public: + + enum Type + { + Linear, + Area, + Flannery, + Unknown + }; + + /** Constructor for QgsScaleExpression which parses an expression string + * to determine whether it's a scale expression + * @param expression expression string + */ + QgsScaleExpression( const QString &expression ); + + /** Constructor for QgsScaleExpression which creates an expression from + * specified parameters + * @param type scale method + * @param baseExpression expression (or field) used for value + * @param minValue minimum value, corresponds to specified minimum size + * @param maxValue maximum value, corresponds to specified maximum size + * @param minSize minimum size + * @param maxSize maximum size + */ + QgsScaleExpression( Type type, const QString& baseExpression, double minValue, double maxValue, double minSize, double maxSize ); + + operator bool() const; + + /** Calculates the size corresponding to a specific value. + * @param value + * @returns calculated size using expression's parameters and type + */ + double size( double value ) const; + + /** Returns the minimum size calculated by the expression + * @see maxSize + */ + double minSize() const; + + /** Returns the maximum size calculated by the expression + * @see minSize + */ + double maxSize() const; + + /** Returns the minimum value expected by the expression. The minimum + * value corresponds to the expression's minimum size. + * @see maxValue + */ + double minValue() const; + + /** Returns the maximum value expected by the expression. The maximum + * value corresponds to the expression's maximum size. + * @see minValue + */ + double maxValue() const; + + /** Returns the base expression string (or field reference) used for + * calculating the values to be mapped to a size. + */ + QString baseExpression() const; + + /** Returns the scale expression's type (method used to calculate + * the size from a value). + */ + Type type() const; + +}; + diff --git a/src/core/qgsscaleexpression.cpp b/src/core/qgsscaleexpression.cpp index d452a3f106e..fc4b4f1936c 100644 --- a/src/core/qgsscaleexpression.cpp +++ b/src/core/qgsscaleexpression.cpp @@ -1,9 +1,8 @@ - /*************************************************************************** qgsscaleexpression.cpp --------------------- - begin : November 2015 - copyright : (C) 2015 by Vincent Mora + begin : November 2014 + copyright : (C) 2014 by Vincent Mora email : vincent dor mora at oslandia dot com *************************************************************************** * * @@ -15,90 +14,127 @@ ***************************************************************************/ #include "qgsscaleexpression.h" - +#include "qgis.h" #include #include +QgsScaleExpression::QgsScaleExpression( const QString& expression ) + : QgsExpression( expression ) + , mType( Unknown ) + , mMinSize( 0 ) + , mMaxSize( 10 ) + , mMinValue( 0 ) + , mMaxValue( 100 ) +{ + init(); +} + +QgsScaleExpression::QgsScaleExpression( Type type, const QString& baseExpression, double minValue, double maxValue, double minSize, double maxSize ) + : QgsExpression( createExpression( type, baseExpression, minValue, maxValue, minSize, maxSize ) ) + , mExpression( baseExpression ) + , mType( type ) + , mMinSize( minSize ) + , mMaxSize( maxSize ) + , mMinValue( minValue ) + , mMaxValue( maxValue ) +{ + +} + void QgsScaleExpression::init() { bool ok; - if ( rootNode() ) + if ( !rootNode() ) + return; + + const NodeFunction * f = dynamic_cast( rootNode() ); + if ( !f ) + return; + + QList args = f->args()->list(); + + if ( "scale_linear" == Functions()[f->fnIndex()]->name() ) { - const NodeFunction * f = dynamic_cast( rootNode() ); - if ( f ) + mType = Linear; + } + else if ( "scale_exp" == Functions()[f->fnIndex()]->name() ) + { + const double exp = QgsExpression( args[5]->dump() ).evaluate().toDouble( &ok ); + if ( ! ok ) + return; + if ( qgsDoubleNear( exp, 0.57, 0.001 ) ) + mType = Flannery; + else if ( qgsDoubleNear( exp, 0.5, 0.001 ) ) + mType = Area; + else { - QList args = f->args()->list(); - if ( "scale_linear" == Functions()[f->fnIndex()]->name() ) - { - mType = Linear; - } - if ( "scale_exp" == Functions()[f->fnIndex()]->name() ) - { - const double exp = QgsExpression( args[5]->dump() ).evaluate().toDouble( &ok ); - if ( ! ok ) return; - if ( qAbs( exp - .57 ) < .001 ) mType = Flannery; - else if ( qAbs( exp - .5 ) < .001 ) mType = Area; - else return; - } - mMinValue = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok ); - if ( ! ok ) return; - mMaxValue = QgsExpression( args[2]->dump() ).evaluate().toDouble( &ok ); - if ( ! ok ) return; - mMinSize = QgsExpression( args[3]->dump() ).evaluate().toDouble( &ok ); - if ( ! ok ) return; - mMaxSize = QgsExpression( args[4]->dump() ).evaluate().toDouble( &ok ); - if ( ! ok ) return; - mExpression = args[0]->dump(); + mType = Unknown; + return; } } -} + else + { + mType = Unknown; + return; + } -QgsScaleExpression::QgsScaleExpression( const QString & expr ) - : QgsExpression( expr ) -{ - init(); -} + bool expOk = true; + mMinValue = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok ); + expOk &= ok; + mMaxValue = QgsExpression( args[2]->dump() ).evaluate().toDouble( &ok ); + expOk &= ok; + mMinSize = QgsExpression( args[3]->dump() ).evaluate().toDouble( &ok ); + expOk &= ok; + mMaxSize = QgsExpression( args[4]->dump() ).evaluate().toDouble( &ok ); + expOk &= ok; -QgsScaleExpression::QgsScaleExpression( Type type, const QString & baseExpr, double minValue, double maxValue, double minSize, double maxSize ) - : QgsExpression( createExpression( type, baseExpr, minValue, maxValue, minSize, maxSize ) ) -{ - init(); + if ( !expOk ) + { + mType = Unknown; + return; + } + mExpression = args[0]->dump(); } QString QgsScaleExpression::createExpression( Type type, const QString & baseExpr, double minValue, double maxValue, double minSize, double maxSize ) { + QString minValueString = QString::number( minValue ); + QString maxValueString = QString::number( maxValue ); + QString minSizeString = QString::number( minSize ); + QString maxSizeString = QString::number( maxSize ); + switch ( type ) { case Linear: - return "scale_linear(" + baseExpr - + ", " + QString::number( minValue ) - + ", " + QString::number( maxValue ) - + ", " + QString::number( minSize ) - + ", " + QString::number( maxSize ) + ")"; - case Area: - return "scale_exp(" + baseExpr - + ", " + QString::number( minValue ) - + ", " + QString::number( maxValue ) - + ", " + QString::number( minSize ) - + ", " + QString::number( maxSize ) + ", .5)"; - case Flannery: - return "scale_exp(" + baseExpr - + ", " + QString::number( minValue ) - + ", " + QString::number( maxValue ) - + ", " + QString::number( minSize ) - + ", " + QString::number( maxSize ) + ", .57)"; - } - return ""; -} + return QString( "scale_linear(%1,%2,%3,%4,%5)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString ); + case Area: + return QString( "scale_exp(%1,%2,%3,%4,%5, 0.5)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString ); + + case Flannery: + return QString( "scale_exp(%1,%2,%3,%4,%5, 0.57)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString ); + + case Unknown: + break; + } + return QString(); +} double QgsScaleExpression::size( double value ) const { switch ( mType ) { - case Linear: return mMinSize + ( qBound( mMinValue, value, mMaxValue ) - mMinValue ) * ( mMaxSize - mMinSize ) / ( mMaxValue - mMinValue ); - case Area: return qPow( qBound( mMinValue, value, mMaxValue ) - mMinValue, .5 ) * ( mMaxSize - mMinSize ) / qPow( mMaxValue - mMinValue, .5 ); - case Flannery: return qPow( qBound( mMinValue, value, mMaxValue ) - mMinValue, .57 ) * ( mMaxSize - mMinSize ) / qPow( mMaxValue - mMinValue, .57 ); + case Linear: + return mMinSize + ( qBound( mMinValue, value, mMaxValue ) - mMinValue ) * ( mMaxSize - mMinSize ) / ( mMaxValue - mMinValue ); + + case Area: + return mMinSize + qPow( qBound( mMinValue, value, mMaxValue ) - mMinValue, .5 ) * ( mMaxSize - mMinSize ) / qPow( mMaxValue - mMinValue, .5 ); + + case Flannery: + return mMinSize + qPow( qBound( mMinValue, value, mMaxValue ) - mMinValue, .57 ) * ( mMaxSize - mMinSize ) / qPow( mMaxValue - mMinValue, .57 ); + + case Unknown: + break; } return 0; } diff --git a/src/core/qgsscaleexpression.h b/src/core/qgsscaleexpression.h index 17d9b2799a6..fb3182357b1 100644 --- a/src/core/qgsscaleexpression.h +++ b/src/core/qgsscaleexpression.h @@ -1,9 +1,8 @@ - /*************************************************************************** qgsscaleexpression.h --------------------- - begin : November 2015 - copyright : (C) 2015 by Vincent Mora + begin : November 2014 + copyright : (C) 2014 by Vincent Mora email : vincent dor mora at oslandia dot com *************************************************************************** * * @@ -13,47 +12,98 @@ * (at your option) any later version. * * * ***************************************************************************/ + #ifndef QGSSCALEEXPRESSION_H #define QGSSCALEEXPRESSION_H #include "qgsexpression.h" -//! Class to retrieve parameters of a -//! scale expression (size or width) -//! -//! It derives from QgsExpression, +/** \ingroup core +* \class QgsScaleExpression +* \brief Class storing parameters of a scale expression, which is a subclass of +* QgsExpression for expressions which return a size or width. +* \note Added in version 2.9 +*/ + class QgsScaleExpression: public QgsExpression { -public: - enum Type {Linear, Area, Flannery}; + public: - //! parse string like an expression and - //! detemine if it's a size expression - QgsScaleExpression( const QString & expr ); + enum Type + { + Linear, + Area, + Flannery, + Unknown + }; - //! setup expression from parameters - QgsScaleExpression( Type type, const QString & baseExpr, double minValue, double maxValue, double minSize, double maxSize ); + /** Constructor for QgsScaleExpression which parses an expression string + * to determine whether it's a scale expression + * @param expression expression string + */ + QgsScaleExpression( const QString &expression ); - operator bool() const { return ! mExpression.isEmpty(); } - double size( double value ) const; + /** Constructor for QgsScaleExpression which creates an expression from + * specified parameters + * @param type scale method + * @param baseExpression expression (or field) used for value + * @param minValue minimum value, corresponds to specified minimum size + * @param maxValue maximum value, corresponds to specified maximum size + * @param minSize minimum size + * @param maxSize maximum size + */ + QgsScaleExpression( Type type, const QString& baseExpression, double minValue, double maxValue, double minSize, double maxSize ); - double minSize() const { return mMinSize; } - double maxSize() const { return mMaxSize; } - double minValue() const { return mMinValue; } - double maxValue() const { return mMaxValue; } - QString baseExpression() const { return mExpression; } - Type type() const { return mType; } + operator bool() const { return ! mExpression.isEmpty(); } -private: - QString mExpression; - Type mType; - double mMinSize; - double mMaxSize; - double mMinValue; - double mMaxValue; + /** Calculates the size corresponding to a specific value. + * @param value + * @returns calculated size using expression's parameters and type + */ + double size( double value ) const; - void init(); - static QString createExpression( Type type, const QString & baseExpr, double minValue, double maxValue, double minSize, double maxSize ); + /** Returns the minimum size calculated by the expression + * @see maxSize + */ + double minSize() const { return mMinSize; } + + /** Returns the maximum size calculated by the expression + * @see minSize + */ + double maxSize() const { return mMaxSize; } + + /** Returns the minimum value expected by the expression. The minimum + * value corresponds to the expression's minimum size. + * @see maxValue + */ + double minValue() const { return mMinValue; } + + /** Returns the maximum value expected by the expression. The maximum + * value corresponds to the expression's maximum size. + * @see minValue + */ + double maxValue() const { return mMaxValue; } + + /** Returns the base expression string (or field reference) used for + * calculating the values to be mapped to a size. + */ + QString baseExpression() const { return mExpression; } + + /** Returns the scale expression's type (method used to calculate + * the size from a value). + */ + Type type() const { return mType; } + + private: + QString mExpression; + Type mType; + double mMinSize; + double mMaxSize; + double mMinValue; + double mMaxValue; + + void init(); + static QString createExpression( Type type, const QString& baseExpr, double minValue, double maxValue, double minSize, double maxSize ); }; diff --git a/tests/src/core/testqgsscaleexpression.cpp b/tests/src/core/testqgsscaleexpression.cpp index 13d4b5a2d6b..350ced7a8f2 100644 --- a/tests/src/core/testqgsscaleexpression.cpp +++ b/tests/src/core/testqgsscaleexpression.cpp @@ -1,9 +1,9 @@ /*************************************************************************** - test_template.cpp - -------------------------------------- - Date : Sun Sep 16 12:22:23 AKDT 2007 - Copyright : (C) 2007 by Gary E. Sherman - Email : sherman at mrcc dot com + testqgsscaleexpression.cpp + -------------------------- + begin : November 2014 + copyright : (C) 2014 by Vincent Mora + email : vincent dor mora at oslandia dot com *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * @@ -12,20 +12,13 @@ * (at your option) any later version. * * * ***************************************************************************/ + #include #include #include #include -#include -#include -#include -//header for class being tested #include -#include -#include -#include -#include #if QT_VERSION < 0x40701 // See http://hub.qgis.org/issues/4284 @@ -37,23 +30,8 @@ class TestQgsScaleExpression: public QObject Q_OBJECT private slots: - void initTestCase() - { - // - // Runs once before any tests are run - // - // init QGIS's paths - true means that all path will be inited from prefix - QgsApplication::init(); - QgsApplication::initQgis(); - // Will make sure the settings dir with the style file for color ramp is created - QgsApplication::createDB(); - QgsApplication::showSettings(); - } - - void cleanupTestCase() - { - QgsApplication::exitQgis(); - } + void initTestCase() {} + void cleanupTestCase() {} void parsing() { @@ -80,11 +58,18 @@ class TestQgsScaleExpression: public QObject { QgsScaleExpression exp( "scale_exp(column, 1, 7, 2, 10, 0.51)" ); QCOMPARE( bool(exp), false ); + QCOMPARE( exp.type(), QgsScaleExpression::Unknown ); } { QgsScaleExpression exp( "scale_exp(column, 1, 7, a, 10, 0.5)" ); QCOMPARE( bool(exp), false ); + QCOMPARE( exp.type(), QgsScaleExpression::Unknown ); } + { + QgsScaleExpression exp( "scale_exp(column, 1, 7)" ); + QCOMPARE( bool(exp), false ); + QCOMPARE( exp.type(), QgsScaleExpression::Unknown ); + } { QgsScaleExpression exp( QgsScaleExpression::Linear, "column", 1, 7, 2, 10 ); QCOMPARE( bool(exp), true );