/*========================================================================= 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 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(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(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(strlen(this->ScalarVariableNames[variableNumber])); } else { return static_cast(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; }