Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1995 lines
56 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkFunctionParser.cxx,v $
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 <ctype.h>
vtkCxxRevisionMacro(vtkFunctionParser, "$Revision: 1.32 $");
vtkStandardNewMacro(vtkFunctionParser);
static double vtkParserVectorErrorResult[3] = { VTK_PARSER_ERROR_RESULT,
VTK_PARSER_ERROR_RESULT,
VTK_PARSER_ERROR_RESULT };
vtkFunctionParser::vtkFunctionParser()
{
this->NumberOfScalarVariables = 0;
this->NumberOfVectorVariables = 0;
this->ScalarVariableNames = NULL;
this->VectorVariableNames = NULL;
this->ScalarVariableValues = NULL;
this->VectorVariableValues = NULL;
this->Function = 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->ReplaceInvalidValues = 0;
this->ReplacementValue = 0.0;
}
vtkFunctionParser::~vtkFunctionParser()
{
int i;
if (this->ScalarVariableNames)
{
for (i = 0; i < this->NumberOfScalarVariables; i++)
{
delete [] this->ScalarVariableNames[i];
this->ScalarVariableNames[i] = NULL;
}
delete [] this->ScalarVariableNames;
this->ScalarVariableNames = NULL;
}
if (this->VectorVariableNames)
{
for (i = 0; i < this->NumberOfVectorVariables; i++)
{
delete [] this->VectorVariableNames[i];
this->VectorVariableNames[i] = NULL;
}
delete [] this->VectorVariableNames;
this->VectorVariableNames = NULL;
}
if (this->ScalarVariableValues)
{
delete [] this->ScalarVariableValues;
this->ScalarVariableValues = NULL;
}
if (this->VectorVariableValues)
{
for (i = 0; i < this->NumberOfVectorVariables; i++)
{
delete [] this->VectorVariableValues[i];
this->VectorVariableValues[i] = NULL;
}
delete [] this->VectorVariableValues;
this->VectorVariableValues = NULL;
}
if (this->Function)
{
delete [] this->Function;
this->Function = NULL;
}
if (this->ByteCode)
{
delete [] this->ByteCode;
this->ByteCode = NULL;
}
if (this->Immediates)
{
delete [] this->Immediates;
this->Immediates = NULL;
}
if (this->Stack)
{
delete [] this->Stack;
this->Stack = NULL;
}
}
void vtkFunctionParser::SetFunction(const char *function)
{
if (this->Function && function && strcmp(this->Function,function) == 0)
{
return;
}
if (this->Function)
{
delete [] this->Function;
}
if (function)
{
this->Function = new char[strlen(function)+1];
strcpy(this->Function,function);
}
else
{
this->Function = NULL;
}
this->FunctionMTime.Modified();
this->Modified();
}
int vtkFunctionParser::Parse()
{
int result;
int i;
if (this->Function == NULL)
{
vtkErrorMacro("Parse: no function has been set");
return 0;
}
this->RemoveSpaces();
result = this->CheckSyntax();
if (!result)
{
return 0;
}
result = this->BuildInternalFunctionStructure();
if (!result)
{
vtkErrorMacro("Parse: Error creating internal structure for parse string");
return 0;
}
// need to make sure that the ambiguous operators are correct
// - scalar/vector +
// - scalar/vector -
// - scalar/vector unary minus
// - * (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->NumberOfScalarVariables) ||
(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;
}
}
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_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))
{
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))
{
vtkErrorMacro("addition 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)
{
vtkErrorMacro("expecting either 2 scalars or a scalar and"
<< " a vector");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_DIVIDE:
if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
{
vtkErrorMacro("can't divide vectors");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_POWER:
if (tempStack[tempStackPtr] == 1)
{
vtkErrorMacro("can't raise a vector to a power");
return 0;
}
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)
{
vtkErrorMacro("expecting a scalar, but got a vector");
return 0;
}
break;
case VTK_PARSER_MIN:
if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
{
vtkErrorMacro("can't apply min to vectors");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_MAX:
if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1)
{
vtkErrorMacro("can't apply max to vectors");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_VECTOR_UNARY_MINUS:
if (tempStack[tempStackPtr] == 0)
{
this->ByteCode[i] = VTK_PARSER_UNARY_MINUS;
}
break;
case VTK_PARSER_DOT_PRODUCT:
if (tempStack[tempStackPtr] == 0 || tempStack[tempStackPtr-1] == 0)
{
vtkErrorMacro("dot product does not operate on scalars");
return 0;
}
tempStack[tempStackPtr-1] = 0;
tempStackPtr--;
break;
case VTK_PARSER_VECTOR_ADD:
if (tempStack[tempStackPtr] != 1 && tempStack[tempStackPtr-1] != 1)
{
this->ByteCode[i] = VTK_PARSER_ADD;
}
else if ((tempStack[tempStackPtr] == 0 &&
tempStack[tempStackPtr-1] != 0) ||
(tempStack[tempStackPtr] != 0 &&
tempStack[tempStackPtr-1] == 0))
{
vtkErrorMacro("addition expects either 2 vectors or 2 scalars");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_VECTOR_SUBTRACT:
if (tempStack[tempStackPtr] != 1 && tempStack[tempStackPtr-1] != 1)
{
this->ByteCode[i] = VTK_PARSER_SUBTRACT;
}
else if ((tempStack[tempStackPtr] == 0 &&
tempStack[tempStackPtr-1] != 0) ||
(tempStack[tempStackPtr] != 0 &&
tempStack[tempStackPtr-1] == 0))
{
vtkErrorMacro("subtraction expects either 2 vectors or 2 scalars");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_SCALAR_TIMES_VECTOR:
if (tempStack[tempStackPtr] == 0 && tempStack[tempStackPtr-1] == 0)
{
this->ByteCode[i] = VTK_PARSER_MULTIPLY;
}
else if (tempStack[tempStackPtr-1] == 1 &&
tempStack[tempStackPtr] == 0)
{
this->ByteCode[i] = VTK_PARSER_VECTOR_TIMES_SCALAR;
}
else
{
vtkErrorMacro("expecting a scalar followed by a vector");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_VECTOR_TIMES_SCALAR:
if (tempStack[tempStackPtr] == 0 && tempStack[tempStackPtr-1] == 0)
{
this->ByteCode[i] = VTK_PARSER_MULTIPLY;
}
else if (tempStack[tempStackPtr-1] == 0 &&
tempStack[tempStackPtr] == 1)
{
this->ByteCode[i] = VTK_PARSER_SCALAR_TIMES_VECTOR;
}
else
{
vtkErrorMacro("expecting a vector followed by a scalar");
return 0;
}
tempStackPtr--;
break;
case VTK_PARSER_MAGNITUDE:
if (tempStack[tempStackPtr] == 0)
{
vtkErrorMacro("magnitude expects a vector, but got a scalar");
return 0;
}
tempStack[tempStackPtr] = 0;
break;
case VTK_PARSER_NORMALIZE:
if (tempStack[tempStackPtr] == 0)
{
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;
default:
if ((this->ByteCode[i] - VTK_PARSER_BEGIN_VARIABLES) <
this->NumberOfScalarVariables)
{
tempStackPtr++;
tempStack[tempStackPtr] = 0;
}
else
{
tempStackPtr++;
tempStack[tempStackPtr] = 1;
}
}
}
delete [] tempStack;
return 1;
}
void vtkFunctionParser::Evaluate()
{
int numBytesProcessed;
int numImmediatesProcessed = 0;
int stackPosition = -1;
double magnitude;
this->StackPointer = -1;
if (this->FunctionMTime.GetMTime() > this->ParseMTime.GetMTime())
{
if (this->Parse() == 0)
{
return;
}
}
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_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;
}
}
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 logarithm of a negative value");
return;
}
}
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 logarithm of a negative value");
return;
}
}
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 logarithm of a negative value");
return;
}
}
else
{
this->Stack[stackPosition] =
log(this->Stack[stackPosition])/log((double)10);
}
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;
}
}
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");
return;
}
}
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");
return;
}
}
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_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_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_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;
default:
if ((this->ByteCode[numBytesProcessed] -
VTK_PARSER_BEGIN_VARIABLES) < this->NumberOfScalarVariables)
{
this->Stack[++stackPosition] =
this->ScalarVariableValues[this->ByteCode[numBytesProcessed] -
VTK_PARSER_BEGIN_VARIABLES];
}
else
{
int vectorNum = this->ByteCode[numBytesProcessed] -
VTK_PARSER_BEGIN_VARIABLES - this->NumberOfScalarVariables;
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();
}
int vtkFunctionParser::IsScalarResult()
{
if (this->VariableMTime.GetMTime() > this->EvaluateMTime.GetMTime() ||
this->FunctionMTime.GetMTime() > this->EvaluateMTime.GetMTime())
{
this->Evaluate();
}
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())
{
this->Evaluate();
}
return (this->StackPointer == 2);
}
double *vtkFunctionParser::GetVectorResult()
{
if (!(this->IsVectorResult()))
{
vtkErrorMacro("GetVectorResult: no valid vector result");
return vtkParserVectorErrorResult;
}
return this->Stack;
}
char* vtkFunctionParser::GetScalarVariableName(int i)
{
if (i >= 0 && i < this->NumberOfScalarVariables)
{
return this->ScalarVariableNames[i];
}
return NULL;
}
char* vtkFunctionParser::GetVectorVariableName(int i)
{
if (i >= 0 && i < this->NumberOfVectorVariables)
{
return this->VectorVariableNames[i];
}
return NULL;
}
int vtkFunctionParser::IsVariableName(int currentIndex)
{
int i;
for (i = 0; i < this->NumberOfScalarVariables; i++)
{
if (strncmp(this->ScalarVariableNames[i], &this->Function[currentIndex],
strlen(this->ScalarVariableNames[i])) == 0)
{
return 1;
}
}
for (i = 0; i < this->NumberOfVectorVariables; i++)
{
if (strncmp(this->VectorVariableNames[i], &this->Function[currentIndex],
strlen(this->VectorVariableNames[i])) == 0)
{
return 1;
}
}
return 0;
}
int vtkFunctionParser::IsElementaryOperator(int op)
{
return strchr("+-.*/^", op) != NULL;
}
void vtkFunctionParser::SetScalarVariableValue(const char* inVariableName,
double value)
{
int i;
double *tempValues;
char** tempNames;
char* variableName = this->RemoveSpacesFrom(inVariableName);
for (i = 0; i < this->NumberOfScalarVariables; i++)
{
if (strcmp(variableName, this->ScalarVariableNames[i]) == 0)
{
if (this->ScalarVariableValues[i] != value)
{
this->ScalarVariableValues[i] = value;
this->VariableMTime.Modified();
this->Modified();
}
delete [] variableName;
return;
}
}
tempValues = new double [this->NumberOfScalarVariables];
tempNames = new char *[this->NumberOfScalarVariables];
for (i = 0; i < this->NumberOfScalarVariables; i++)
{
tempValues[i] = this->ScalarVariableValues[i];
tempNames[i] = new char [strlen(this->ScalarVariableNames[i]) + 1];
strcpy(tempNames[i], this->ScalarVariableNames[i]);
delete [] this->ScalarVariableNames[i];
this->ScalarVariableNames[i] = NULL;
}
if (this->ScalarVariableValues)
{
delete [] this->ScalarVariableValues;
this->ScalarVariableValues = NULL;
}
if (this->ScalarVariableNames)
{
delete [] this->ScalarVariableNames;
this->ScalarVariableNames = NULL;
}
this->ScalarVariableValues = new double [this->NumberOfScalarVariables + 1];
this->ScalarVariableNames = new char *[this->NumberOfScalarVariables + 1];
for (i = 0; i < this->NumberOfScalarVariables; i++)
{
this->ScalarVariableValues[i] = tempValues[i];
this->ScalarVariableNames[i] = new char [strlen(tempNames[i]) + 1];
strcpy(this->ScalarVariableNames[i], tempNames[i]);
delete [] tempNames[i];
tempNames[i] = NULL;
}
delete [] tempValues;
delete [] tempNames;
this->ScalarVariableValues[i] = value;
this->ScalarVariableNames[i] = new char [strlen(variableName) + 1];
strcpy(this->ScalarVariableNames[i], variableName);
this->NumberOfScalarVariables++;
this->VariableMTime.Modified();
this->Modified();
delete [] variableName;
}
void vtkFunctionParser::SetScalarVariableValue(int i, double value)
{
if (i < 0 || i >= this->NumberOfScalarVariables)
{
return;
}
if (this->ScalarVariableValues[i] != value)
{
this->ScalarVariableValues[i] = value;
this->VariableMTime.Modified();
}
this->Modified();
}
double vtkFunctionParser::GetScalarVariableValue(const char* inVariableName)
{
int i;
char* variableName = this->RemoveSpacesFrom(inVariableName);
for (i = 0; i < this->NumberOfScalarVariables; i++)
{
if (strcmp(variableName, this->ScalarVariableNames[i]) == 0)
{
delete [] variableName;
return this->ScalarVariableValues[i];
}
}
vtkErrorMacro("GetScalarVariableValue: scalar variable " << variableName
<< " does not exist");
delete [] variableName;
return VTK_PARSER_ERROR_RESULT;
}
double vtkFunctionParser::GetScalarVariableValue(int i)
{
if (i < 0 || i >= this->NumberOfScalarVariables)
{
vtkErrorMacro("GetScalarVariableValue: scalar variable " << 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)
{
int i;
double **tempValues;
char** tempNames;
char* variableName = this->RemoveSpacesFrom(inVariableName);
for (i = 0; i < this->NumberOfVectorVariables; i++)
{
if (strcmp(variableName, this->VectorVariableNames[i]) == 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;
}
}
tempValues = new double *[this->NumberOfVectorVariables];
tempNames = new char *[this->NumberOfVectorVariables];
for (i = 0; i < this->NumberOfVectorVariables; i++)
{
tempValues[i] = new double[3];
tempValues[i][0] = this->VectorVariableValues[i][0];
tempValues[i][1] = this->VectorVariableValues[i][1];
tempValues[i][2] = this->VectorVariableValues[i][2];
tempNames[i] = new char [strlen(this->VectorVariableNames[i]) + 1];
strcpy(tempNames[i], this->VectorVariableNames[i]);
delete [] this->VectorVariableNames[i];
this->VectorVariableNames[i] = NULL;
delete [] this->VectorVariableValues[i];
this->VectorVariableValues[i] = NULL;
}
if (this->VectorVariableValues)
{
delete [] this->VectorVariableValues;
this->VectorVariableValues = NULL;
}
if (this->VectorVariableNames)
{
delete [] this->VectorVariableNames;
this->VectorVariableNames = NULL;
}
this->VectorVariableValues = new double *[this->NumberOfVectorVariables + 1];
this->VectorVariableNames = new char *[this->NumberOfVectorVariables + 1];
for (i = 0; i < this->NumberOfVectorVariables; i++)
{
this->VectorVariableValues[i] = new double[3];
this->VectorVariableValues[i][0] = tempValues[i][0];
this->VectorVariableValues[i][1] = tempValues[i][1];
this->VectorVariableValues[i][2] = tempValues[i][2];
this->VectorVariableNames[i] = new char [strlen(tempNames[i]) + 1];
strcpy(this->VectorVariableNames[i], tempNames[i]);
delete [] tempNames[i];
tempNames[i] = NULL;
delete [] tempValues[i];
tempValues[i] = NULL;
}
delete [] tempValues;
delete [] tempNames;
this->VectorVariableValues[i] = new double[3];
this->VectorVariableValues[i][0] = xValue;
this->VectorVariableValues[i][1] = yValue;
this->VectorVariableValues[i][2] = zValue;
this->VectorVariableNames[i] = new char [strlen(variableName) + 1];
strcpy(this->VectorVariableNames[i], variableName);
this->NumberOfVectorVariables++;
this->VariableMTime.Modified();
this->Modified();
delete [] variableName;
}
void vtkFunctionParser::SetVectorVariableValue(int i, double xValue,
double yValue, double zValue)
{
if (i < 0 || i >= this->NumberOfVectorVariables)
{
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)
{
int i;
char* variableName = this->RemoveSpacesFrom(inVariableName);
for (i = 0; i < this->NumberOfVectorVariables; i++)
{
if (strcmp(variableName, this->VectorVariableNames[i]) == 0)
{
delete [] variableName;
return this->VectorVariableValues[i];
}
}
vtkErrorMacro("GetVectorVariableValue: vector variable " << variableName
<< " does not exist");
delete [] variableName;
return vtkParserVectorErrorResult;
}
double* vtkFunctionParser::GetVectorVariableValue(int i)
{
if (i < 0 || i >= this->NumberOfVectorVariables)
{
vtkErrorMacro("GetVectorVariableValue: vector variable " << i
<< " does not exist");
return vtkParserVectorErrorResult;
}
return this->VectorVariableValues[i];
}
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, this->FunctionLength);
this->Function[this->FunctionLength] = '\0';
delete [] tempString;
}
int vtkFunctionParser::OperatorWithinVariable(int idx)
{
int i;
char *tmpString;
int start, end;
for (i = 0; i < this->NumberOfScalarVariables; i++)
{
if (strchr(this->ScalarVariableNames[i], this->Function[idx]) != 0)
{
tmpString = strstr(this->Function, this->ScalarVariableNames[i]);
if (tmpString)
{
start = (int)(tmpString - this->Function);
end = start + strlen(this->ScalarVariableNames[i]);
if (start <= idx && end >= idx)
{
return 1;
}
}
}
}
for (i = 0; i < this->NumberOfVectorVariables; i++)
{
if (strchr(this->VectorVariableNames[i], this->Function[idx]) != 0)
{
tmpString = strstr(this->Function, this->VectorVariableNames[i]);
if (tmpString)
{
start = (int)(tmpString - this->Function);
end = start + strlen(this->VectorVariableNames[i]);
if (start <= idx && end >= idx)
{
return 1;
}
}
}
}
return 0;
}
int vtkFunctionParser::CheckSyntax()
{
int index = 0, parenthesisCount = 0, currentChar;
char* ptr;
int functionNumber, constantNumber;
int *expectCommaOnParenthesisCount = new int[this->FunctionLength];
int i;
for (i = 0; i < this->FunctionLength; i++)
{
expectCommaOnParenthesisCount[i] = 0;
}
while (1)
{
currentChar = this->Function[index];
// Check for valid operand (must appear)
// Check for leading -
if (currentChar == '-')
{
currentChar = this->Function[++index];
if(index == this->FunctionLength)
{
vtkErrorMacro("Syntax error: unary minus with no operand;"
<< " see position " << index);
delete [] expectCommaOnParenthesisCount;
return 0;
}
}
// Check for math function
if ((functionNumber = this->GetMathFunctionNumber(index)))
{
if ((functionNumber == VTK_PARSER_MIN) ||
(functionNumber == VTK_PARSER_MAX))
{
expectCommaOnParenthesisCount[parenthesisCount+1] = 1;
}
index += this->GetMathFunctionStringLength(functionNumber);
currentChar = this->Function[index];
if ( currentChar != '(' )
{
vtkErrorMacro("Syntax error: input to math function not in "
<< "parentheses; see position " << index);
delete [] expectCommaOnParenthesisCount;
return 0;
}
}
// Check for opening parenthesis
if( currentChar == '(' )
{
parenthesisCount++;
index++;
continue;
}
// Check for number
if(isdigit(currentChar) ||
(currentChar == '.' && isdigit(this->Function[index+1])))
{
strtod(&this->Function[index], &ptr);
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];
}
else
{ // Check for variable
if (!this->IsVariableName(index))
{
vtkErrorMacro("Syntax error: expecting a variable name; "
<< "see position " << index);
delete [] expectCommaOnParenthesisCount;
return 0;
}
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])
{
// Check for comma
if (currentChar == ',')
{
expectCommaOnParenthesisCount[parenthesisCount] = 2;
index++;
continue;
}
}
// Check for closing parenthesis
while ( currentChar == ')' )
{
if (expectCommaOnParenthesisCount[parenthesisCount] == 1)
{
// We can't be closing this function if
// expectCommaOnParenthesisCount[..] is still 1; either it was always
// 0 or it should have been incremented to 2.
vtkErrorMacro("Syntax Error: two parameters separated by commas "
<< "expected; see position " << index);
delete [] expectCommaOnParenthesisCount;
return 0;
}
parenthesisCount--;
if(parenthesisCount < 0)
{
vtkErrorMacro("Syntax Error: mismatched parenthesis; see position "
<< index);
delete [] expectCommaOnParenthesisCount;
return 0;
}
if( this->Function[index - 1] == '(' )
{
vtkErrorMacro("Syntax Error: empty parentheses; see position "
<< index);
delete [] expectCommaOnParenthesisCount;
return 0;
}
currentChar = this->Function[++index];
}
// 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))
{
vtkErrorMacro("Syntax error: operator expected; see position "
<< index);
delete [] expectCommaOnParenthesisCount;
return 0;
}
// If we get here, we have an operand and an operator; the next loop will
// check for another operand (must appear)
index++;
} // while
// Check that all opened parentheses are also closed
if(parenthesisCount > 0)
{
vtkErrorMacro("Syntax Error: missing closing parenthesis; see position "
<< index);
delete [] expectCommaOnParenthesisCount;
return 0;
}
// The string is ok
delete [] expectCommaOnParenthesisCount;
return 1;
}
int vtkFunctionParser::BuildInternalFunctionStructure()
{
if (this->ByteCode)
{
delete [] this->ByteCode;
this->ByteCode = NULL;
}
if (this->Immediates)
{
delete [] this->Immediates;
this->Immediates = NULL;
}
if (this->Stack)
{
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;
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->GetMathConstantNumber(beginIndex+1) > 0 &&
this->FindEndOfMathConstant(beginIndex+1) == endIndex)
{
this->BuildInternalSubstringStructure(beginIndex+1, endIndex);
this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
return;
}
}
if (isalpha(this->Function[beginIndex]))
{
mathFunctionNum = this->GetMathFunctionNumber(beginIndex);
if (mathFunctionNum > 0)
{
beginIndex2 = beginIndex;
while (this->Function[beginIndex2] != '(')
{
beginIndex2++;
}
if (this->IsSubstringCompletelyEnclosed(beginIndex2, endIndex))
{
if ((mathFunctionNum == VTK_PARSER_MIN) ||
(mathFunctionNum == VTK_PARSER_MAX))
{
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(mathFunctionNum);
this->StackPointer--;
return;
}
}
}
this->BuildInternalSubstringStructure(beginIndex2+1, endIndex-1);
this->AddInternalByte(mathFunctionNum);
return;
}
}
}
for (opNum = 0; opNum < 6; opNum++)
{
parenthesisCount = 0;
for (i = endIndex; i > beginIndex; i--)
{
if (this->Function[i] == ')')
{
parenthesisCount++;
}
else if (this->Function[i] == '(')
{
parenthesisCount--;
}
if (parenthesisCount == 0 &&
this->Function[i] == elementaryMathOps[opNum] &&
!(this->Function[i] == '-' &&
(this->IsElementaryOperator(this->Function[i-1]) ||
this->Function[i-1] == '(' ||
(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;
}
}
}
beginIndex2 = beginIndex;
if (this->Function[beginIndex] == '-')
{
beginIndex2++;
}
this->AddInternalByte(this->GetOperandNumber(beginIndex2));
this->StackPointer++;
if (this->StackPointer > this->StackSize)
{
this->StackSize++;
}
if (beginIndex2 > beginIndex)
{
this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
}
}
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];
}
if (this->ByteCode)
{
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)
{
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], "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;
}
return 0;
}
int vtkFunctionParser::GetMathFunctionStringLength(int mathFunctionNumber)
{
switch (mathFunctionNumber)
{
case VTK_PARSER_LOGARITHME:
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:
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:
return 4;
case VTK_PARSER_FLOOR:
case VTK_PARSER_LOGARITHM10:
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->NumberOfScalarVariables)
{
return static_cast<int>(strlen(this->ScalarVariableNames[variableNumber]));
}
else
{
return static_cast<int>(strlen(
this->VectorVariableNames[variableNumber -
this->NumberOfScalarVariables]));
}
}
int vtkFunctionParser::FindEndOfMathFunction(int beginIndex)
{
int i = beginIndex, parenthesisCount;
while (this->Function[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;
}
int vtkFunctionParser::GetElementaryOperatorNumber(char op)
{
static const char* const operators = "+-*/^";
int i;
for(i = 0; i < 5; i++)
{
if (operators[i] == op)
{
return VTK_PARSER_ADD + i;
}
}
if (op == '.')
{
return VTK_PARSER_DOT_PRODUCT;
}
return 0;
}
int vtkFunctionParser::GetOperandNumber(int currentIndex)
{
int i, variableIndex = -1;
if (isdigit(this->Function[currentIndex]) ||
this->Function[currentIndex] == '.') // Number
{
double *tempImmediates = new double[this->ImmediatesSize];
for (i = 0; i < this->ImmediatesSize; i++)
{ // Copy current immediates to a temporary array
tempImmediates[i] = this->Immediates[i];
}
if (this->Immediates)
{
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 (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;
}
for (i = 0; i < this->NumberOfScalarVariables; i++)
{ // Variable
if (strncmp(&this->Function[currentIndex], this->ScalarVariableNames[i],
strlen(this->ScalarVariableNames[i])) == 0)
{
if (variableIndex == -1 ||
(strlen(this->ScalarVariableNames[i]) >
strlen(this->ScalarVariableNames[variableIndex])))
{
variableIndex = i;
}
}
}
if (variableIndex >= 0)
{
return VTK_PARSER_BEGIN_VARIABLES + variableIndex;
}
for (i = 0; i < this->NumberOfVectorVariables; i++)
{ // Variable
if (strncmp(&this->Function[currentIndex], this->VectorVariableNames[i],
strlen(this->VectorVariableNames[i])) == 0)
{
if (variableIndex == -1 ||
(strlen(this->VectorVariableNames[i]) >
strlen(this->VectorVariableNames[variableIndex])))
{
variableIndex = i;
}
}
}
if (variableIndex >= 0)
{
return VTK_PARSER_BEGIN_VARIABLES + variableIndex + this->NumberOfScalarVariables;
}
return 0;
}
void vtkFunctionParser::RemoveAllVariables()
{
int i;
for (i = 0; i < this->NumberOfScalarVariables; i++)
{
delete [] this->ScalarVariableNames[i];
this->ScalarVariableNames[i] = NULL;
}
if (this->NumberOfScalarVariables > 0)
{
delete [] this->ScalarVariableNames;
this->ScalarVariableNames = NULL;
delete [] this->ScalarVariableValues;
this->ScalarVariableValues = NULL;
}
this->NumberOfScalarVariables = 0;
for (i = 0; i < this->NumberOfVectorVariables; i++)
{
delete [] this->VectorVariableNames[i];
this->VectorVariableNames[i] = NULL;
}
if (this->NumberOfVectorVariables > 0)
{
delete [] this->VectorVariableNames;
this->VectorVariableNames = NULL;
delete [] this->VectorVariableValues;
this->VectorVariableValues = NULL;
}
this->NumberOfVectorVariables = 0;
}
void vtkFunctionParser::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
int i;
os << indent << "Function: "
<< (this->Function ? this->Function : "(none)") << endl;
os << indent << "NumberOfScalarVariables: "
<< this->NumberOfScalarVariables << endl;
for (i = 0; i < this->NumberOfScalarVariables; i++)
{
os << indent << " " << this->GetScalarVariableName(i) << ": "
<< this->GetScalarVariableValue(i) << endl;
}
os << indent << "NumberOfVectorVariables: "
<< this->NumberOfVectorVariables << endl;
for (i = 0; i < this->NumberOfVectorVariables; 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->ReplaceInvalidValues ? "On" : "Off") << endl;
os << indent << "Replacement Value: " << this->ReplacementValue << endl;
}