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