1/* -*-c++-*- */
2/* osgEarth - Geospatial SDK for OpenSceneGraph
3 * Copyright 2019 Pelican Mapping
4 * http://osgearth.org
5 *
6 * osgEarth is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>
18 */
19
20#ifndef OSGEARTHSYMBOLOGY_EXPRESSION_H
21#define OSGEARTHSYMBOLOGY_EXPRESSION_H 1
22
23#include <osgEarthSymbology/Common>
24#include <osgEarth/Config>
25#include <osgEarth/URI>
26#include <osgEarth/GeoData>
27#include <osgEarth/TileKey>
28
29namespace osgEarth { namespace Symbology
30{
31    /**
32     * Simple numeric expression evaluator with variables.
33     */
34    class OSGEARTHSYMBOLOGY_EXPORT NumericExpression
35    {
36    public:
37        typedef std::pair<std::string,unsigned> Variable;
38        typedef std::vector<Variable> Variables;
39
40    public:
41        NumericExpression();
42
43        NumericExpression( const Config& conf );
44
45        /** Construct a new expression from the infix string. */
46        NumericExpression( const std::string& expr );
47
48        /** Construct a new static expression from a value */
49        NumericExpression( double staticValue );
50
51        /** Copy ctor. */
52        NumericExpression( const NumericExpression& rhs );
53
54        /** dtor */
55        virtual ~NumericExpression() { }
56
57        /** Set the result to a literal value. */
58        void setLiteral( double staticValue );
59
60        /** Access the expression variables. */
61        const Variables& variables() const { return _vars; }
62
63        /** Set the value of a variable. */
64        void set( const Variable& var, double value );
65
66        /** Evaluate the expression. */
67        double eval() const;
68
69        /** Gets the expression string. */
70        const std::string& expr() const { return _src; }
71
72        /** Whether the expression is empty */
73        bool empty() const { return _src.empty(); }
74
75    public:
76        Config getConfig() const;
77        void mergeConfig( const Config& conf );
78
79    private:
80        enum Op { OPERAND, VARIABLE, ADD, SUB, MULT, DIV, MOD, MIN, MAX, LPAREN, RPAREN, COMMA }; // in low-high precedence order
81        typedef std::pair<Op,double> Atom;
82        typedef std::vector<Atom> AtomVector;
83        typedef std::stack<Atom> AtomStack;
84
85        std::string _src;
86        AtomVector  _rpn;
87        Variables   _vars;
88        double      _value;
89        bool        _dirty;
90
91        void init();
92    };
93
94    //--------------------------------------------------------------------
95
96    /**
97     * Simple string expression evaluator with variables.
98     */
99    class OSGEARTHSYMBOLOGY_EXPORT StringExpression
100    {
101    public:
102        typedef std::pair<std::string,unsigned> Variable;
103        typedef std::vector<Variable> Variables;
104
105    public:
106        StringExpression();
107
108        StringExpression( const Config& conf );
109
110        /** Construct a new expression from the infix string. */
111        StringExpression( const std::string& expr );
112
113        /** Construct an expression from the infix string and a URI context. */
114        StringExpression( const std::string& expr, const URIContext& uriContext );
115
116        /** Copy ctor. */
117        StringExpression( const StringExpression& rhs );
118
119        /** dtor */
120        virtual ~StringExpression() { }
121
122        /** Set the infix expr. */
123        void setInfix( const std::string& infix );
124
125        /** Set the infix expr to a literal string */
126        void setLiteral( const std::string& value );
127
128        /** Access the expression variables. */
129        const Variables& variables() const { return _vars; }
130
131        /** Set the value of a variable. */
132        void set( const Variable& var, const std::string& value );
133
134        /** Set the value of a names variable if it exists */
135        void set( const std::string& varName, const std::string& value );
136
137        /** Evaluate the expression. */
138        const std::string& eval() const;
139
140        /** Evaluate the expression as a URI.
141            TODO: it would be better to have a whole new subclass URIExpression */
142        URI evalURI() const;
143
144        /** Gets the expression string. */
145        const std::string& expr() const { return _src; }
146
147        /** Whether the expression is empty */
148        bool empty() const { return _src.empty(); }
149
150        void setURIContext( const URIContext& uriContext ) { _uriContext = uriContext; }
151        const URIContext& uriContext() const { return _uriContext; }
152
153    public:
154        Config getConfig() const;
155        void mergeConfig( const Config& conf );
156
157    private:
158        enum Op { OPERAND, VARIABLE }; // in low-high precedence order
159        typedef std::pair<Op,std::string> Atom;
160        typedef std::vector<Atom> AtomVector;
161
162        std::string  _src;
163        AtomVector   _infix;
164        Variables    _vars;
165        std::string  _value;
166        bool         _dirty;
167        URIContext   _uriContext;
168
169        void init();
170    };
171
172
173} } // namespace osgEarth::Symbology
174
175OSGEARTH_SPECIALIZE_CONFIG(osgEarth::Symbology::NumericExpression);
176OSGEARTH_SPECIALIZE_CONFIG(osgEarth::Symbology::StringExpression);
177
178#endif // OSGEARTHSYMBOLOGY_EXPRESSION_H
179