QGIS API Documentation  2.12.0-Lyon
qgsscaleexpression.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsscaleexpression.cpp
3  ---------------------
4  begin : November 2014
5  copyright : (C) 2014 by Vincent Mora
6  email : vincent dor mora at oslandia dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsscaleexpression.h"
17 #include "qgis.h"
18 #include <QStringList>
19 #include <qmath.h>
20 
22  : QgsExpression( expression )
23  , mType( Unknown )
24  , mMinSize( 0 )
25  , mMaxSize( 10 )
26  , mMinValue( 0 )
27  , mMaxValue( 100 )
28  , mNullSize( 0 )
29 {
30  init();
31 }
32 
33 QgsScaleExpression::QgsScaleExpression( Type type, const QString& baseExpression, double minValue, double maxValue, double minSize, double maxSize, double nullSize )
34  : QgsExpression( createExpression( type, baseExpression, minValue, maxValue, minSize, maxSize, nullSize ) )
35  , mExpression( baseExpression )
36  , mType( type )
37  , mMinSize( minSize )
38  , mMaxSize( maxSize )
39  , mMinValue( minValue )
40  , mMaxValue( maxValue )
41  , mNullSize( nullSize )
42 {
43 
44 }
45 
46 void QgsScaleExpression::init()
47 {
48  bool ok;
49  mType = Unknown;
50 
51  if ( !rootNode() )
52  return;
53 
54  const NodeFunction * f = dynamic_cast<const NodeFunction*>( rootNode() );
55  if ( !f )
56  return;
57 
58  QList<Node*> args = f->args()->list();
59 
60  // the scale function may be enclosed in a coalesce(expr, 0) to avoid NULL value
61  // to be drawn with the default size
62  if ( "coalesce" == Functions()[f->fnIndex()]->name() )
63  {
64  f = dynamic_cast<const NodeFunction*>( args[0] );
65  if ( !f )
66  return;
67  mNullSize = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
68  if ( ! ok )
69  return;
70  args = f->args()->list();
71  }
72 
73  if ( "scale_linear" == Functions()[f->fnIndex()]->name() )
74  {
75  mType = Linear;
76  }
77  else if ( "scale_exp" == Functions()[f->fnIndex()]->name() )
78  {
79  const double exp = QgsExpression( args[5]->dump() ).evaluate().toDouble( &ok );
80  if ( ! ok )
81  return;
82  if ( qgsDoubleNear( exp, 0.57, 0.001 ) )
83  mType = Flannery;
84  else if ( qgsDoubleNear( exp, 0.5, 0.001 ) )
85  mType = Area;
86  else
87  {
88  return;
89  }
90  }
91  else
92  {
93  return;
94  }
95 
96  bool expOk = true;
97  mMinValue = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
98  expOk &= ok;
99  mMaxValue = QgsExpression( args[2]->dump() ).evaluate().toDouble( &ok );
100  expOk &= ok;
101  mMinSize = QgsExpression( args[3]->dump() ).evaluate().toDouble( &ok );
102  expOk &= ok;
103  mMaxSize = QgsExpression( args[4]->dump() ).evaluate().toDouble( &ok );
104  expOk &= ok;
105 
106  if ( !expOk )
107  {
108  mType = Unknown;
109  return;
110  }
111  mExpression = args[0]->dump();
112 }
113 
114 QString QgsScaleExpression::createExpression( Type type, const QString & baseExpr, double minValue, double maxValue, double minSize, double maxSize, double nullSize )
115 {
116  QString minValueString = QString::number( minValue );
117  QString maxValueString = QString::number( maxValue );
118  QString minSizeString = QString::number( minSize );
119  QString maxSizeString = QString::number( maxSize );
120  QString nullSizeString = QString::number( nullSize );
121 
122  switch ( type )
123  {
124  case Linear:
125  return QString( "coalesce(scale_linear(%1, %2, %3, %4, %5), %6)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString, nullSizeString );
126 
127  case Area:
128  return QString( "coalesce(scale_exp(%1, %2, %3, %4, %5, 0.5), %6)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString, nullSizeString );
129 
130  case Flannery:
131  return QString( "coalesce(scale_exp(%1, %2, %3, %4, %5, 0.57), %6)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString, nullSizeString );
132 
133  case Unknown:
134  break;
135  }
136  return QString();
137 }
138 
139 double QgsScaleExpression::size( double value ) const
140 {
141  switch ( mType )
142  {
143  case Linear:
144  return mMinSize + ( qBound( mMinValue, value, mMaxValue ) - mMinValue ) * ( mMaxSize - mMinSize ) / ( mMaxValue - mMinValue );
145 
146  case Area:
147  return mMinSize + qPow( qBound( mMinValue, value, mMaxValue ) - mMinValue, .5 ) * ( mMaxSize - mMinSize ) / qPow( mMaxValue - mMinValue, .5 );
148 
149  case Flannery:
150  return mMinSize + qPow( qBound( mMinValue, value, mMaxValue ) - mMinValue, .57 ) * ( mMaxSize - mMinSize ) / qPow( mMaxValue - mMinValue, .57 );
151 
152  case Unknown:
153  break;
154  }
155  return 0;
156 }
QgsScaleExpression(const QString &expression)
Constructor for QgsScaleExpression which parses an expression string to determine whether it's a scal...
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:92
double size(double value) const
Calculates the size corresponding to a specific value.
QgsExpression()
Used by QgsOgcUtils to create an empty.
QString dump() const
Return the expression string that represents this QgsExpression.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:268
static const QList< Function * > & Functions()
QString number(int n, int base)
const Node * rootNode() const
Returns root node of the expression. Root node is null is parsing has failed.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const