Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Formatting and code cleanups for QgsScaleExpression
  • Loading branch information
nyalldawson committed Apr 29, 2015
1 parent 70b91b6 commit 721d9f5
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 126 deletions.
1 change: 1 addition & 0 deletions python/core/core.sip
Expand Up @@ -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
Expand Down
82 changes: 82 additions & 0 deletions 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 <qgsscaleexpression.h>
%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;

};

154 changes: 95 additions & 59 deletions 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
***************************************************************************
* *
Expand All @@ -15,90 +14,127 @@
***************************************************************************/

#include "qgsscaleexpression.h"

#include "qgis.h"
#include <QStringList>
#include <qmath.h>

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<const NodeFunction*>( rootNode() );
if ( !f )
return;

QList<Node*> args = f->args()->list();

if ( "scale_linear" == Functions()[f->fnIndex()]->name() )
{
const NodeFunction * f = dynamic_cast<const NodeFunction*>( 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<Node*> 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 ) + ")";
return QString( "scale_linear(%1,%2,%3,%4,%5)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString );

case Area:
return "scale_exp(" + baseExpr
+ ", " + QString::number( minValue )
+ ", " + QString::number( maxValue )
+ ", " + QString::number( minSize )
+ ", " + QString::number( maxSize ) + ", .5)";
return QString( "scale_exp(%1,%2,%3,%4,%5, 0.5)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString );

case Flannery:
return "scale_exp(" + baseExpr
+ ", " + QString::number( minValue )
+ ", " + QString::number( maxValue )
+ ", " + QString::number( minSize )
+ ", " + QString::number( maxSize ) + ", .57)";
return QString( "scale_exp(%1,%2,%3,%4,%5, 0.57)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString );

case Unknown:
break;
}
return "";
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;
}

0 comments on commit 721d9f5

Please sign in to comment.