QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 
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&#39;s a scal...
Class for parsing and evaluation of expressions (formerly called "search strings").
QString dump() const
Return an expression string, constructed from the internal abstract syntax tree.
double exponent() const
Returns the exponent of the exponential expression.
QgsExpression()
Create an empty expression.
double size(double value) const
Calculates the size corresponding to a specific value.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
QString baseExpression() const
Returns the base expression string (or field reference) used for calculating the values to be mapped ...
double maxValue() const
Returns the maximum value expected by the expression.
const Node * rootNode() const
Returns root node of the expression. Root node is null is parsing has failed.
static const QList< Function * > & Functions()
QString number(int n, int base)
double maxSize() const
Returns the maximum size calculated by the expression.
double minValue() const
Returns the minimum value expected by the expression.
Type type() const
Returns the scale expression&#39;s type (method used to calculate the size from a value).
double nullSize() const
Returns the size value when expression evaluates to NULL.
double minSize() const
Returns the minimum size calculated by the expression.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QList< Node * > list()