You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

422 lines
12 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkFunctionParser.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkFunctionParser
* @brief Parse and evaluate a mathematical expression
*
* vtkFunctionParser is a class that takes in a mathematical expression as
* a char string, parses it, and evaluates it at the specified values of
* the variables in the input string.
*
* You can use the "if" operator to create conditional expressions
* such as if ( test, trueresult, falseresult). These evaluate the boolean
* valued test expression and then evaluate either the trueresult or the
* falseresult expression to produce a final (scalar or vector valued) value.
* "test" may contain <,>,=,|,&, and () and all three subexpressions can
* evaluate arbitrary function operators (ln, cos, +, if, etc)
*
* @par Thanks:
* Juha Nieminen (juha.nieminen@gmail.com) for relicensing this branch of the
* function parser code that this class is based upon under the new BSD license
* so that it could be used in VTK. Note, the BSD license applies to this
* version of the function parser only (by permission of the author), and not
* the original library.
*
* @par Thanks:
* Thomas Dunne (thomas.dunne@iwr.uni-heidelberg.de) for adding code for
* two-parameter-parsing and a few functions (sign, min, max).
*
* @par Thanks:
* Sid Sydoriak (sxs@lanl.gov) for adding boolean operations and
* conditional expressions and for fixing a variety of bugs.
*/
#ifndef vtkFunctionParser_h
#define vtkFunctionParser_h
#include "vtkCommonMiscModule.h" // For export macro
#include "vtkObject.h"
#include "vtkTuple.h" // needed for vtkTuple
#include <string> // needed for string.
#include <vector> // needed for vector
#define VTK_PARSER_IMMEDIATE 1
#define VTK_PARSER_UNARY_MINUS 2
#define VTK_PARSER_UNARY_PLUS 3
// supported math functions
#define VTK_PARSER_ADD 4
#define VTK_PARSER_SUBTRACT 5
#define VTK_PARSER_MULTIPLY 6
#define VTK_PARSER_DIVIDE 7
#define VTK_PARSER_POWER 8
#define VTK_PARSER_ABSOLUTE_VALUE 9
#define VTK_PARSER_EXPONENT 10
#define VTK_PARSER_CEILING 11
#define VTK_PARSER_FLOOR 12
#define VTK_PARSER_LOGARITHM 13
#define VTK_PARSER_LOGARITHME 14
#define VTK_PARSER_LOGARITHM10 15
#define VTK_PARSER_SQUARE_ROOT 16
#define VTK_PARSER_SINE 17
#define VTK_PARSER_COSINE 18
#define VTK_PARSER_TANGENT 19
#define VTK_PARSER_ARCSINE 20
#define VTK_PARSER_ARCCOSINE 21
#define VTK_PARSER_ARCTANGENT 22
#define VTK_PARSER_HYPERBOLIC_SINE 23
#define VTK_PARSER_HYPERBOLIC_COSINE 24
#define VTK_PARSER_HYPERBOLIC_TANGENT 25
#define VTK_PARSER_MIN 26
#define VTK_PARSER_MAX 27
#define VTK_PARSER_SIGN 29
// functions involving vectors
#define VTK_PARSER_CROSS 28
#define VTK_PARSER_VECTOR_UNARY_MINUS 30
#define VTK_PARSER_VECTOR_UNARY_PLUS 31
#define VTK_PARSER_DOT_PRODUCT 32
#define VTK_PARSER_VECTOR_ADD 33
#define VTK_PARSER_VECTOR_SUBTRACT 34
#define VTK_PARSER_SCALAR_TIMES_VECTOR 35
#define VTK_PARSER_VECTOR_TIMES_SCALAR 36
#define VTK_PARSER_VECTOR_OVER_SCALAR 37
#define VTK_PARSER_MAGNITUDE 38
#define VTK_PARSER_NORMALIZE 39
// constants involving vectors
#define VTK_PARSER_IHAT 40
#define VTK_PARSER_JHAT 41
#define VTK_PARSER_KHAT 42
// code for if(bool, trueval, falseval) resulting in a scalar
#define VTK_PARSER_IF 43
// code for if(bool, truevec, falsevec) resulting in a vector
#define VTK_PARSER_VECTOR_IF 44
// codes for boolean expressions
#define VTK_PARSER_LESS_THAN 45
// codes for boolean expressions
#define VTK_PARSER_GREATER_THAN 46
// codes for boolean expressions
#define VTK_PARSER_EQUAL_TO 47
// codes for boolean expressions
#define VTK_PARSER_AND 48
// codes for boolean expressions
#define VTK_PARSER_OR 49
// codes for scalar variables come before those for vectors. Do not define
// values for VTK_PARSER_BEGIN_VARIABLES+1, VTK_PARSER_BEGIN_VARIABLES+2, ...,
// because they are used to look up variables numbered 1, 2, ...
#define VTK_PARSER_BEGIN_VARIABLES 50
// the value that is returned as a result if there is an error
#define VTK_PARSER_ERROR_RESULT VTK_FLOAT_MAX
class VTKCOMMONMISC_EXPORT vtkFunctionParser : public vtkObject
{
public:
static vtkFunctionParser* New();
vtkTypeMacro(vtkFunctionParser, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* Return parser's MTime
*/
vtkMTimeType GetMTime() override;
//@{
/**
* Set/Get input string to evaluate.
*/
void SetFunction(const char* function);
vtkGetStringMacro(Function);
//@}
/**
* Check whether the result is a scalar result. If it isn't, then
* either the result is a vector or an error has occurred.
*/
int IsScalarResult();
/**
* Check whether the result is a vector result. If it isn't, then
* either the result is scalar or an error has occurred.
*/
int IsVectorResult();
/**
* Get a scalar result from evaluating the input function.
*/
double GetScalarResult();
//@{
/**
* Get a vector result from evaluating the input function.
*/
double* GetVectorResult() VTK_SIZEHINT(3);
void GetVectorResult(double result[3])
{
double* r = this->GetVectorResult();
result[0] = r[0];
result[1] = r[1];
result[2] = r[2];
}
//@}
//@{
/**
* Set the value of a scalar variable. If a variable with this name
* exists, then its value will be set to the new value. If there is not
* already a variable with this name, variableName will be added to the
* list of variables, and its value will be set to the new value.
*/
void SetScalarVariableValue(const char* variableName, double value);
void SetScalarVariableValue(int i, double value);
//@}
//@{
/**
* Get the value of a scalar variable.
*/
double GetScalarVariableValue(const char* variableName);
double GetScalarVariableValue(int i);
//@}
//@{
/**
* Set the value of a vector variable. If a variable with this name
* exists, then its value will be set to the new value. If there is not
* already a variable with this name, variableName will be added to the
* list of variables, and its value will be set to the new value.
*/
void SetVectorVariableValue(
const char* variableName, double xValue, double yValue, double zValue);
void SetVectorVariableValue(const char* variableName, const double values[3])
{
this->SetVectorVariableValue(variableName, values[0], values[1], values[2]);
}
void SetVectorVariableValue(int i, double xValue, double yValue, double zValue);
void SetVectorVariableValue(int i, const double values[3])
{
this->SetVectorVariableValue(i, values[0], values[1], values[2]);
}
//@}
//@{
/**
* Get the value of a vector variable.
*/
double* GetVectorVariableValue(const char* variableName) VTK_SIZEHINT(3);
void GetVectorVariableValue(const char* variableName, double value[3])
{
double* r = this->GetVectorVariableValue(variableName);
value[0] = r[0];
value[1] = r[1];
value[2] = r[2];
}
double* GetVectorVariableValue(int i) VTK_SIZEHINT(3);
void GetVectorVariableValue(int i, double value[3])
{
double* r = this->GetVectorVariableValue(i);
value[0] = r[0];
value[1] = r[1];
value[2] = r[2];
}
//@}
/**
* Get the number of scalar variables.
*/
int GetNumberOfScalarVariables() { return static_cast<int>(this->ScalarVariableNames.size()); }
/**
* Get scalar variable index or -1 if not found
*/
int GetScalarVariableIndex(const char* name);
/**
* Get the number of vector variables.
*/
int GetNumberOfVectorVariables() { return static_cast<int>(this->VectorVariableNames.size()); }
/**
* Get scalar variable index or -1 if not found
*/
int GetVectorVariableIndex(const char* name);
/**
* Get the ith scalar variable name.
*/
const char* GetScalarVariableName(int i);
/**
* Get the ith vector variable name.
*/
const char* GetVectorVariableName(int i);
//@{
/**
* Returns whether a scalar variable is needed for the function evaluation.
* This is only valid after a successful Parse(). Thus, call GetScalarResult()
* or IsScalarResult() or similar method before calling this.
*/
bool GetScalarVariableNeeded(int i);
bool GetScalarVariableNeeded(const char* variableName);
//@}
//@{
/**
* Returns whether a vector variable is needed for the function evaluation.
* This is only valid after a successful Parse(). Thus, call GetVectorResult()
* or IsVectorResult() or similar method before calling this.
*/
bool GetVectorVariableNeeded(int i);
bool GetVectorVariableNeeded(const char* variableName);
//@}
/**
* Remove all the current variables.
*/
void RemoveAllVariables();
/**
* Remove all the scalar variables.
*/
void RemoveScalarVariables();
/**
* Remove all the vector variables.
*/
void RemoveVectorVariables();
//@{
/**
* When ReplaceInvalidValues is on, all invalid values (such as
* sqrt(-2), note that function parser does not handle complex
* numbers) will be replaced by ReplacementValue. Otherwise an
* error will be reported
*/
vtkSetMacro(ReplaceInvalidValues, vtkTypeBool);
vtkGetMacro(ReplaceInvalidValues, vtkTypeBool);
vtkBooleanMacro(ReplaceInvalidValues, vtkTypeBool);
vtkSetMacro(ReplacementValue, double);
vtkGetMacro(ReplacementValue, double);
//@}
/**
* Check the validity of the function expression.
*/
void CheckExpression(int& pos, char** error);
/**
* Allow the user to force the function to be re-parsed
*/
void InvalidateFunction();
protected:
vtkFunctionParser();
~vtkFunctionParser() override;
int Parse();
/**
* Evaluate the function, returning true on success, false on failure.
*/
bool Evaluate();
int CheckSyntax();
void CopyParseError(int& position, char** error);
void RemoveSpaces();
char* RemoveSpacesFrom(const char* variableName);
int OperatorWithinVariable(int idx);
int BuildInternalFunctionStructure();
void BuildInternalSubstringStructure(int beginIndex, int endIndex);
void AddInternalByte(unsigned int newByte);
int IsSubstringCompletelyEnclosed(int beginIndex, int endIndex);
int FindEndOfMathFunction(int beginIndex);
int FindEndOfMathConstant(int beginIndex);
int IsVariableName(int currentIndex);
int IsElementaryOperator(int op);
int GetMathFunctionNumber(int currentIndex);
int GetMathFunctionNumberByCheckingParenthesis(int currentIndex);
int GetMathFunctionStringLength(int mathFunctionNumber);
int GetMathConstantNumber(int currentIndex);
int GetMathConstantStringLength(int mathConstantNumber);
unsigned char GetElementaryOperatorNumber(char op);
unsigned int GetOperandNumber(int currentIndex);
int GetVariableNameLength(int variableNumber);
int DisambiguateOperators();
/**
* Collects meta-data about which variables are needed by the current
* function. This is called only after a successful call to this->Parse().
*/
void UpdateNeededVariables();
vtkSetStringMacro(ParseError);
int FindPositionInOriginalFunction(const int& pos);
char* Function;
char* FunctionWithSpaces;
int FunctionLength;
std::vector<std::string> ScalarVariableNames;
std::vector<std::string> VectorVariableNames;
std::vector<double> ScalarVariableValues;
std::vector<vtkTuple<double, 3> > VectorVariableValues;
std::vector<bool> ScalarVariableNeeded;
std::vector<bool> VectorVariableNeeded;
std::vector<unsigned int> ByteCode;
int ByteCodeSize;
double* Immediates;
int ImmediatesSize;
double* Stack;
int StackSize;
int StackPointer;
vtkTimeStamp FunctionMTime;
vtkTimeStamp ParseMTime;
vtkTimeStamp VariableMTime;
vtkTimeStamp EvaluateMTime;
vtkTimeStamp CheckMTime;
vtkTypeBool ReplaceInvalidValues;
double ReplacementValue;
int ParseErrorPositon;
char* ParseError;
private:
vtkFunctionParser(const vtkFunctionParser&) = delete;
void operator=(const vtkFunctionParser&) = delete;
};
#endif