QGIS API Documentation  2.14.11-Essen
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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  , mExponent( 1 )
30 {
31  init();
32 }
33 
34 QgsScaleExpression::QgsScaleExpression( Type type, const QString& baseExpression, double minValue, double maxValue, double minSize, double maxSize, double nullSize, double exponent )
35  : QgsExpression( createExpression( type, baseExpression, minValue, maxValue, minSize, maxSize, nullSize, exponent ) )
36  , mExpression( baseExpression )
37  , mType( type )
38  , mMinSize( minSize )
39  , mMaxSize( maxSize )
40  , mMinValue( minValue )
41  , mMaxValue( maxValue )
42  , mNullSize( nullSize )
43  , mExponent( 1 )
44 {
45  switch ( type )
46  {
47  case Linear:
48  mExponent = 1;
49  break;
50  case Area:
51  mExponent = .5;
52  break;
53  case Flannery:
54  mExponent = .57;
55  break;
56  case Exponential:
57  mExponent = exponent;
58  break;
59  case Unknown:
60  break;
61  }
62 }
63 
64 void QgsScaleExpression::init()
65 {
66  bool ok;
67  mType = Unknown;
68 
69  if ( !rootNode() )
70  return;
71 
72  const NodeFunction * f = dynamic_cast<const NodeFunction*>( rootNode() );
73  if ( !f )
74  return;
75 
76  QList<Node*> args = f->args()->list();
77 
78  // the scale function may be enclosed in a coalesce(expr, 0) to avoid NULL value
79  // to be drawn with the default size
80  if ( "coalesce" == Functions()[f->fnIndex()]->name() )
81  {
82  f = dynamic_cast<const NodeFunction*>( args[0] );
83  if ( !f )
84  return;
85  mNullSize = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
86  if ( ! ok )
87  return;
88  args = f->args()->list();
89  }
90 
91  if ( "scale_linear" == Functions()[f->fnIndex()]->name() )
92  {
93  mType = Linear;
94  }
95  else if ( "scale_exp" == Functions()[f->fnIndex()]->name() )
96  {
97  mExponent = QgsExpression( args[5]->dump() ).evaluate().toDouble( &ok );
98  if ( ! ok )
99  return;
100  if ( qgsDoubleNear( mExponent, 0.57, 0.001 ) )
101  mType = Flannery;
102  else if ( qgsDoubleNear( mExponent, 0.5, 0.001 ) )
103  mType = Area;
104  else
105  mType = Exponential;
106  }
107  else
108  {
109  return;
110  }
111 
112  bool expOk = true;
113  mMinValue = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
114  expOk &= ok;
115  mMaxValue = QgsExpression( args[2]->dump() ).evaluate().toDouble( &ok );
116  expOk &= ok;
117  mMinSize = QgsExpression( args[3]->dump() ).evaluate().toDouble( &ok );
118  expOk &= ok;
119  mMaxSize = QgsExpression( args[4]->dump() ).evaluate().toDouble( &ok );
120  expOk &= ok;
121 
122  if ( !expOk )
123  {
124  mType = Unknown;
125  return;
126  }
127  mExpression = args[0]->dump();
128 }
129 
130 QString QgsScaleExpression::createExpression( Type type, const QString & baseExpr, double minValue, double maxValue, double minSize, double maxSize, double nullSize, double exponent )
131 {
132  QString minValueString = QString::number( minValue );
133  QString maxValueString = QString::number( maxValue );
134  QString minSizeString = QString::number( minSize );
135  QString maxSizeString = QString::number( maxSize );
136  QString nullSizeString = QString::number( nullSize );
137  QString exponentString = QString::number( exponent );
138 
139  switch ( type )
140  {
141  case Linear:
142  return QString( "coalesce(scale_linear(%1, %2, %3, %4, %5), %6)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString, nullSizeString );
143 
144  case Area:
145  case Flannery:
146  case Exponential:
147  return QString( "coalesce(scale_exp(%1, %2, %3, %4, %5, %6), %7)" ).arg( baseExpr, minValueString, maxValueString, minSizeString, maxSizeString, exponentString, nullSizeString );
148 
149  case Unknown:
150  break;
151  }
152  return QString();
153 }
154 
155 double QgsScaleExpression::size( double value ) const
156 {
157  switch ( mType )
158  {
159  case Linear:
160  return mMinSize + ( qBound( mMinValue, value, mMaxValue ) - mMinValue ) * ( mMaxSize - mMinSize ) / ( mMaxValue - mMinValue );
161 
162  case Area:
163  case Flannery:
164  case Exponential:
165  return mMinSize + qPow( qBound( mMinValue, value, mMaxValue ) - mMinValue, mExponent ) * ( mMaxSize - mMinSize ) / qPow( mMaxValue - mMinValue, mExponent );
166 
167  case Unknown:
168  break;
169  }
170  return 0;
171 }
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").
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 an expression string, constructed from the internal abstract syntax tree.
const Node * rootNode() const
Returns root node of the expression. Root node is null is parsing has failed.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:285
static const QList< Function * > & Functions()
QString number(int n, int base)
double exponent() const
Returns the exponent of the exponential expression.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const