1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkExprTkFunctionParser.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /**
16  * @class   vtkExprTkFunctionParser
17  * @brief   Parse and evaluate a mathematical expression
18  *
19  * vtkExprTkFunctionParser is a wrapper class of the ExprTK library that takes
20  * in a mathematical expression as a char string, parses it, and evaluates it
21  * at the specified values of the variables in the input string.
22  *
23  * The detailed documentation of the supported functionality is described in
24  * https://github.com/ArashPartow/exprtk. In addition to the documented
25  * functionality, the following vector operations have been implemented:
26  * 1) cross(v1, v2), cross product of two vectors,
27  * 2) mag(v), magnitude of a vector,
28  * 3) norm(v), the normalized version of a vector.
29  *
30  * @par Thanks:
31  * Arash Partow for implementing the ExprTk library.
32  */
33 
34 #ifndef vtkExprTkFunctionParser_h
35 #define vtkExprTkFunctionParser_h
36 
37 #include "vtkCommonMiscModule.h" // For export macro
38 #include "vtkObject.h"
39 #include "vtkTuple.h" // needed for vtkTuple
40 #include <string>     // needed for string.
41 #include <vector>     // needed for vector
42 
43 // forward declarations for ExprTk tools
44 struct vtkExprTkTools;
45 
46 class VTKCOMMONMISC_EXPORT vtkExprTkFunctionParser : public vtkObject
47 {
48 public:
49   static vtkExprTkFunctionParser* New();
50   vtkTypeMacro(vtkExprTkFunctionParser, vtkObject);
51   void PrintSelf(ostream& os, vtkIndent indent) override;
52 
53   /**
54    * Return parser's MTime
55    */
56   vtkMTimeType GetMTime() override;
57 
58   ///@{
59   /**
60    * Set/Get input string to evaluate.
61    */
62   void SetFunction(const char* function);
GetFunction()63   const char* GetFunction() { return this->Function.c_str(); }
64   ///@}
65 
66   /**
67    * Check whether the result is a scalar result.  If it isn't, then
68    * either the result is a vector or an error has occurred.
69    */
70   int IsScalarResult();
71 
72   /**
73    * Check whether the result is a vector result.  If it isn't, then
74    * either the result is scalar or an error has occurred.
75    */
76   int IsVectorResult();
77 
78   /**
79    * Get a scalar result from evaluating the input function.
80    *
81    * If ReplaceInvalidValues is not set, then the error value
82    * that will be return is NaN.
83    */
84   double GetScalarResult();
85 
86   ///@{
87   /**
88    * Get a vector result from evaluating the input function.
89    *
90    * If ReplaceInvalidValues is not set, then the error value
91    * that will be return is [NaN, NaN, NaN].
92    */
93   double* GetVectorResult() VTK_SIZEHINT(3);
GetVectorResult(double result[3])94   void GetVectorResult(double result[3])
95   {
96     double* r = this->GetVectorResult();
97     result[0] = r[0];
98     result[1] = r[1];
99     result[2] = r[2];
100   }
101   ///@}
102 
103   ///@{
104   /**
105    * Set the value of a scalar variable.  If a variable with this name
106    * exists, then its value will be set to the new value.  If there is not
107    * already a variable with this name, variableName will be added to the
108    * list of variables, and its value will be set to the new value. If the
109    * variable name is not sanitized, it should be provided in quotes, and
110    * a valid unique string will be used as a replacement by the parser.
111    *
112    * @note A sanitized variable name is accepted by the following regex: ^[a-zA-Z][a-zA-Z_0-9]*.
113    */
114   void SetScalarVariableValue(const std::string& variableName, double value);
115   void SetScalarVariableValue(int i, double value);
116   ///@}
117 
118   ///@{
119   /**
120    * Get the value of a scalar variable.
121    */
122   double GetScalarVariableValue(const std::string& variableName);
123   double GetScalarVariableValue(int i);
124   ///@}
125 
126   ///@{
127   /**
128    * Set the value of a vector variable.  If a variable with this name
129    * exists, then its value will be set to the new value.  If there is not
130    * already a variable with this name, variableName will be added to the
131    * list of variables, and its value will be set to the new value. If the
132    * variable name is not sanitized, it should be provided in quotes, and
133    * a valid unique string will be used as a replacement by the parser.
134    *
135    * @note A sanitized variable name is accepted by the following regex: ^[a-zA-Z][a-zA-Z_0-9]*.
136    */
137   void SetVectorVariableValue(
138     const std::string& variableName, double xValue, double yValue, double zValue);
SetVectorVariableValue(const std::string & variableName,double values[3])139   void SetVectorVariableValue(const std::string& variableName, double values[3])
140   {
141     this->SetVectorVariableValue(variableName, values[0], values[1], values[2]);
142   }
143   void SetVectorVariableValue(int i, double xValue, double yValue, double zValue);
SetVectorVariableValue(int i,double values[3])144   void SetVectorVariableValue(int i, double values[3])
145   {
146     this->SetVectorVariableValue(i, values[0], values[1], values[2]);
147   }
148   ///@}
149 
150   ///@{
151   /**
152    * Get the value of a vector variable.
153    */
154   double* GetVectorVariableValue(const std::string& variableName) VTK_SIZEHINT(3);
GetVectorVariableValue(const std::string & variableName,double value[3])155   void GetVectorVariableValue(const std::string& variableName, double value[3])
156   {
157     double* r = this->GetVectorVariableValue(variableName);
158     value[0] = r[0];
159     value[1] = r[1];
160     value[2] = r[2];
161   }
162   double* GetVectorVariableValue(int i) VTK_SIZEHINT(3);
GetVectorVariableValue(int i,double value[3])163   void GetVectorVariableValue(int i, double value[3])
164   {
165     double* r = this->GetVectorVariableValue(i);
166     value[0] = r[0];
167     value[1] = r[1];
168     value[2] = r[2];
169   }
170   ///@}
171 
172   /**
173    * Get the number of scalar variables.
174    */
GetNumberOfScalarVariables()175   int GetNumberOfScalarVariables()
176   {
177     return static_cast<int>(this->UsedScalarVariableNames.size());
178   }
179 
180   /**
181    * Get scalar variable index or -1 if not found
182    */
183   int GetScalarVariableIndex(const std::string& name);
184 
185   /**
186    * Get the number of vector variables.
187    */
GetNumberOfVectorVariables()188   int GetNumberOfVectorVariables()
189   {
190     return static_cast<int>(this->UsedVectorVariableNames.size());
191   }
192 
193   /**
194    * Get scalar variable index or -1 if not found
195    */
196   int GetVectorVariableIndex(const std::string& name);
197 
198   /**
199    * Get the ith scalar variable name.
200    */
201   std::string GetScalarVariableName(int i);
202 
203   /**
204    * Get the ith vector variable name.
205    */
206   std::string GetVectorVariableName(int i);
207 
208   ///@{
209   /**
210    * Returns whether a scalar variable is needed for the function evaluation.
211    * This is only valid after a successful Parse(). Thus, call GetScalarResult()
212    * or IsScalarResult() or similar method before calling this.
213    */
214   bool GetScalarVariableNeeded(int i);
215   bool GetScalarVariableNeeded(const std::string& variableName);
216   ///@}
217 
218   ///@{
219   /**
220    * Returns whether a vector variable is needed for the function evaluation.
221    * This is only valid after a successful Parse(). Thus, call GetVectorResult()
222    * or IsVectorResult() or similar method before calling this.
223    */
224   bool GetVectorVariableNeeded(int i);
225   bool GetVectorVariableNeeded(const std::string& variableName);
226   ///@}
227 
228   /**
229    * Remove all the current variables.
230    */
231   void RemoveAllVariables();
232 
233   /**
234    * Remove all the scalar variables.
235    */
236   void RemoveScalarVariables();
237 
238   /**
239    * Remove all the vector variables.
240    */
241   void RemoveVectorVariables();
242 
243   ///@{
244   /**
245    * When ReplaceInvalidValues is on, all invalid values (such as
246    * sqrt(-2), note that function parser does not handle complex
247    * numbers) will be replaced by ReplacementValue. Otherwise an
248    * error will be reported
249    */
250   vtkSetMacro(ReplaceInvalidValues, vtkTypeBool);
251   vtkGetMacro(ReplaceInvalidValues, vtkTypeBool);
252   vtkBooleanMacro(ReplaceInvalidValues, vtkTypeBool);
253   vtkSetMacro(ReplacementValue, double);
254   vtkGetMacro(ReplacementValue, double);
255   ///@}
256 
257   /**
258    * Allow the user to force the function to be re-parsed
259    */
260   void InvalidateFunction();
261 
262   /**
263    * Sanitize a label/name to remove spaces, delimiters etc.
264    * Once the label/name is sanitized is can be accepted by the
265    * following regex: ^[a-zA-Z][a-zA-Z_0-9]*.
266    *
267    * @note taken from vtkSMCoreUtilities
268    */
269   static std::string SanitizeName(const char* name);
270 
271 protected:
272   vtkExprTkFunctionParser();
273   ~vtkExprTkFunctionParser() override;
274 
275   /**
276    * The first mode parses the function and uses a return statement
277    * to identify the ReturnType. The second mode parses the function and uses a result
278    * vector to store the results of the function knowing its return type. The second mode
279    * is used because it's a lot faster than the first.
280    */
281   enum ParseMode
282   {
283     DetectReturnType,
284     SaveResultInVariable
285   };
286 
287   /**
288    * Parses the given function, returning true on success, false on failure.
289    * It has 2 modes (see ParseMode). Both modes need to be utilized to extract
290    * results of a function.
291    */
292   int Parse(ParseMode mode);
293 
294   /**
295    * Enum that defines the vector returning functions that are not supported by ExprTk.
296    */
297   enum VectorReturningFunction
298   {
299     Cross,
300     Norm
301   };
302 
303   /**
304    * ExprTk does not support functions which return a vector.
305    *
306    * All the cross(v1,v2) occurrences will be replaced with
307    * (iHat*crossX(v1,v2)+jHat*crossY(v1,v2)+kHat*crossZ(v1,v2)).
308    *
309    * All the norm(v) occurrences will be replaced with ((v)/mag(v)).
310    */
311   std::string FixVectorReturningFunctionOccurrences(
312     VectorReturningFunction vectorReturningFunction);
313 
314   /**
315    *  Check possible usage of old format of dot product, e.g. v1.v2
316    */
317   bool CheckOldFormatOfDotProductUsage();
318 
319   /**
320    * Evaluate the function, returning true on success, false on failure.
321    */
322   bool Evaluate();
323 
324   /**
325    * Collects meta-data about which variables are needed by the current
326    * function. This is called only after a successful call to this->Parse().
327    */
328   void UpdateNeededVariables();
329 
330   std::string Function;
331   std::string FunctionWithUsedVariableNames;
332   std::string ExpressionString;
333 
334   // original and used variables names are the same, except if the original
335   // ones are not valid.
336   std::vector<std::string> OriginalScalarVariableNames;
337   std::vector<std::string> UsedScalarVariableNames;
338   std::vector<std::string> OriginalVectorVariableNames;
339   std::vector<std::string> UsedVectorVariableNames;
340   // pointers for scalar and vector variables are used to enforce
341   // that their memory address will not change due to a possible
342   // resizing of their container (std::vector), ExprTk requires the
343   // memory address of the given variable to remain the same.
344   std::vector<double*> ScalarVariableValues;
345   std::vector<vtkTuple<double, 3>*> VectorVariableValues;
346   std::vector<bool> ScalarVariableNeeded;
347   std::vector<bool> VectorVariableNeeded;
348 
349   vtkTimeStamp FunctionMTime;
350   vtkTimeStamp ParseMTime;
351   vtkTimeStamp VariableMTime;
352   vtkTimeStamp EvaluateMTime;
353 
354   vtkTypeBool ReplaceInvalidValues;
355   double ReplacementValue;
356 
357   vtkExprTkTools* ExprTkTools;
358 
359   int ResultType;
360   vtkTuple<double, 3> Result;
361 
362 private:
363   vtkExprTkFunctionParser(const vtkExprTkFunctionParser&) = delete;
364   void operator=(const vtkExprTkFunctionParser&) = delete;
365 };
366 
367 #endif
368