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.
nmWTAI-Platform/3rd/VTK7.1/source/VTK-7.1.1/Common/Misc/vtkFunctionParser.cxx

2513 lines
76 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkFunctionParser.cxx
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.
=========================================================================*/
#include "vtkFunctionParser.h"
#include "vtkObjectFactory.h"
#include <cctype>
#include <algorithm>
vtkStandardNewMacro(vtkFunctionParser);
static double vtkParserVectorErrorResult[3] = { VTK_PARSER_ERROR_RESULT,
VTK_PARSER_ERROR_RESULT,
VTK_PARSER_ERROR_RESULT };
//-----------------------------------------------------------------------------
vtkFunctionParser::vtkFunctionParser()
{
this->Function = NULL;
this->FunctionWithSpaces = NULL;
this->ByteCode = NULL;
this->ByteCodeSize = 0;
this->Immediates = NULL;
this->ImmediatesSize = 0;
this->Stack = NULL;
this->StackSize = 0;
this->StackPointer = 0;
this->EvaluateMTime.Modified();
this->VariableMTime.Modified();
this->ParseMTime.Modified();
this->FunctionMTime.Modified();
this->CheckMTime.Modified();
this->ReplaceInvalidValues = 0;
this->ReplacementValue = 0.0;
this->ParseErrorPositon = -1;
this->ParseError = NULL;
}
//-----------------------------------------------------------------------------
vtkFunctionParser::~vtkFunctionParser()
{
delete [] this->Function;
this->Function = NULL;
delete [] this->FunctionWithSpaces;
this->FunctionWithSpaces = NULL;
delete [] this->ByteCode;
this->ByteCode = NULL;
delete [] this->Immediates;
this->Immediates = NULL;
delete [] this->Stack;
this->Stack = NULL;
if(this->ParseError)
{
this->SetParseError(0);
}
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::SetFunction(const char *function)
{
if (this->Function && function && strcmp(this->Function,function) == 0)
{
return;
}
if (this->Function)
{
delete [] this->Function;
delete [] this->FunctionWithSpaces;
}
if (function)
{
this->Function = new char[strlen(function)+1];
this->FunctionWithSpaces = new char[strlen(function) + 1];
strcpy(this->Function,function);
strcpy(this->FunctionWithSpaces, function);
}
else
{
this->Function = NULL;
this->FunctionWithSpaces = NULL;
}
this->FunctionMTime.Modified();
this->ScalarVariableNeeded.clear();
this->VectorVariableNeeded.clear();
this->Modified();
}
int vtkFunctionParser::Parse()
{
int result;
int i;
if (this->Function == NULL)
{
vtkErrorMacro("Parse: no function has been set");
return 0;
}
result = this->CheckSyntax();
if (!result)
{
return 0;
}
this->BuildInternalFunctionStructure();
// need to make sure that the ambiguous operators are correct
// - scalar/vector +
// - scalar/vector -
// - scalar/vector unary minus
// - scalar/vector unary plus
// - * (2 scalars) or scalar multiple (scalar, vector)
result = this->DisambiguateOperators();
if (!result)
{
vtkErrorMacro("Parse: Error deciding between ambiguous operators");
return 0;
}
// need to recalculate stack size based on number of vector variables
// in byte code
for (i = 0; i < this->ByteCodeSize; i++)
{
if ((this->ByteCode[i] >= VTK_PARSER_BEGIN_VARIABLES +
this->GetNumberOfScalarVariables()) ||
(this->ByteCode[i] == VTK_PARSER_IHAT) ||
(this->ByteCode[i] == VTK_PARSER_JHAT) ||
(this->ByteCode[i] == VTK_PARSER_KHAT))
{
this->StackSize += 2;
}
}
if (this->StackSize)
{
this->Stack = new double[this->StackSize];
if (!this->Stack)
{
vtkErrorMacro("Parse: Out of memory");
return 0;
}
}
// Collect meta-data about variables that are needed for evaluation of the
// function.
this->UpdateNeededVariables();
this->ParseMTime.Modified();
return 1;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::DisambiguateOperators()
{
unsigned char* tempStack = new unsigned char[this->ByteCodeSize];
int i;
int tempStackPtr = -1;
// using 0 for scalars and 1 for vectors
for (i = 0; i < this->ByteCodeSize; i++)
{
switch (this->ByteCode[i])
{
case VTK_PARSER_IMMEDIATE:
tempStackPtr++;
tempStack[tempStackPtr] = 0;
break;
case VTK_PARSER_UNARY_MINUS:
if (tempStack[tempStackPtr] != 0)
{
this->ByteCode[i] = VTK_PARSER_VECTOR_UNARY_MINUS;
}
break;
case VTK_PARSER_UNARY_PLUS:
if (tempStack[tempStackPtr] != 0)
{
this->ByteCode[i] = VTK_PARSER_VECTOR_UNARY_PLUS;
}
break;
case VTK_PARSER_ADD:
if (tempStack[tempStackPtr] != 0 && tempStack[tempStackPtr-1] != 0)
{
this->ByteCode[i] = VTK_PARSER_VECTOR_ADD;
}
else if ((tempStack[tempStackPtr] == 0 &&
tempStack[tempStackPtr-1] != 0) ||
(tempStack[tempStackPtr] != 0 &&
tempStack[tempStackPtr-1] == 0))
{
delete [] tempStack;
vtkErrorMacro("addition expects either 2 vectors or 2 scalars");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_SUBTRACT:
if (tempStack[tempStackPtr] != 0 && tempStack[tempStackPtr-1] != 0)
{
this->ByteCode[i] = VTK_PARSER_VECTOR_SUBTRACT;
}
else if ((tempStack[tempStackPtr] == 0 &&
tempStack[tempStackPtr-1] != 0) ||
(tempStack[tempStackPtr] != 0 &&
tempStack[tempStackPtr-1] == 0))
{
delete [] tempStack;
vtkErrorMacro("subtraction expects either 2 vectors or 2 scalars");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_MULTIPLY:
if (tempStack[tempStackPtr-1] == 0 && tempStack[tempStackPtr] == 1)
{
this->ByteCode[i] = VTK_PARSER_SCALAR_TIMES_VECTOR;
tempStack[tempStackPtr-1] = 1;
}
else if (tempStack[tempStackPtr-1] == 1 &&
tempStack[tempStackPtr] == 0)
{
this->ByteCode[i] = VTK_PARSER_VECTOR_TIMES_SCALAR;
tempStack[tempStackPtr-1] = 1;
}
else if (tempStack[tempStackPtr] == 1)
{
delete [] tempStack;
vtkErrorMacro("multiply expecting either 2 scalars or a scalar and"
<< " a vector");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_DIVIDE:
if (tempStack[tempStackPtr-1] == 1 && tempStack[tempStackPtr] == 0)
{
// vector / scalar.
this->ByteCode[i] = VTK_PARSER_VECTOR_OVER_SCALAR;
tempStack[tempStackPtr-1] = 1;
}
else if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
{
delete [] tempStack;
vtkErrorMacro("can't divide vectors");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_POWER:
if (tempStack[tempStackPtr-1] == 1)
{
delete [] tempStack;
vtkErrorMacro("can't raise a vector to a power");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_LESS_THAN:
case VTK_PARSER_GREATER_THAN:
case VTK_PARSER_EQUAL_TO:
case VTK_PARSER_AND:
case VTK_PARSER_OR:
if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
{
delete [] tempStack;
vtkErrorMacro("Vectors cannot be used in boolean expressions.");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_ABSOLUTE_VALUE:
case VTK_PARSER_EXPONENT:
case VTK_PARSER_CEILING:
case VTK_PARSER_FLOOR:
case VTK_PARSER_LOGARITHM:
case VTK_PARSER_LOGARITHME:
case VTK_PARSER_LOGARITHM10:
case VTK_PARSER_SQUARE_ROOT:
case VTK_PARSER_SINE:
case VTK_PARSER_COSINE:
case VTK_PARSER_TANGENT:
case VTK_PARSER_ARCSINE:
case VTK_PARSER_ARCCOSINE:
case VTK_PARSER_ARCTANGENT:
case VTK_PARSER_HYPERBOLIC_SINE:
case VTK_PARSER_HYPERBOLIC_COSINE:
case VTK_PARSER_HYPERBOLIC_TANGENT:
case VTK_PARSER_SIGN:
if (tempStack[tempStackPtr] == 1)
{
delete [] tempStack;
vtkErrorMacro("expecting a scalar, but got a vector");
return 0;
}
break;
case VTK_PARSER_MIN:
if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
{
delete [] tempStack;
vtkErrorMacro("can't apply min to vectors");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_MAX:
if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
{
delete [] tempStack;
vtkErrorMacro("can't apply max to vectors");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_CROSS:
if (tempStack[tempStackPtr] == 0 || tempStack[tempStackPtr-1] == 0)
{
delete [] tempStack;
vtkErrorMacro("can't apply cross to scalars");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_DOT_PRODUCT:
if (tempStack[tempStackPtr] == 0 || tempStack[tempStackPtr-1] == 0)
{
delete [] tempStack;
vtkErrorMacro("dot product does not operate on scalars");
return 0;
}
tempStack[tempStackPtr-1] = 0;
tempStackPtr--;
break;
case VTK_PARSER_MAGNITUDE:
if (tempStack[tempStackPtr] == 0)
{
delete [] tempStack;
vtkErrorMacro("magnitude expects a vector, but got a scalar");
return 0;
}
tempStack[tempStackPtr] = 0;
break;
case VTK_PARSER_NORMALIZE:
if (tempStack[tempStackPtr] == 0)
{
delete [] tempStack;
vtkErrorMacro("normalize expects a vector, but got a scalar");
return 0;
}
break;
case VTK_PARSER_IHAT:
case VTK_PARSER_JHAT:
case VTK_PARSER_KHAT:
tempStackPtr++;
tempStack[tempStackPtr] = 1;
break;
case VTK_PARSER_IF:
// tempStack[tempStackPtr] = tempStack[2] refers to the bool argument
// of if(bool,valtrue,valfalse). tempStack[1] is valtrue, and
// tempStack[0] is valfalse.
if (tempStack[tempStackPtr] != 0)
{
delete [] tempStack;
vtkErrorMacro("first argument of if(bool,valtrue,valfalse) cannot be a vector");
return 0;
}
else if (tempStack[tempStackPtr-1] != 0 &&
tempStack[tempStackPtr-2] != 0)
{
this->ByteCode[i] = VTK_PARSER_VECTOR_IF;
}
else if ((tempStack[tempStackPtr-1] == 0 &&
tempStack[tempStackPtr-2] != 0) ||
(tempStack[tempStackPtr-1] != 0 &&
tempStack[tempStackPtr-2] == 0))
{
delete [] tempStack;
vtkErrorMacro("the if function expects the second and third arguments to be either 2 vectors or 2 scalars");
return 0;
}
tempStackPtr--;
tempStackPtr--;
break;
default:
if ((this->ByteCode[i] - VTK_PARSER_BEGIN_VARIABLES) < this->GetNumberOfScalarVariables())
{
tempStackPtr++;
tempStack[tempStackPtr] = 0;
}
else
{
tempStackPtr++;
tempStack[tempStackPtr] = 1;
}
}
}
delete [] tempStack;
return 1;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::InvalidateFunction()
{
this->FunctionMTime.Modified();
}
//-----------------------------------------------------------------------------
bool vtkFunctionParser::Evaluate()
{
int numBytesProcessed;
int numImmediatesProcessed = 0;
int stackPosition = -1;
double magnitude;
double temp[3];
this->StackPointer = -1;
if (this->FunctionMTime.GetMTime() > this->ParseMTime.GetMTime())
{
if (this->Parse() == 0)
{
return false;
}
}
for (numBytesProcessed = 0; numBytesProcessed < this->ByteCodeSize;
numBytesProcessed++)
{
switch (this->ByteCode[numBytesProcessed])
{
case VTK_PARSER_IMMEDIATE:
this->Stack[++stackPosition] =
this->Immediates[numImmediatesProcessed++];
break;
case VTK_PARSER_UNARY_MINUS:
this->Stack[stackPosition] = -(this->Stack[stackPosition]);
break;
case VTK_PARSER_UNARY_PLUS:
break;
case VTK_PARSER_ADD:
this->Stack[stackPosition-1] += this->Stack[stackPosition];
stackPosition--;
break;
case VTK_PARSER_SUBTRACT:
this->Stack[stackPosition-1] -= this->Stack[stackPosition];
stackPosition--;
break;
case VTK_PARSER_MULTIPLY:
this->Stack[stackPosition-1] *= this->Stack[stackPosition];
stackPosition--;
break;
case VTK_PARSER_DIVIDE:
if (this->Stack[stackPosition]==0)
{
if (this->ReplaceInvalidValues)
{
this->Stack[stackPosition-1] = this->ReplacementValue;
stackPosition--;
}
else
{
vtkErrorMacro("Trying to divide by zero");
return false;
}
}
else
{
this->Stack[stackPosition-1] /= this->Stack[stackPosition];
stackPosition--;
}
break;
case VTK_PARSER_POWER:
this->Stack[stackPosition-1] = pow(this->Stack[stackPosition-1],
this->Stack[stackPosition]);
stackPosition--;
break;
case VTK_PARSER_ABSOLUTE_VALUE:
this->Stack[stackPosition] = fabs(this->Stack[stackPosition]);
break;
case VTK_PARSER_EXPONENT:
this->Stack[stackPosition] = exp(this->Stack[stackPosition]);
break;
case VTK_PARSER_CEILING:
this->Stack[stackPosition] = ceil(this->Stack[stackPosition]);
break;
case VTK_PARSER_FLOOR:
this->Stack[stackPosition] = floor(this->Stack[stackPosition]);
break;
case VTK_PARSER_LOGARITHM:
if (this->Stack[stackPosition]<=0)
{
if (this->ReplaceInvalidValues)
{
this->Stack[stackPosition] = this->ReplacementValue;
}
else
{
vtkErrorMacro("Trying to take a log of a negative value");
return false;
}
}
else
{
this->Stack[stackPosition] = log(this->Stack[stackPosition]);
}
break;
case VTK_PARSER_LOGARITHME:
if (this->Stack[stackPosition]<=0)
{
if (this->ReplaceInvalidValues)
{
this->Stack[stackPosition] = this->ReplacementValue;
}
else
{
vtkErrorMacro("Trying to take a natural logarithm of a negative value");
return false;
}
}
else
{
this->Stack[stackPosition] = log(this->Stack[stackPosition]);
}
break;
case VTK_PARSER_LOGARITHM10:
if (this->Stack[stackPosition]<=0)
{
if (this->ReplaceInvalidValues)
{
this->Stack[stackPosition] = this->ReplacementValue;
}
else
{
vtkErrorMacro("Trying to take a log10 of a negative value");
return false;
}
}
else
{
this->Stack[stackPosition] =
log10(this->Stack[stackPosition]);
}
break;
case VTK_PARSER_SQUARE_ROOT:
if (this->Stack[stackPosition] < 0)
{
if (this->ReplaceInvalidValues)
{
this->Stack[stackPosition] = this->ReplacementValue;
}
else
{
vtkErrorMacro("Trying to take a square root of a negative value");
return false;
}
}
else
{
this->Stack[stackPosition] = sqrt(this->Stack[stackPosition]);
}
break;
case VTK_PARSER_SINE:
this->Stack[stackPosition] = sin(this->Stack[stackPosition]);
break;
case VTK_PARSER_COSINE:
this->Stack[stackPosition] = cos(this->Stack[stackPosition]);
break;
case VTK_PARSER_TANGENT:
this->Stack[stackPosition] = tan(this->Stack[stackPosition]);
break;
case VTK_PARSER_ARCSINE:
if (this->Stack[stackPosition] < -1 || this->Stack[stackPosition] > 1)
{
if (this->ReplaceInvalidValues)
{
this->Stack[stackPosition] = this->ReplacementValue;
}
else
{
vtkErrorMacro("Trying to take asin of a value < -1 or > 1. Arg is q" << this->Stack[stackPosition]);
return false;
}
}
else
{
this->Stack[stackPosition] = asin(this->Stack[stackPosition]);
}
break;
case VTK_PARSER_ARCCOSINE:
if(this->Stack[stackPosition]<-1 || this->Stack[stackPosition]>1)
{
if (this->ReplaceInvalidValues)
{
this->Stack[stackPosition] = this->ReplacementValue;
}
else
{
vtkErrorMacro("Trying to take acos of a value < -1 or > 1. Arg is q" << this->Stack[stackPosition]);
return false;
}
}
else
{
this->Stack[stackPosition] = acos(this->Stack[stackPosition]);
}
break;
case VTK_PARSER_ARCTANGENT:
this->Stack[stackPosition] = atan(this->Stack[stackPosition]);
break;
case VTK_PARSER_HYPERBOLIC_SINE:
this->Stack[stackPosition] = sinh(this->Stack[stackPosition]);
break;
case VTK_PARSER_HYPERBOLIC_COSINE:
this->Stack[stackPosition] = cosh(this->Stack[stackPosition]);
break;
case VTK_PARSER_HYPERBOLIC_TANGENT:
this->Stack[stackPosition] = tanh(this->Stack[stackPosition]);
break;
case VTK_PARSER_MIN:
if (this->Stack[stackPosition] < this->Stack[stackPosition-1])
{
this->Stack[stackPosition-1] = this->Stack[stackPosition];
}
stackPosition--;
break;
case VTK_PARSER_MAX:
if (this->Stack[stackPosition] > this->Stack[stackPosition-1])
{
this->Stack[stackPosition-1] = this->Stack[stackPosition];
}
stackPosition--;
break;
case VTK_PARSER_CROSS:
// Cross Product
#define Ux (stackPosition-5)
#define Uy (stackPosition-4)
#define Uz (stackPosition-3)
#define Vx (stackPosition-2)
#define Vy (stackPosition-1)
#define Vz stackPosition
temp[0] = this->Stack[Uy]*this->Stack[Vz] -
this->Stack[Uz]*this->Stack[Vy];
temp[1] = this->Stack[Uz]*this->Stack[Vx] -
this->Stack[Ux]*this->Stack[Vz];
temp[2] = this->Stack[Ux]*this->Stack[Vy] -
this->Stack[Uy]*this->Stack[Vx];
this->Stack[Ux] = temp[0];
this->Stack[Uy] = temp[1];
this->Stack[Uz] = temp[2];
#undef Ux
#undef Uy
#undef Uz
#undef Vx
#undef Vy
#undef Vz
stackPosition-=3;
break;
case VTK_PARSER_SIGN:
if (this->Stack[stackPosition] < 0)
{
this->Stack[stackPosition] = -1;
}
else if (this->Stack[stackPosition] == 0)
{
this->Stack[stackPosition] = 0;
}
else
{
this->Stack[stackPosition] = 1;
}
break;
case VTK_PARSER_VECTOR_UNARY_MINUS:
this->Stack[stackPosition] = -this->Stack[stackPosition];
this->Stack[stackPosition-1] = -this->Stack[stackPosition-1];
this->Stack[stackPosition-2] = -this->Stack[stackPosition-2];
break;
case VTK_PARSER_VECTOR_UNARY_PLUS:
break;
case VTK_PARSER_DOT_PRODUCT:
this->Stack[stackPosition-3] *= this->Stack[stackPosition];
this->Stack[stackPosition-4] *= this->Stack[stackPosition-1];
this->Stack[stackPosition-5] *= this->Stack[stackPosition-2];
this->Stack[stackPosition-5] = this->Stack[stackPosition-5] +
this->Stack[stackPosition-4] + this->Stack[stackPosition-3];
stackPosition -= 5;
break;
case VTK_PARSER_VECTOR_ADD:
this->Stack[stackPosition-3] += this->Stack[stackPosition];
this->Stack[stackPosition-4] += this->Stack[stackPosition-1];
this->Stack[stackPosition-5] += this->Stack[stackPosition-2];
stackPosition -= 3;
break;
case VTK_PARSER_VECTOR_SUBTRACT:
this->Stack[stackPosition-3] -= this->Stack[stackPosition];
this->Stack[stackPosition-4] -= this->Stack[stackPosition-1];
this->Stack[stackPosition-5] -= this->Stack[stackPosition-2];
stackPosition -= 3;
break;
case VTK_PARSER_SCALAR_TIMES_VECTOR:
this->Stack[stackPosition] *= this->Stack[stackPosition-3];
this->Stack[stackPosition-1] *= this->Stack[stackPosition-3];
this->Stack[stackPosition-2] *= this->Stack[stackPosition-3];
this->Stack[stackPosition-3] = this->Stack[stackPosition-2];
this->Stack[stackPosition-2] = this->Stack[stackPosition-1];
this->Stack[stackPosition-1] = this->Stack[stackPosition];
stackPosition--;
break;
case VTK_PARSER_VECTOR_TIMES_SCALAR:
this->Stack[stackPosition-3] *= this->Stack[stackPosition];
this->Stack[stackPosition-2] *= this->Stack[stackPosition];
this->Stack[stackPosition-1] *= this->Stack[stackPosition];
stackPosition--;
break;
case VTK_PARSER_VECTOR_OVER_SCALAR:
this->Stack[stackPosition-3] /= this->Stack[stackPosition];
this->Stack[stackPosition-2] /= this->Stack[stackPosition];
this->Stack[stackPosition-1] /= this->Stack[stackPosition];
stackPosition--;
break;
case VTK_PARSER_MAGNITUDE:
this->Stack[stackPosition-2] =
sqrt(pow(this->Stack[stackPosition], 2) +
pow(this->Stack[stackPosition-1], 2) +
pow(this->Stack[stackPosition-2], 2));
stackPosition -= 2;
break;
case VTK_PARSER_NORMALIZE:
magnitude = sqrt(pow(this->Stack[stackPosition], 2) +
pow(this->Stack[stackPosition-1], 2) +
pow(this->Stack[stackPosition-2], 2));
if (magnitude != 0)
{
this->Stack[stackPosition] /= magnitude;
this->Stack[stackPosition-1] /= magnitude;
this->Stack[stackPosition-2] /= magnitude;
}
break;
case VTK_PARSER_IHAT:
this->Stack[++stackPosition] = 1;
this->Stack[++stackPosition] = 0;
this->Stack[++stackPosition] = 0;
break;
case VTK_PARSER_JHAT:
this->Stack[++stackPosition] = 0;
this->Stack[++stackPosition] = 1;
this->Stack[++stackPosition] = 0;
break;
case VTK_PARSER_KHAT:
this->Stack[++stackPosition] = 0;
this->Stack[++stackPosition] = 0;
this->Stack[++stackPosition] = 1;
break;
case VTK_PARSER_LESS_THAN:
this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] < this->Stack[stackPosition]);
stackPosition--;
break;
case VTK_PARSER_GREATER_THAN:
this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] > this->Stack[stackPosition]);
stackPosition--;
break;
case VTK_PARSER_EQUAL_TO:
this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] == this->Stack[stackPosition]);
stackPosition--;
break;
case VTK_PARSER_AND:
this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] && this->Stack[stackPosition]);
stackPosition--;
break;
case VTK_PARSER_OR:
this->Stack[stackPosition-1] = (this->Stack[stackPosition-1] || this->Stack[stackPosition]);
stackPosition--;
break;
case VTK_PARSER_IF:
{
// Stack[stackPosition]=Stack[2] refers to the bool
// argument of if(bool,valtrue,valfalse). Stack[1] is valtrue, and
// Stack[0] is valfalse.
int result = stackPosition - 2;
int valFalse = stackPosition - 2;
int valTrue = stackPosition - 1;
int boolArg = stackPosition;
if (this->Stack[boolArg] != 0.0)
this->Stack[result] = this->Stack[valTrue];
else
this->Stack[result] = this->Stack[valFalse];
stackPosition -= 2;
break;
}
case VTK_PARSER_VECTOR_IF:
{
int xResult = stackPosition - 6;
int yResult = stackPosition - 5;
int zResult = stackPosition - 4;
int xValFalse = stackPosition - 6;
int yValFalse = stackPosition - 5;
int zValFalse = stackPosition - 4;
int xValTrue = stackPosition - 3;
int yValTrue = stackPosition - 2;
int zValTrue = stackPosition - 1;
int boolArg = stackPosition;
if (this->Stack[boolArg] != 0.0)
{
this->Stack[xResult] = this->Stack[xValTrue];
this->Stack[yResult] = this->Stack[yValTrue];
this->Stack[zResult] = this->Stack[zValTrue];
}
else
{
this->Stack[xResult] = this->Stack[xValFalse];
this->Stack[yResult] = this->Stack[yValFalse];
this->Stack[zResult] = this->Stack[zValFalse];
}
stackPosition -= 4;
break;
}
default:
if ((this->ByteCode[numBytesProcessed] -
VTK_PARSER_BEGIN_VARIABLES) < this->GetNumberOfScalarVariables())
{
this->Stack[++stackPosition] =
this->ScalarVariableValues[this->ByteCode[numBytesProcessed] -
VTK_PARSER_BEGIN_VARIABLES];
}
else
{
int vectorNum = this->ByteCode[numBytesProcessed] -
VTK_PARSER_BEGIN_VARIABLES - this->GetNumberOfScalarVariables();
this->Stack[++stackPosition] =
this->VectorVariableValues[vectorNum][0];
this->Stack[++stackPosition] =
this->VectorVariableValues[vectorNum][1];
this->Stack[++stackPosition] =
this->VectorVariableValues[vectorNum][2];
}
}
}
this->StackPointer = stackPosition;
this->EvaluateMTime.Modified();
return true;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::IsScalarResult()
{
if (this->VariableMTime.GetMTime() > this->EvaluateMTime.GetMTime() ||
this->FunctionMTime.GetMTime() > this->EvaluateMTime.GetMTime())
{
if (this->Evaluate() == false)
return 0;
}
return (this->StackPointer == 0);
}
//-----------------------------------------------------------------------------
double vtkFunctionParser::GetScalarResult()
{
if (!(this->IsScalarResult()))
{
vtkErrorMacro("GetScalarResult: no valid scalar result");
return VTK_PARSER_ERROR_RESULT;
}
return this->Stack[0];
}
int vtkFunctionParser::IsVectorResult()
{
if (this->VariableMTime.GetMTime() > this->EvaluateMTime.GetMTime() ||
this->FunctionMTime.GetMTime() > this->EvaluateMTime.GetMTime())
{
if (this->Evaluate() == false)
return 0;
}
return (this->StackPointer == 2);
}
//-----------------------------------------------------------------------------
double *vtkFunctionParser::GetVectorResult()
{
if (!(this->IsVectorResult()))
{
vtkErrorMacro("GetVectorResult: no valid vector result");
return vtkParserVectorErrorResult;
}
return this->Stack;
}
//-----------------------------------------------------------------------------
const char* vtkFunctionParser::GetScalarVariableName(int i)
{
if (i >= 0 && i < this->GetNumberOfScalarVariables())
{
return this->ScalarVariableNames[i].c_str();
}
return NULL;
}
//-----------------------------------------------------------------------------
const char* vtkFunctionParser::GetVectorVariableName(int i)
{
if (i >= 0 && i < this->GetNumberOfVectorVariables())
{
return this->VectorVariableNames[i].c_str();
}
return NULL;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::IsVariableName(int currentIndex)
{
for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
{
if (strncmp(this->ScalarVariableNames[i].c_str(), &this->Function[currentIndex],
this->ScalarVariableNames[i].size()) == 0)
{
return 1;
}
}
for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
{
if (strncmp(this->VectorVariableNames[i].c_str(), &this->Function[currentIndex],
this->VectorVariableNames[i].size()) == 0)
{
return 1;
}
}
return 0;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::IsElementaryOperator(int op)
{
return strchr("+-.*/^", op) != NULL;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::SetScalarVariableValue(const char* inVariableName,
double value)
{
char* variableName = this->RemoveSpacesFrom(inVariableName);
for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
{
if (strcmp(variableName, this->ScalarVariableNames[i].c_str()) == 0)
{
if (this->ScalarVariableValues[i] != value)
{
this->ScalarVariableValues[i] = value;
this->VariableMTime.Modified();
this->Modified();
}
delete [] variableName;
return;
}
}
this->ScalarVariableValues.push_back(value);
this->ScalarVariableNames.push_back(variableName);
this->VariableMTime.Modified();
this->Modified();
delete [] variableName;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::SetScalarVariableValue(int i, double value)
{
if (i < 0 || i >= this->GetNumberOfScalarVariables())
{
return;
}
if (this->ScalarVariableValues[i] != value)
{
this->ScalarVariableValues[i] = value;
this->VariableMTime.Modified();
}
this->Modified();
}
//-----------------------------------------------------------------------------
double vtkFunctionParser::GetScalarVariableValue(const char* inVariableName)
{
char* variableName = this->RemoveSpacesFrom(inVariableName);
for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
{
if (strcmp(variableName, this->ScalarVariableNames[i].c_str()) == 0)
{
delete [] variableName;
return this->ScalarVariableValues[i];
}
}
vtkErrorMacro("GetScalarVariableValue: scalar variable name " << variableName
<< " does not exist");
delete [] variableName;
return VTK_PARSER_ERROR_RESULT;
}
//-----------------------------------------------------------------------------
double vtkFunctionParser::GetScalarVariableValue(int i)
{
if (i < 0 || i >= this->GetNumberOfScalarVariables())
{
vtkErrorMacro("GetScalarVariableValue: scalar variable number " << i
<< " does not exist");
return VTK_PARSER_ERROR_RESULT;
}
return this->ScalarVariableValues[i];
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::SetVectorVariableValue(const char* inVariableName,
double xValue, double yValue,
double zValue)
{
char* variableName = this->RemoveSpacesFrom(inVariableName);
for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
{
if (strcmp(variableName, this->VectorVariableNames[i].c_str()) == 0)
{
if (this->VectorVariableValues[i][0] != xValue ||
this->VectorVariableValues[i][1] != yValue ||
this->VectorVariableValues[i][2] != zValue)
{
this->VectorVariableValues[i][0] = xValue;
this->VectorVariableValues[i][1] = yValue;
this->VectorVariableValues[i][2] = zValue;
this->VariableMTime.Modified();
this->Modified();
}
delete [] variableName;
return;
}
}
this->VectorVariableNames.push_back(variableName);
vtkTuple<double, 3> val;
val[0] = xValue;
val[1] = yValue;
val[2] = zValue;
this->VectorVariableValues.push_back(val);
this->VariableMTime.Modified();
this->Modified();
delete [] variableName;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::SetVectorVariableValue(int i, double xValue,
double yValue, double zValue)
{
if (i < 0 || i >= this->GetNumberOfVectorVariables())
{
return;
}
if (this->VectorVariableValues[i][0] != xValue ||
this->VectorVariableValues[i][1] != yValue ||
this->VectorVariableValues[i][2] != zValue)
{
this->VectorVariableValues[i][0] = xValue;
this->VectorVariableValues[i][1] = yValue;
this->VectorVariableValues[i][2] = zValue;
this->VariableMTime.Modified();
this->Modified();
}
}
//-----------------------------------------------------------------------------
double* vtkFunctionParser::GetVectorVariableValue(const char* inVariableName)
{
char* variableName = this->RemoveSpacesFrom(inVariableName);
for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
{
if (strcmp(variableName, this->VectorVariableNames[i].c_str()) == 0)
{
delete [] variableName;
return this->VectorVariableValues[i].GetData();
}
}
vtkErrorMacro("GetVectorVariableValue: vector variable name " << variableName
<< " does not exist");
delete [] variableName;
return vtkParserVectorErrorResult;
}
//-----------------------------------------------------------------------------
double* vtkFunctionParser::GetVectorVariableValue(int i)
{
if (i < 0 || i >= this->GetNumberOfVectorVariables())
{
vtkErrorMacro("GetVectorVariableValue: vector variable number " << i
<< " does not exist");
return vtkParserVectorErrorResult;
}
return this->VectorVariableValues[i].GetData();
}
//-----------------------------------------------------------------------------
char* vtkFunctionParser::RemoveSpacesFrom(const char* variableName)
{
int len = static_cast<int>(strlen(variableName));
int i;
char* resultString = new char[len+1];
char* out = resultString;
for(i=0; i < len; ++i)
{
if(variableName[i] != ' ')
{
*out++ = variableName[i];
}
}
*out = '\0';
return resultString;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::RemoveSpaces()
{
char *tempString;
int i, length;
this->FunctionLength = 0;
length = static_cast<int>(strlen(this->Function));
tempString = new char[length+1];
for (i = 0; i < length; i++)
{
if (!isspace(this->Function[i]))
{
tempString[this->FunctionLength] = this->Function[i];
this->FunctionLength++;
}
}
delete [] this->Function;
this->Function = new char[this->FunctionLength+1];
strncpy(this->Function, tempString,
static_cast<size_t>(this->FunctionLength));
this->Function[this->FunctionLength] = '\0';
delete [] tempString;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::OperatorWithinVariable(int idx)
{
char *tmpString = NULL;
for ( int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i ++ )
{
int end = 0;
if ( strchr( this->ScalarVariableNames[i].c_str(), this->Function[idx] ) != 0 )
{
if ( ( tmpString = strstr( this->Function, this->ScalarVariableNames[i].c_str() ) ) )
{
do
{
if (tmpString)
{
int start = static_cast<int>(tmpString - this->Function);
end = start + static_cast<int>( this->ScalarVariableNames[i].size() );
// the variable being investigated does contain an operator (at idx)
if ( start <= idx && idx <= end ) return 1;
// just in case of one or even more occurrences of the
// variable name (being investigated) preceding "idx" in this->Function[]
// As suggested by 7islands, a greedy search is used here
if ( end <= idx ) // to save strstr() whenever possible
tmpString = strstr( this->Function + end, this->ScalarVariableNames[i].c_str() );
}
else break;
} while ( end <= idx );
}
}
}
for ( int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i ++ )
{
int end = 0;
if ( strchr( this->VectorVariableNames[i].c_str(), this->Function[idx] ) != 0 )
{
if ( ( tmpString = strstr( this->Function, this->VectorVariableNames[i].c_str() ) ) )
{
do
{
if (tmpString)
{
int start = static_cast<int>(tmpString - this->Function);
end = start + static_cast<int>( this->VectorVariableNames[i].size() );
// the variable being investigated does contain an operator (at idx)
if ( start <= idx && idx <= end ) return 1;
// just in case of one or even more occurrences of the
// variable name (being investigated) preceding "idx" in this->Function[]
// As suggested by 7islands, a greedy search is used here
if ( end <= idx ) // to save strstr() whenever possible
tmpString = strstr( this->Function + end, this->VectorVariableNames[i].c_str() );
}
else break;
} while ( end <= idx );
}
}
}
return 0;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::CheckSyntax()
{
int pos = -1;
char* error = NULL;
this->CheckExpression(pos, &error);
if(pos != -1 || error)
{
vtkErrorMacro(<< error << "; " << " see position " << pos);
return 0;
}
else
{
return 1;
}
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::CopyParseError(int &position, char **error)
{
if(!error)
{
return;
}
position = this->ParseErrorPositon;
*error = this->ParseError;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::BuildInternalFunctionStructure()
{
delete [] this->ByteCode;
this->ByteCode = NULL;
delete [] this->Immediates;
this->Immediates = NULL;
delete [] this->Stack;
this->Stack = NULL;
this->ByteCodeSize = this->ImmediatesSize = this->StackSize = 0;
this->StackPointer = 0;
this->BuildInternalSubstringStructure(0, this->FunctionLength - 1);
return 1;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::BuildInternalSubstringStructure(int beginIndex,
int endIndex)
{
int mathFunctionNum, beginIndex2;
int opNum, parenthesisCount, i;
// in order of reverse precedence
static const char* const elementaryMathOps = "|&=<>+-.*/^";
if (this->IsSubstringCompletelyEnclosed(beginIndex, endIndex))
{
this->BuildInternalSubstringStructure(beginIndex+1, endIndex-1);
return;
}
if (this->Function[beginIndex] == '-')
{
if (this->IsSubstringCompletelyEnclosed(beginIndex+1, endIndex))
{
this->BuildInternalSubstringStructure(beginIndex+2, endIndex-1);
this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
return;
}
if (this->GetMathFunctionNumber(beginIndex+1) > 0 &&
this->FindEndOfMathFunction(beginIndex+1) == endIndex)
{
this->BuildInternalSubstringStructure(beginIndex+1, endIndex);
this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
return;
}
}
if (this->Function[beginIndex] == '+')
{
if (this->IsSubstringCompletelyEnclosed(beginIndex+1, endIndex))
{
this->BuildInternalSubstringStructure(beginIndex+2, endIndex-1);
this->AddInternalByte(VTK_PARSER_UNARY_PLUS);
return;
}
if (this->GetMathFunctionNumber(beginIndex+1) > 0 &&
this->FindEndOfMathFunction(beginIndex+1) == endIndex)
{
this->BuildInternalSubstringStructure(beginIndex+1, endIndex);
this->AddInternalByte(VTK_PARSER_UNARY_PLUS);
return;
}
}
if (isalpha(this->Function[beginIndex]))
{
mathFunctionNum = this->GetMathFunctionNumber(beginIndex);
if (mathFunctionNum > 0)
{
beginIndex2 = beginIndex;
while (beginIndex2 <= endIndex && this->Function[beginIndex2] != '(')
{
beginIndex2++;
}
if (this->IsSubstringCompletelyEnclosed(beginIndex2, endIndex))
{
if ((mathFunctionNum == VTK_PARSER_MIN) ||
(mathFunctionNum == VTK_PARSER_MAX) ||
(mathFunctionNum == VTK_PARSER_CROSS))
{
parenthesisCount = 0;
for (i = endIndex-1; i > beginIndex2; i--)
{
if (this->Function[i] == ')')
{
parenthesisCount++;
}
else if (this->Function[i] == '(')
{
parenthesisCount--;
}
if (parenthesisCount == 0 && this->Function[i] == ',')
{
this->BuildInternalSubstringStructure(beginIndex2+1, i-1);
this->BuildInternalSubstringStructure(i+1, endIndex-1);
this->AddInternalByte(
static_cast<unsigned char>(mathFunctionNum));
this->StackPointer--;
return;
}
} // for (i = endIndex-1; i > beginIndex2; i--)
} // VTK_PARSER_MIN, ...
if (mathFunctionNum == VTK_PARSER_IF)
{
// if(bool, valtrue, valfalse)
int numCommas = 0;
int secondCommaIndex = endIndex;
parenthesisCount = 0;
for (i = endIndex-1; i > beginIndex2; i--)
{
if (this->Function[i] == ')')
{
parenthesisCount++;
}
else if (this->Function[i] == '(')
{
parenthesisCount--;
}
if (parenthesisCount == 0 && this->Function[i] == ',')
{
numCommas++;
if (numCommas == 1)
{
// third arg
secondCommaIndex = i;
this->BuildInternalSubstringStructure(i+1, endIndex-1);
}
else // numCommas == 2
{
// second arg
this->BuildInternalSubstringStructure(i+1, secondCommaIndex-1);
// first arg
this->BuildInternalSubstringStructure(beginIndex2+1, i-1);
this->AddInternalByte(
static_cast<unsigned char>(mathFunctionNum));
this->StackPointer--;
return;
}
} // if (parenthesisCount == 0 ... )
} // for (i = endIndex-1; i > beginIndex2; i--)
} // VTK_PARSER_IF, ...
this->BuildInternalSubstringStructure(beginIndex2+1, endIndex-1);
this->AddInternalByte(static_cast<unsigned char>(mathFunctionNum));
return;
} // if (this->IsSubstringCompletelyEnclosed ... )
} // if (mathFunctionNum > 0)
} // if (isalpha(this->Function[beginIndex]))
int numMathOps = static_cast<int>(strlen(elementaryMathOps));
for (opNum = 0; opNum < numMathOps; opNum++)
{
parenthesisCount = 0;
for (i = endIndex; i > beginIndex; i--)
{
if (this->Function[i] == ')')
{
parenthesisCount++;
}
else if (this->Function[i] == '(')
{
parenthesisCount--;
}
if (parenthesisCount == 0 &&
// arithmetic or boolean
this->Function[i] == elementaryMathOps[opNum] &&
!((this->Function[i] == '-' || this->Function[i] == '+') &&
(this->IsElementaryOperator(this->Function[i-1]) ||
this->Function[i-1] == '(' ||
((this->Function[i-1] == 'e' || this->Function[i-1] == 'E') &&
i > 1 &&
isdigit(this->Function[i-2])))) &&
!(this->Function[i] == '.' &&
(i+1 < this->FunctionLength) &&
(isdigit(this->Function[i+1]))) &&
!this->OperatorWithinVariable(i))
{
this->BuildInternalSubstringStructure(beginIndex, i-1);
this->BuildInternalSubstringStructure(i+1, endIndex);
this->AddInternalByte(
this->GetElementaryOperatorNumber(elementaryMathOps[opNum]));
this->StackPointer--;
return;
}
} // end of for (i = endIndex; i > beginIndex; i--)
} // end of for (opNum = 0; opNum < numMathOps; opNum++)
beginIndex2 = beginIndex;
bool unaryMinus = false;
if (this->Function[beginIndex] == '-' ||
this->Function[beginIndex] == '+')
{
if (this->Function[beginIndex] == '-')
unaryMinus = true;
beginIndex2++;
}
this->AddInternalByte(this->GetOperandNumber(beginIndex2));
this->StackPointer++;
if (this->StackPointer > this->StackSize)
{
this->StackSize++;
}
if (beginIndex2 > beginIndex)
{
if (unaryMinus)
this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
else
this->AddInternalByte(VTK_PARSER_UNARY_PLUS);
}
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::AddInternalByte(unsigned char newByte)
{
int i;
unsigned char *tempByteCode = new unsigned char[this->ByteCodeSize];
for (i = 0; i < this->ByteCodeSize; i++)
{ // Copy current byte code to a temporary array
tempByteCode[i] = this->ByteCode[i];
}
delete [] this->ByteCode;
// Allocate space for new byte.
this->ByteCode = new unsigned char[this->ByteCodeSize + 1];
// Copy contents of temporary array back to ByteCode.
for (i = 0; i < this->ByteCodeSize; i++)
{
this->ByteCode[i] = tempByteCode[i];
}
this->ByteCode[this->ByteCodeSize] = newByte;
this->ByteCodeSize++;
delete [] tempByteCode;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::IsSubstringCompletelyEnclosed(int beginIndex,
int endIndex)
{
int i, parenthesisCount;
if ( this->Function[beginIndex] == '(' && this->Function[endIndex]== ')' )
{
parenthesisCount = 1;
for (i = beginIndex + 1; i < endIndex; i++)
{
if (this->Function[i] == '(' )
{
parenthesisCount++;
}
else if(this->Function[i] == ')' )
{
parenthesisCount--;
}
if (parenthesisCount == 0)
{
break;
}
}
if (i == endIndex)
{
return 1;
}
}
return 0;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::GetMathFunctionNumber(int currentIndex)
{
// For addition of any new math function, please update
// function GetMathFunctionNumberByCheckingParenthesis()
if (strncmp(&this->Function[currentIndex], "abs", 3) == 0)
{
return VTK_PARSER_ABSOLUTE_VALUE;
}
if (strncmp(&this->Function[currentIndex], "exp", 3) == 0)
{
return VTK_PARSER_EXPONENT;
}
if (strncmp(&this->Function[currentIndex], "ceil", 4) == 0)
{
return VTK_PARSER_CEILING;
}
if (strncmp(&this->Function[currentIndex], "floor", 5) == 0)
{
return VTK_PARSER_FLOOR;
}
if (strncmp(&this->Function[currentIndex], "ln", 2) == 0)
{
return VTK_PARSER_LOGARITHME;
}
if (strncmp(&this->Function[currentIndex], "log10", 5) == 0)
{
return VTK_PARSER_LOGARITHM10;
}
if (strncmp(&this->Function[currentIndex], "log", 3) == 0)
{
vtkErrorMacro("The use of log function is being deprecated. "
"Please use log10 or ln instead");
return VTK_PARSER_LOGARITHM;
}
if (strncmp(&this->Function[currentIndex], "sqrt", 4) == 0)
{
return VTK_PARSER_SQUARE_ROOT;
}
if (strncmp(&this->Function[currentIndex], "sin", 3) == 0)
{
if (strncmp(&this->Function[currentIndex], "sinh", 4) == 0)
{
return VTK_PARSER_HYPERBOLIC_SINE;
}
return VTK_PARSER_SINE;
}
if (strncmp(&this->Function[currentIndex], "cos", 3) == 0)
{
if (strncmp(&this->Function[currentIndex], "cosh", 4) == 0)
{
return VTK_PARSER_HYPERBOLIC_COSINE;
}
return VTK_PARSER_COSINE;
}
if (strncmp(&this->Function[currentIndex], "tan", 3) == 0)
{
if (strncmp(&this->Function[currentIndex], "tanh", 4) == 0)
{
return VTK_PARSER_HYPERBOLIC_TANGENT;
}
return VTK_PARSER_TANGENT;
}
if (strncmp(&this->Function[currentIndex], "asin", 4) == 0)
{
return VTK_PARSER_ARCSINE;
}
if (strncmp(&this->Function[currentIndex], "acos", 4) == 0)
{
return VTK_PARSER_ARCCOSINE;
}
if (strncmp(&this->Function[currentIndex], "atan", 4) == 0)
{
return VTK_PARSER_ARCTANGENT;
}
if (strncmp(&this->Function[currentIndex], "min", 3) == 0)
{
return VTK_PARSER_MIN;
}
if (strncmp(&this->Function[currentIndex], "max", 3) == 0)
{
return VTK_PARSER_MAX;
}
if (strncmp(&this->Function[currentIndex], "cross", 5) == 0)
{
return VTK_PARSER_CROSS;
}
if (strncmp(&this->Function[currentIndex], "sign", 4) == 0)
{
return VTK_PARSER_SIGN;
}
if (strncmp(&this->Function[currentIndex], "mag", 3) == 0)
{
return VTK_PARSER_MAGNITUDE;
}
if (strncmp(&this->Function[currentIndex], "norm", 4) == 0)
{
return VTK_PARSER_NORMALIZE;
}
if (strncmp(&this->Function[currentIndex], "if", 2) == 0)
{
return VTK_PARSER_IF;
}
return 0;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::GetMathFunctionNumberByCheckingParenthesis
( int currentIndex )
{
// This function assumes that RemoveSpaces() has been called and
// hence involves the check on the '(' that immediately follows a
// valid function. Addressing '(' here instead of in CheckSyntax()
// allows for early detection of grammar errors, i.e., lack of '(',
// and hence simplifies the parsing process.
// For addition of any new math function, please update NUMBFUNCS
// and add an entry to each of the three arrays below.
const int NUMBFUNCS = 24;
static int charsLens[NUMBFUNCS] = { 4, 4, 5, 6,
3, 6, 4, 5,
4, 5, 4, 5,
4, 5, 5, 5,
5, 4, 4, 6,
5, 4, 5, 3
};
static int funcNumbs[NUMBFUNCS] = { VTK_PARSER_ABSOLUTE_VALUE,
VTK_PARSER_EXPONENT,
VTK_PARSER_CEILING,
VTK_PARSER_FLOOR,
VTK_PARSER_LOGARITHME,
VTK_PARSER_LOGARITHM10,
VTK_PARSER_LOGARITHM,
VTK_PARSER_SQUARE_ROOT,
VTK_PARSER_SINE,
VTK_PARSER_HYPERBOLIC_SINE,
VTK_PARSER_COSINE,
VTK_PARSER_HYPERBOLIC_COSINE,
VTK_PARSER_TANGENT,
VTK_PARSER_HYPERBOLIC_TANGENT,
VTK_PARSER_ARCSINE,
VTK_PARSER_ARCCOSINE,
VTK_PARSER_ARCTANGENT,
VTK_PARSER_MIN,
VTK_PARSER_MAX,
VTK_PARSER_CROSS,
VTK_PARSER_SIGN,
VTK_PARSER_MAGNITUDE,
VTK_PARSER_NORMALIZE,
VTK_PARSER_IF
};
static char funcNames[NUMBFUNCS][10] = { "abs(", "exp(", "ceil(", "floor(",
"ln(", "log10(", "log(", "sqrt(",
"sin(", "sinh(", "cos(", "cosh(",
"tan(", "tanh(", "asin(", "acos(",
"atan(", "min(", "max(", "cross(",
"sign(", "mag(", "norm(", "if("
};
int isMatched = 0;
int retNumber = 0;
for ( int i = 0; i < NUMBFUNCS && isMatched == 0; i ++ )
{
isMatched = ( strncmp( this->Function + currentIndex,
funcNames[i], charsLens[i]
) == 0
) ? 1 : 0;
retNumber = isMatched * funcNumbs[i];
}
return retNumber;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::GetMathFunctionStringLength(int mathFunctionNumber)
{
switch (mathFunctionNumber)
{
case VTK_PARSER_LOGARITHME:
case VTK_PARSER_IF:
return 2;
case VTK_PARSER_ABSOLUTE_VALUE:
case VTK_PARSER_EXPONENT:
case VTK_PARSER_LOGARITHM:
case VTK_PARSER_SINE:
case VTK_PARSER_COSINE:
case VTK_PARSER_TANGENT:
case VTK_PARSER_MAGNITUDE:
case VTK_PARSER_MIN:
case VTK_PARSER_MAX:
return 3;
case VTK_PARSER_CEILING:
case VTK_PARSER_SQUARE_ROOT:
case VTK_PARSER_ARCSINE:
case VTK_PARSER_ARCCOSINE:
case VTK_PARSER_ARCTANGENT:
case VTK_PARSER_HYPERBOLIC_SINE:
case VTK_PARSER_HYPERBOLIC_COSINE:
case VTK_PARSER_HYPERBOLIC_TANGENT:
case VTK_PARSER_NORMALIZE:
case VTK_PARSER_SIGN:
return 4;
case VTK_PARSER_FLOOR:
case VTK_PARSER_LOGARITHM10:
case VTK_PARSER_CROSS:
return 5;
default:
vtkWarningMacro("Unknown math function");
return 0;
}
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::GetMathConstantNumber(int currentIndex)
{
if (strncmp(&this->Function[currentIndex], "iHat", 4) == 0)
{
return VTK_PARSER_IHAT;
}
if (strncmp(&this->Function[currentIndex], "jHat", 4) == 0)
{
return VTK_PARSER_JHAT;
}
if (strncmp(&this->Function[currentIndex], "kHat", 4) == 0)
{
return VTK_PARSER_KHAT;
}
return 0;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::GetMathConstantStringLength(int mathConstantNumber)
{
switch (mathConstantNumber)
{
case VTK_PARSER_IHAT:
case VTK_PARSER_JHAT:
case VTK_PARSER_KHAT:
return 4;
default:
vtkWarningMacro("Unknown math constant");
return 0;
}
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::GetVariableNameLength(int variableNumber)
{
if (variableNumber < this->GetNumberOfScalarVariables())
{
return static_cast<int>(this->ScalarVariableNames[variableNumber].size());
}
else
{
return static_cast<int>(
this->VectorVariableNames[variableNumber -
this->GetNumberOfScalarVariables()].size());
}
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::FindEndOfMathFunction(int beginIndex)
{
int i = beginIndex, parenthesisCount;
while (this->Function[i] != '(' )
{
i++;
}
i++;
for (parenthesisCount = 1; parenthesisCount > 0; ++i)
{
parenthesisCount += (this->Function[i] == '(' ? 1 :
(this->Function[i] == ')' ? -1 : 0));
}
return i - 1;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::FindEndOfMathConstant(int beginIndex)
{
if(int constantNumber = this->GetMathConstantNumber(beginIndex))
{
return beginIndex+this->GetMathConstantStringLength(constantNumber);
}
return beginIndex;
}
//-----------------------------------------------------------------------------
unsigned char vtkFunctionParser::GetElementaryOperatorNumber(char op)
{
static const char* const operators = "+-*/^";
int i;
if (op == '<')
{
return VTK_PARSER_LESS_THAN;
}
if (op == '>')
{
return VTK_PARSER_GREATER_THAN;
}
if (op == '=')
{
return VTK_PARSER_EQUAL_TO;
}
if (op == '&')
{
return VTK_PARSER_AND;
}
if (op == '|')
{
return VTK_PARSER_OR;
}
for(i = 0; i < 5; i++)
{
if (operators[i] == op)
{
return static_cast<unsigned char>(VTK_PARSER_ADD + i);
}
}
if (op == '.')
{
return VTK_PARSER_DOT_PRODUCT;
}
return 0;
}
//-----------------------------------------------------------------------------
unsigned char vtkFunctionParser::GetOperandNumber(int currentIndex)
{
int variableIndex = -1;
if (isdigit(this->Function[currentIndex]) ||
this->Function[currentIndex] == '.') // Number
{
double *tempImmediates = new double[this->ImmediatesSize];
for (int i = 0; i < this->ImmediatesSize; i++)
{ // Copy current immediates to a temporary array
tempImmediates[i] = this->Immediates[i];
}
delete [] this->Immediates;
// Allocate space for new immediate value.
this->Immediates = new double[this->ImmediatesSize + 1];
// Copy contents of temporary array back to Immediates.
for (int i = 0; i < this->ImmediatesSize; i++)
{
this->Immediates[i] = tempImmediates[i];
}
this->Immediates[this->ImmediatesSize] =
atof(&this->Function[currentIndex]);
this->ImmediatesSize++;
delete [] tempImmediates;
return VTK_PARSER_IMMEDIATE;
}
if (!strncmp(&this->Function[currentIndex], "iHat", 4))
{
return VTK_PARSER_IHAT;
}
if (!strncmp(&this->Function[currentIndex], "jHat", 4))
{
return VTK_PARSER_JHAT;
}
if (!strncmp(&this->Function[currentIndex], "kHat", 4))
{
return VTK_PARSER_KHAT;
}
bool scalarVar = false;
size_t currentLen = 0;
//Bug 7396. If a scalar variable name is a subset of a vector var name it will
//casue the scripting to crash. So instead of ending once we find a var name that matches in scalars
//we will also check vectors
for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
{ // Variable
if (strncmp(&this->Function[currentIndex], this->ScalarVariableNames[i].c_str(),
this->ScalarVariableNames[i].size()) == 0)
{
if (variableIndex == -1 ||
this->ScalarVariableNames[i].size() > currentLen )
{
currentLen = this->ScalarVariableNames[i].size();
variableIndex = i;
}
}
}
if (variableIndex >= 0)
{
scalarVar = true;
}
for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
{ // Variable
if (strncmp(&this->Function[currentIndex], this->VectorVariableNames[i].c_str(),
this->VectorVariableNames[i].size()) == 0)
{
if (variableIndex == -1
|| this->VectorVariableNames[i].size() > currentLen )
{
scalarVar = false;
currentLen = this->VectorVariableNames[i].size();
variableIndex = i;
}
}
}
if (variableIndex >= 0)
{
//add the offset if vector
variableIndex = scalarVar? variableIndex : (this->GetNumberOfScalarVariables() + variableIndex);
return static_cast<unsigned char>(
VTK_PARSER_BEGIN_VARIABLES + variableIndex);
}
return 0;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::RemoveScalarVariables()
{
this->ScalarVariableNames.clear();
this->ScalarVariableValues.clear();
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::RemoveVectorVariables()
{
this->VectorVariableNames.clear();
this->VectorVariableValues.clear();
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::CheckExpression(int &pos, char **error)
{
if(this->FunctionMTime.GetMTime() > this->CheckMTime.GetMTime())
{
// Need to parse again.
// Reset previous error cache.
this->ParseErrorPositon = -1;
this->SetParseError(0);
this->CopyParseError(pos, error);
}
else
{
this->CopyParseError(pos, error);
return;
}
this->CheckMTime.Modified();
this->RemoveSpaces();
int index = 0, parenthesisCount = 0, currentChar;
char* ptr;
int functionNumber, constantNumber;
int *expectCommaOnParenthesisCount = new int[this->FunctionLength];
int *expectTwoCommasOnParenthesisCount = new int[this->FunctionLength];
int i;
for (i = 0; i < this->FunctionLength; i++)
{
expectCommaOnParenthesisCount[i] = 0;
expectTwoCommasOnParenthesisCount[i] = 0;
}
while (1)
{
currentChar = this->Function[index];
bool breakToOuterLoop = false;
// Check for valid operand (must appear)
// Check for leading -
if (currentChar == '-')
{
currentChar = this->Function[++index];
if(index == this->FunctionLength)
{
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax error: unary minus with no operand");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
}
// Check for leading +
if (currentChar == '+')
{
currentChar = this->Function[++index];
if(index == this->FunctionLength)
{
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax error: unary plus with no operand");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
}
// Check for math function
if ((functionNumber = this->GetMathFunctionNumberByCheckingParenthesis(index)))
{
if ((functionNumber == VTK_PARSER_MIN) ||
(functionNumber == VTK_PARSER_MAX) ||
(functionNumber == VTK_PARSER_CROSS))
{
expectCommaOnParenthesisCount[parenthesisCount+1] = 1;
}
if (functionNumber == VTK_PARSER_IF)
{
expectTwoCommasOnParenthesisCount[parenthesisCount+1] = 1;
}
index += this->GetMathFunctionStringLength(functionNumber);
currentChar = this->Function[index];
// == currentChar should always be '(' here == a fix to Bug #9208
// since GetMathFunctionNumberByCheckingParenthesis() is employed above
//if ( currentChar != '(' )
// {
// vtkErrorMacro("Syntax error: input to math function not in "
// << "parentheses; see position " << index);
// delete [] expectCommaOnParenthesisCount;
// delete [] expectTwoCommasOnParenthesisCount;
// return 0;
// }
}
// Check for opening parenthesis
if( currentChar == '(' )
{
parenthesisCount++;
index++;
continue;
}
// Check for number
if(isdigit(currentChar) ||
(currentChar == '.' && isdigit(this->Function[index+1])))
{
double value=strtod(&this->Function[index], &ptr);
// ignore the return value, we just try to figure out
// the position of the pointer after the double value.
static_cast<void>(value);
index += int(ptr-&this->Function[index]);
currentChar = this->Function[index];
}
// Check for named constant
else if ((constantNumber = this->GetMathConstantNumber(index)))
{
index += this->GetMathConstantStringLength(constantNumber);
currentChar = this->Function[index];
}
// End parenthesis should indicate that the next character might be a
// comma. This is a hack because the while (currentChar == ') below checks
// for an incorrect number of commas.
else if (currentChar == ')' && this->Function[index - 1] != '(')
{
++index;
currentChar = this->Function[index];
}
else
{ // Check for variable
if (!this->IsVariableName(index))
{
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax error: expecting a variable name");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
index += this->GetVariableNameLength(this->GetOperandNumber(index) -
VTK_PARSER_BEGIN_VARIABLES);
currentChar = this->Function[index];
}
// Check for possible second number from min or max function
if (expectCommaOnParenthesisCount[parenthesisCount] > 0)
{
// Check for comma
if (currentChar == ',')
{
expectCommaOnParenthesisCount[parenthesisCount] += 1;
index++;
continue;
}
}
// Check for possible second or third number from if function
if (expectTwoCommasOnParenthesisCount[parenthesisCount] > 0)
{
// Check for comma
if (currentChar == ',')
{
expectTwoCommasOnParenthesisCount[parenthesisCount] += 1;
index++;
continue;
}
}
// Check for closing parenthesis
while ( currentChar == ')' )
{
if (expectCommaOnParenthesisCount[parenthesisCount] != 0 &&
expectCommaOnParenthesisCount[parenthesisCount] != 2)
{
// We can't be closing this function if
// expectCommaOnParenthesisCount[..] is not 2; either it was always
// 0 or it should have been incremented to 2.
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax Error: two parameters separated by commas expected");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
if (expectTwoCommasOnParenthesisCount[parenthesisCount] != 0 &&
expectTwoCommasOnParenthesisCount[parenthesisCount] != 3)
{
// We can't be closing this function if
// expectCommaOnParenthesisCount[..] is not 3; either it was always
// 0 or it should have been incremented to 3.
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax Error: three parameters separated by commas expected");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
parenthesisCount--;
if(parenthesisCount < 0)
{
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax Error: mismatched parenthesis");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
if( this->Function[index - 1] == '(' )
{
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax Error: empty parentheses");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
// Check for possible argument in a multiple argument function. In this
// case the next character might be a comman, so break out to the outer
// loop before incrementing index.
if ((expectCommaOnParenthesisCount[parenthesisCount] > 0 &&
expectCommaOnParenthesisCount[parenthesisCount] < 2) ||
(expectTwoCommasOnParenthesisCount[parenthesisCount] > 0 &&
expectTwoCommasOnParenthesisCount[parenthesisCount] < 3))
{
breakToOuterLoop = true;
break;
}
currentChar = this->Function[++index];
} // while ( currentChar == ')' )
// If necessary, break out to the outer loop.
if (breakToOuterLoop == true)
{
continue;
}
// If we get here, we have a legal operand and now a legal operator or
// end of string must follow.
// Check for EOS
// The only way to end the checking loop without error.
if (index == this->FunctionLength)
{
break;
}
// Check for operator
if(!this->IsElementaryOperator(currentChar) &&
currentChar != '<' &&
currentChar != '>' &&
currentChar != '=' &&
currentChar != '&' &&
currentChar != '|' &&
currentChar != ',')
{
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax error: operator expected");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
if (currentChar != ',')
{
// If we get here, we have an operand and an operator; the next loop will
// check for another operand (must appear)
index++;
}
} // while(1)
// Check that all opened parentheses are also closed
if(parenthesisCount > 0)
{
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax Error: missing closing parenthesis");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
// The string is ok
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::RemoveAllVariables()
{
this->RemoveScalarVariables();
this->RemoveVectorVariables();
}
//-----------------------------------------------------------------------------
vtkMTimeType vtkFunctionParser::GetMTime()
{
vtkMTimeType mTime = this->Superclass::GetMTime();
if (this->EvaluateMTime > mTime)
{
mTime = this->EvaluateMTime;
}
if (this->VariableMTime > mTime)
{
mTime = this->VariableMTime;
}
if (this->ParseMTime > mTime)
{
mTime = this->ParseMTime;
}
if (this->FunctionMTime > mTime)
{
mTime = this->FunctionMTime;
}
if (this->CheckMTime > mTime)
{
mTime = this->CheckMTime;
}
return mTime;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Function: "
<< (this->GetFunction() ? this->GetFunction() : "(none)") << endl;
os << indent << "FunctionWithSpaces: "
<< (this->FunctionWithSpaces ? this->FunctionWithSpaces : "(none)") << endl;
for (int i = 0, max = this->GetNumberOfScalarVariables(); i < max; i++)
{
os << indent << " " << this->GetScalarVariableName(i) << ": "
<< this->GetScalarVariableValue(i) << endl;
}
for (int i = 0, max = this->GetNumberOfVectorVariables(); i < max; i++)
{
os << indent << " " << this->GetVectorVariableName(i) << ": ("
<< this->GetVectorVariableValue(i)[0] << ", "
<< this->GetVectorVariableValue(i)[1] << ", "
<< this->GetVectorVariableValue(i)[2] << ")" << endl;
}
if (this->EvaluateMTime.GetMTime() > this->FunctionMTime.GetMTime() &&
this->EvaluateMTime.GetMTime() > this->VariableMTime.GetMTime() &&
(this->StackPointer == 0 || this->StackPointer == 2))
{
if (this->StackPointer == 0)
{
os << indent << "ScalarResult: " << this->GetScalarResult() << endl;
os << indent << "VectorResult: " << "(none)" << endl;
}
else if (this->StackPointer == 2)
{
os << indent << "ScalarResult: " << "(none)" << endl;
os << indent << "VectorResult: " << "("
<< this->GetVectorResult()[0] << ", "
<< this->GetVectorResult()[1] << ", "
<< this->GetVectorResult()[2] << ")" << endl;
}
}
else
{
os << indent << "ScalarResult: " << "(none)" << endl;
os << indent << "VectorResult: " << "(none)" << endl;
}
os << indent << "Replace Invalid Values: "
<< (this->GetReplaceInvalidValues() ? "On" : "Off") << endl;
os << indent << "Replacement Value: " << this->GetReplacementValue() << endl;
os << indent << "Parse Error Position: " << this->ParseErrorPositon << endl;
os << indent << "Parse Error: " << (this->ParseError ? this->ParseError : "NULL")
<< endl;
}
//-----------------------------------------------------------------------------
int vtkFunctionParser::FindPositionInOriginalFunction(const int &pos)
{
// Copy the value.
int origPos = pos;
if(this->Function && this->FunctionWithSpaces)
{
size_t withSpacesLen = strlen(this->FunctionWithSpaces);
size_t withoutSpacesLen = strlen(this->Function);
int counter = 0;
for(size_t i=0; i < withSpacesLen; ++i)
{
// If we have covered all the characters excluding the spaces.
if(counter == static_cast<int>(withoutSpacesLen) || counter == pos)
{
return origPos;
}
char currentChar = this->FunctionWithSpaces[i];
if(currentChar == ' ')
{
// Every time we hit a whitespace increment the origPos
// as the pos is counted without spaces.
++origPos;
continue;
}
// This needs to be incremented for all the characters except
// spaces.
++counter;
}
}
return origPos;
}
//-----------------------------------------------------------------------------
void vtkFunctionParser::UpdateNeededVariables()
{
this->ScalarVariableNeeded.clear();
this->ScalarVariableNeeded.resize(this->ScalarVariableNames.size(), false);
this->VectorVariableNeeded.clear();
this->VectorVariableNeeded.resize(this->VectorVariableNames.size(), false);
unsigned char numscalars = static_cast<unsigned char>(this->GetNumberOfScalarVariables());
for (int cc=0; cc < this->ByteCodeSize; ++cc)
{
unsigned char code = this->ByteCode[cc];
if (code < VTK_PARSER_BEGIN_VARIABLES)
{
continue;
}
code -= VTK_PARSER_BEGIN_VARIABLES;
if (code >= numscalars)
{
this->VectorVariableNeeded[code - numscalars] = true;
}
else
{
this->ScalarVariableNeeded[code] = true;
}
}
}
//-----------------------------------------------------------------------------
bool vtkFunctionParser::GetScalarVariableNeeded(int i)
{
if (i < 0 || i >= static_cast<int>(this->ScalarVariableNeeded.size()))
{
return false;
}
return this->ScalarVariableNeeded[i];
}
//-----------------------------------------------------------------------------
bool vtkFunctionParser::GetScalarVariableNeeded(const char* inVariableName)
{
char* variableName = this->RemoveSpacesFrom(inVariableName);
std::vector<std::string>::const_iterator iter = std::find(
this->ScalarVariableNames.begin(), this->ScalarVariableNames.end(),
std::string(variableName));
delete [] variableName;
if (iter != this->ScalarVariableNames.end())
{
return this->GetScalarVariableNeeded(
static_cast<int>(iter - this->ScalarVariableNames.begin()));
}
else
{
vtkErrorMacro("GetScalarVariableNeeded: scalar variable name " << variableName
<< " does not exist");
return false;
}
}
//-----------------------------------------------------------------------------
bool vtkFunctionParser::GetVectorVariableNeeded(int i)
{
if (i < 0 || i >= static_cast<int>(this->VectorVariableNeeded.size()))
{
return false;
}
return this->VectorVariableNeeded[i];
}
//-----------------------------------------------------------------------------
bool vtkFunctionParser::GetVectorVariableNeeded(const char* inVariableName)
{
char* variableName = this->RemoveSpacesFrom(inVariableName);
std::vector<std::string>::const_iterator iter = std::find(
this->VectorVariableNames.begin(), this->VectorVariableNames.end(),
std::string(variableName));
delete [] variableName;
if (iter != this->VectorVariableNames.end())
{
return this->GetVectorVariableNeeded(
static_cast<int>(iter - this->VectorVariableNames.begin()));
}
else
{
vtkErrorMacro("GetVectorVariableNeeded: scalar variable name " << variableName
<< " does not exist");
return false;
}
}