/*========================================================================= Program: Visualization Toolkit Module: vtkArrayCalculator.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkArrayCalculator * @brief perform mathematical operations on data in field data arrays * * vtkArrayCalculator performs operations on vectors or scalars in field * data arrays. It uses vtkFunctionParser/vtkExprTkFunctionParser to do * the parsing and to evaluate the function for each entry in the input * arrays. The arrays used in a given function must be all in point data * or all in cell data. The resulting array will be stored as a field * data array. The result array can either be stored in a new array or * it can overwrite an existing array. vtkArrayCalculator can run in * parallel using vtkSMPTools. * * The functions that this array calculator understands is: * * standard operations: * + * - * * * / * ^ * . (only by vtkFunctionParser) * build unit vectors: iHat, jHat, kHat (ie (1,0,0), (0,1,0), (0,0,1)) * abs * acos * asin * atan * ceil * cos * cosh * exp * floor * ln * mag * min * max * norm * dot (only by vtkExprTkFunctionParser) * cross * sign * sin * sinh * sqrt * tan * tanh * * Note that some of these operations work on scalars, some on vectors, and some on * both (e.g., you can multiply a scalar times a vector). The operations are performed * tuple-wise (i.e., tuple-by-tuple). The user must specify which arrays to use as * vectors and/or scalars, and the name of the output data array. * * @sa * For more detailed documentation of the supported functionality see: * 1) vtkFunctionParser * 2) vtkExprTkFunctionParser (default) */ #ifndef vtkArrayCalculator_h #define vtkArrayCalculator_h #include "vtkDataObject.h" // For attribute types #include "vtkFiltersCoreModule.h" // For export macro #include "vtkPassInputTypeAlgorithm.h" #include "vtkTuple.h" // needed for vtkTuple #include // needed for vector class vtkDataSet; class VTKFILTERSCORE_EXPORT vtkArrayCalculator : public vtkPassInputTypeAlgorithm { public: vtkTypeMacro(vtkArrayCalculator, vtkPassInputTypeAlgorithm); void PrintSelf(ostream& os, vtkIndent indent) override; static vtkArrayCalculator* New(); ///@{ /** * Set/Get the function to be evaluated. */ vtkSetStringMacro(Function); vtkGetStringMacro(Function); ///@} ///@{ /** * Add an array name to the list of arrays used in the function and specify * which components of the array to use in evaluating the function. The * array name must match the name in the function. If the array name is not * sanitized, the variable name will be the array name enclosed in quotes. * Use AddScalarVariable or AddVectorVariable to use a user defined * variable name. * * @note A sanitized variable name is accepted by the following regex: ^[a-zA-Z][a-zA-Z_0-9]*. */ void AddScalarArrayName(const char* arrayName, int component = 0); void AddVectorArrayName( const char* arrayName, int component0 = 0, int component1 = 1, int component2 = 2); ///@} ///@{ /** * Add a variable name, a corresponding array name, and which components of * the array to use. The variable name should be sanitized or in quotes. * * @note A sanitized variable name is accepted by the following regex: ^[a-zA-Z][a-zA-Z_0-9]*. */ void AddScalarVariable(const char* variableName, const char* arrayName, int component = 0); void AddVectorVariable(const char* variableName, const char* arrayName, int component0 = 0, int component1 = 1, int component2 = 2); ///@} ///@{ /** * Add a variable name, a corresponding array name, and which components of * the array to use. The variable name should be sanitized or in quotes. * * @note A sanitized variable name is accepted by the following regex: ^[a-zA-Z][a-zA-Z_0-9]*. */ void AddCoordinateScalarVariable(const char* variableName, int component = 0); void AddCoordinateVectorVariable( const char* variableName, int component0 = 0, int component1 = 1, int component2 = 2); ///@} ///@{ /** * Set the name of the array in which to store the result of * evaluating this function. If this is the name of an existing array, * that array will be overwritten. Otherwise a new array will be * created with the specified name. */ vtkSetStringMacro(ResultArrayName); vtkGetStringMacro(ResultArrayName); ///@} ///@{ /** * Type of the result array. It is ignored if CoordinateResults is true. * Initial value is VTK_DOUBLE. */ vtkGetMacro(ResultArrayType, int); vtkSetMacro(ResultArrayType, int); ///@} ///@{ /** * Set whether to output results as coordinates. ResultArrayName will be * ignored. Outputting as coordinates is only valid with vector results and * if the AttributeMode is AttributeModeToUsePointData. * If a valid output can't be made, an error will occur. */ vtkGetMacro(CoordinateResults, vtkTypeBool); vtkSetMacro(CoordinateResults, vtkTypeBool); vtkBooleanMacro(CoordinateResults, vtkTypeBool); ///@} ///@{ /** * Set whether to output results as point/cell normals. Outputting as * normals is only valid with vector results. Point or cell normals are * selected using AttributeMode. */ vtkGetMacro(ResultNormals, bool); vtkSetMacro(ResultNormals, bool); vtkBooleanMacro(ResultNormals, bool); ///@} ///@{ /** * Set whether to output results as point/cell texture coordinates. * Point or cell texture coordinates are selected using AttributeMode. * 2-component texture coordinates cannot be generated at this time. */ vtkGetMacro(ResultTCoords, bool); vtkSetMacro(ResultTCoords, bool); vtkBooleanMacro(ResultTCoords, bool); ///@} /** * Returns a string representation of the calculator's AttributeType */ const char* GetAttributeTypeAsString(); static const int DEFAULT_ATTRIBUTE_TYPE = -1; ///@{ /** * Control which AttributeType the filter operates on (point data or cell data * for vtkDataSets). By default the filter uses Point/Vertex/Row data depending * on the input data type. The input value for this function should be one of the * constants in vtkDataObject::AttributeTypes or DEFAULT_ATTRIBUTE_TYPE for 'default behavior'. */ vtkSetMacro(AttributeType, int); vtkGetMacro(AttributeType, int); void SetAttributeTypeToDefault() { this->SetAttributeType(DEFAULT_ATTRIBUTE_TYPE); } void SetAttributeTypeToPointData() { this->SetAttributeType(vtkDataObject::POINT); } void SetAttributeTypeToCellData() { this->SetAttributeType(vtkDataObject::CELL); } void SetAttributeTypeToEdgeData() { this->SetAttributeType(vtkDataObject::EDGE); } void SetAttributeTypeToVertexData() { this->SetAttributeType(vtkDataObject::VERTEX); } void SetAttributeTypeToRowData() { this->SetAttributeType(vtkDataObject::ROW); } ///@} /** * Remove all the variable names and their associated array names. */ void RemoveAllVariables(); /** * Remove all the scalar variable names and their associated array names. */ virtual void RemoveScalarVariables(); /** * Remove all the scalar variable names and their associated array names. */ virtual void RemoveVectorVariables(); /** * Remove all the coordinate variables. */ virtual void RemoveCoordinateScalarVariables(); /** * Remove all the coordinate variables. */ virtual void RemoveCoordinateVectorVariables(); ///@{ /** * Methods to get information about the current variables. */ const std::vector& GetScalarArrayNames() { return this->ScalarArrayNames; } std::string GetScalarArrayName(int i); const std::vector& GetVectorArrayNames() { return this->VectorArrayNames; } std::string GetVectorArrayName(int i); const std::vector& GetScalarVariableNames() { return this->ScalarVariableNames; } std::string GetScalarVariableName(int i); const std::vector& GetVectorVariableNames() { return this->VectorVariableNames; } std::string GetVectorVariableName(int i); const std::vector& GetSelectedScalarComponents() { return this->SelectedScalarComponents; } int GetSelectedScalarComponent(int i); const std::vector>& GetSelectedVectorComponents() { return this->SelectedVectorComponents; } vtkTuple GetSelectedVectorComponents(int i); int GetNumberOfScalarArrays() { return static_cast(this->ScalarArrayNames.size()); } int GetNumberOfVectorArrays() { return static_cast(this->VectorArrayNames.size()); } ///@} ///@{ /** * When ReplaceInvalidValues is on, all invalid values (such as * sqrt(-2), note that function parser does not handle complex * numbers) will be replaced by ReplacementValue. Otherwise an * error will be reported. */ vtkSetMacro(ReplaceInvalidValues, vtkTypeBool); vtkGetMacro(ReplaceInvalidValues, vtkTypeBool); vtkBooleanMacro(ReplaceInvalidValues, vtkTypeBool); vtkSetMacro(ReplacementValue, double); vtkGetMacro(ReplacementValue, double); ///@} ///@{ /** * When this option is set, silently ignore datasets where the requested field * data array is not present. When an input array is not present, the result array * will not be generated nor added to the output. */ vtkSetMacro(IgnoreMissingArrays, bool); vtkGetMacro(IgnoreMissingArrays, bool); vtkBooleanMacro(IgnoreMissingArrays, bool); ///@} /** * Enum that includes the types of parsers that can be used. */ enum FunctionParserTypes { FunctionParser, // vtkFunctionParser ExprTkFunctionParser, // vtkExprTkFunctionParser NumberOfFunctionParserTypes }; ///@{ /** * Set/Get the FunctionParser type that will be used. * vtkFunctionParser = 0, vtkExprTkFunctionParser = 1. Default is 1. */ vtkSetEnumMacro(FunctionParserType, FunctionParserTypes); void SetFunctionParserTypeToFunctionParser() { this->FunctionParserType = FunctionParserTypes::FunctionParser; this->Modified(); } void SetFunctionParserTypeToExprTkFunctionParser() { this->FunctionParserType = FunctionParserTypes::ExprTkFunctionParser; this->Modified(); } vtkGetEnumMacro(FunctionParserType, FunctionParserTypes); ///@} /** * Returns the output of the filter downcast to a vtkDataSet or nullptr if the * cast fails. */ vtkDataSet* GetDataSetOutput(); protected: vtkArrayCalculator(); ~vtkArrayCalculator() override; int FillInputPortInformation(int, vtkInformation*) override; int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override; /** * Get the attribute type for the input. */ int GetAttributeTypeFromInput(vtkDataObject* input); /** * A variable name is valid if it's sanitized or enclosed in quotes. * 1) if it's valid, return itself. * 2) if it's not valid, return itself enclosed in quotes, * * @note A sanitized variable name is accepted by the following regex: ^[a-zA-Z][a-zA-Z_0-9]*. */ static std::string CheckValidVariableName(const char* variableName); FunctionParserTypes FunctionParserType; char* Function; char* ResultArrayName; std::vector ScalarArrayNames; std::vector VectorArrayNames; std::vector ScalarVariableNames; std::vector VectorVariableNames; int AttributeType; std::vector SelectedScalarComponents; std::vector> SelectedVectorComponents; vtkTypeBool ReplaceInvalidValues; double ReplacementValue; bool IgnoreMissingArrays; vtkTypeBool CoordinateResults; bool ResultNormals; bool ResultTCoords; std::vector CoordinateScalarVariableNames; std::vector CoordinateVectorVariableNames; std::vector SelectedCoordinateScalarComponents; std::vector> SelectedCoordinateVectorComponents; int ResultArrayType; private: vtkArrayCalculator(const vtkArrayCalculator&) = delete; void operator=(const vtkArrayCalculator&) = delete; // Do the bulk of the work template int ProcessDataObject(vtkDataObject* input, vtkDataObject* output); }; #endif