AlgorithmFilter
Repository source: AlgorithmFilter
Description¶
This example demonstrates how to create a filter that accepts a custom class and returns a custom class. To test that it is working, the class vtkTest simply stores a double named 'Value' that is instantiated to the value of 4.5. Example.cxx instantiates a vtkTest and sets its value to 5.6. The filter adds 1.0 to this value, so the vtkTest that is the output of the vtkTestAlgorithmFilter should contain the value 6.6.
You will need the following in your CMakeLists.txt file:
find_package(VTK
COMPONENTS
CommonCore
CommonDataModel
CommonExecutionModel
FiltersSources
InfovisCore
)
Question
If you have a question about this example, please use the VTK Discourse Forum
Code¶
AlgorithmFilter.cxx
#include <vtkNew.h>
#include "vtkTest.h"
#include "vtkTestAlgorithmFilter.h"
int main(int, char*[])
{
vtkNew<vtkTest> inputTest;
inputTest->SetValue(5.6);
std::cout << "Input value: " << inputTest->GetValue() << std::endl;
vtkNew<vtkTestAlgorithmFilter> filter;
filter->SetInput(inputTest);
filter->Update();
vtkTest* outputTest = filter->GetOutput();
std::cout << "Output value: " << outputTest->GetValue() << std::endl;
std::cout << "Input value is still: " << inputTest->GetValue() << std::endl;
return EXIT_SUCCESS;
}
vtkTest.cxx
#include "vtkTest.h"
#include <vtkObjectFactory.h>
vtkStandardNewMacro(vtkTest);
vtkTest::vtkTest()
{
this->Value = 0.0;
}
vtkTest::~vtkTest()
{
}
void vtkTest::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
void vtkTest::ShallowCopy(vtkDataObject* t)
{
vtkTest* m = dynamic_cast<vtkTest*>(t);
this->Value = m->GetValue();
}
vtkTestAlgorithmFilter.cxx
#include "vtkTestAlgorithmFilter.h"
#include "vtkTest.h"
#include <vtkCommand.h>
#include <vtkInformation.h>
#include <vtkInformationVector.h>
#include <vtkObjectFactory.h>
#include <vtkStreamingDemandDrivenPipeline.h>
vtkStandardNewMacro(vtkTestAlgorithmFilter);
//----------------------------------------------------------------------------
vtkTestAlgorithmFilter::vtkTestAlgorithmFilter()
{
this->SetNumberOfInputPorts(1);
this->SetNumberOfOutputPorts(1);
}
//----------------------------------------------------------------------------
vtkTestAlgorithmFilter::~vtkTestAlgorithmFilter()
{
}
//----------------------------------------------------------------------------
void vtkTestAlgorithmFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
vtkTest* vtkTestAlgorithmFilter::GetOutput()
{
return this->GetOutput(0);
}
//----------------------------------------------------------------------------
vtkTest* vtkTestAlgorithmFilter::GetOutput(int port)
{
return dynamic_cast<vtkTest*>(this->GetOutputDataObject(port));
}
//----------------------------------------------------------------------------
void vtkTestAlgorithmFilter::SetOutput(vtkDataObject* d)
{
this->GetExecutive()->SetOutputData(0, d);
}
//----------------------------------------------------------------------------
vtkDataObject* vtkTestAlgorithmFilter::GetInput()
{
return this->GetInput(0);
}
//----------------------------------------------------------------------------
vtkDataObject* vtkTestAlgorithmFilter::GetInput(int port)
{
return this->GetExecutive()->GetInputData(port, 0);
}
//----------------------------------------------------------------------------
vtkTest* vtkTestAlgorithmFilter::GetLabelHierarchyInput(int port)
{
return dynamic_cast<vtkTest*>(this->GetInput(port));
}
//----------------------------------------------------------------------------
int vtkTestAlgorithmFilter::ProcessRequest(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
// Create an output object of the correct type.
if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT()))
{
return this->RequestDataObject(request, inputVector, outputVector);
}
// generate the data
if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
{
return this->RequestData(request, inputVector, outputVector);
}
if (request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT()))
{
return this->RequestUpdateExtent(request, inputVector, outputVector);
}
// execute information
if (request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
{
return this->RequestInformation(request, inputVector, outputVector);
}
return this->Superclass::ProcessRequest(request, inputVector, outputVector);
}
//----------------------------------------------------------------------------
int vtkTestAlgorithmFilter::FillOutputPortInformation(int vtkNotUsed(port),
vtkInformation* info)
{
// now add our info
info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkTest");
return 1;
}
//----------------------------------------------------------------------------
int vtkTestAlgorithmFilter::FillInputPortInformation(int vtkNotUsed(port),
vtkInformation* info)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTest");
return 1;
}
int vtkTestAlgorithmFilter::RequestDataObject(
vtkInformation* vtkNotUsed(request),
vtkInformationVector** vtkNotUsed(inputVector),
vtkInformationVector* outputVector)
{
// RequestDataObject (RDO) is an earlier pipeline pass.
// During RDO, each filter is supposed to produce an empty data object of the
// proper type
vtkInformation* outInfo = outputVector->GetInformationObject(0);
vtkTest* output =
dynamic_cast<vtkTest*>(outInfo->Get(vtkDataObject::DATA_OBJECT()));
if (!output)
{
output = vtkTest::New();
outInfo->Set(vtkDataObject::DATA_OBJECT(), output);
output->FastDelete();
this->GetOutputPortInformation(0)->Set(vtkDataObject::DATA_EXTENT_TYPE(),
output->GetExtentType());
}
return 1;
}
//----------------------------------------------------------------------------
int vtkTestAlgorithmFilter::RequestInformation(
vtkInformation* vtkNotUsed(request),
vtkInformationVector** vtkNotUsed(inputVector),
vtkInformationVector* vtkNotUsed(outputVector))
{
// do nothing let subclasses handle it
return 1;
}
//----------------------------------------------------------------------------
int vtkTestAlgorithmFilter::RequestUpdateExtent(
vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector,
vtkInformationVector* vtkNotUsed(outputVector))
{
int numInputPorts = this->GetNumberOfInputPorts();
for (int i = 0; i < numInputPorts; i++)
{
int numInputConnections = this->GetNumberOfInputConnections(i);
for (int j = 0; j < numInputConnections; j++)
{
vtkInformation* inputInfo = inputVector[i]->GetInformationObject(j);
inputInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1);
}
}
return 1;
}
//----------------------------------------------------------------------------
// This is the superclasses style of Execute method. Convert it into
// an imaging style Execute method.
int vtkTestAlgorithmFilter::RequestData(vtkInformation* vtkNotUsed(request),
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
// Later on RequestData (RD) happens.
// During RD each filter examines any inputs it has, then fills in that empty
// data object with real data.
vtkInformation* outInfo = outputVector->GetInformationObject(0);
vtkTest* output =
dynamic_cast<vtkTest*>(outInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
vtkTest* input =
dynamic_cast<vtkTest*>(inInfo->Get(vtkDataObject::DATA_OBJECT()));
output->ShallowCopy(input);
output->SetValue(output->GetValue() + 1.0);
return 1;
}
//----------------------------------------------------------------------------
void vtkTestAlgorithmFilter::SetInput(vtkDataObject* input)
{
this->SetInput(0, input);
}
//----------------------------------------------------------------------------
void vtkTestAlgorithmFilter::SetInput(int index, vtkDataObject* input)
{
if (input)
{
this->SetInputDataObject(index, input);
}
else
{
// Setting a NULL input removes the connection.
this->SetInputDataObject(index, 0);
}
}
//----------------------------------------------------------------------------
void vtkTestAlgorithmFilter::AddInput(vtkDataObject* input)
{
this->AddInput(0, input);
}
//----------------------------------------------------------------------------
void vtkTestAlgorithmFilter::AddInput(int index, vtkDataObject* input)
{
if (input)
{
this->AddInputDataObject(index, input);
}
}
vtkTestAlgorithmFilter.h
#ifndef __vtkTestAlgorithmFilter_h
#define __vtkTestAlgorithmFilter_h
#include <vtkAlgorithm.h>
class vtkDataSet;
class vtkTest;
class vtkTestAlgorithmFilter : public vtkAlgorithm
{
public:
static vtkTestAlgorithmFilter* New();
vtkTypeMacro(vtkTestAlgorithmFilter, vtkAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent) override;
// Description:
// Get the output data object for a port on this algorithm.
vtkTest* GetOutput();
vtkTest* GetOutput(int);
virtual void SetOutput(vtkDataObject* d);
// Description:
// see vtkAlgorithm for details
virtual int ProcessRequest(vtkInformation*, vtkInformationVector**,
vtkInformationVector*) override;
// this method is not recommended for use, but lots of old style filters use
// it
vtkDataObject* GetInput();
vtkDataObject* GetInput(int port);
vtkTest* GetLabelHierarchyInput(int port);
// Description:
// Set an input of this algorithm. You should not override these
// methods because they are not the only way to connect a pipeline.
// Note that these methods support old-style pipeline connections.
// When writing new code you should use the more general
// vtkAlgorithm::SetInputConnection(). These methods transform the
// input index to the input port index, not an index of a connection
// within a single port.
void SetInput(vtkDataObject*);
void SetInput(int, vtkDataObject*);
// Description:
// Add an input of this algorithm. Note that these methods support
// old-style pipeline connections. When writing new code you should
// use the more general vtkAlgorithm::AddInputConnection(). See
// SetInput() for details.
void AddInput(vtkDataObject*);
void AddInput(int, vtkDataObject*);
protected:
vtkTestAlgorithmFilter();
~vtkTestAlgorithmFilter();
// Description:
// This is called by the superclass.
// This is the method you should override.
virtual int RequestDataObject(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
// convenience method
virtual int RequestInformation(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
// Description:
// This is called by the superclass.
// This is the method you should override.
virtual int RequestData(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
// Description:
// This is called by the superclass.
// This is the method you should override.
virtual int RequestUpdateExtent(vtkInformation*, vtkInformationVector**,
vtkInformationVector*);
virtual int FillOutputPortInformation(int port,
vtkInformation* info) override;
virtual int FillInputPortInformation(int port, vtkInformation* info) override;
private:
vtkTestAlgorithmFilter(const vtkTestAlgorithmFilter&); // Not implemented.
void operator=(const vtkTestAlgorithmFilter&); // Not implemented.
};
#endif
vtkTest.h
#ifndef __vtkTest_h
#define __vtkTest_h
#include <vtkDataObject.h>
class vtkTest : public vtkDataObject
{
public:
static vtkTest* New();
vtkTypeMacro(vtkTest, vtkDataObject);
void PrintSelf(ostream& os, vtkIndent indent) override;
void ShallowCopy(vtkDataObject* t) override;
vtkGetMacro(Value, double);
vtkSetMacro(Value, double);
protected:
vtkTest();
~vtkTest();
private:
vtkTest(const vtkTest&); // Not implemented.
void operator=(const vtkTest&); // Not implemented.
double Value;
};
#endif
CMakeLists.txt¶
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(AlgorithmFilter)
find_package(VTK COMPONENTS
CommonCore
)
if (NOT VTK_FOUND)
message(FATAL_ERROR "AlgorithmFilter: Unable to find the VTK build folder.")
endif()
# Prevent a "command line is too long" failure in Windows.
set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.")
add_executable(AlgorithmFilter MACOSX_BUNDLE AlgorithmFilter.cxx )
target_link_libraries(AlgorithmFilter PRIVATE ${VTK_LIBRARIES}
)
# vtk_module_autoinit is needed
vtk_module_autoinit(
TARGETS AlgorithmFilter
MODULES ${VTK_LIBRARIES}
)
Download and Build AlgorithmFilter¶
Click here to download AlgorithmFilter and its CMakeLists.txt file. Once the tarball AlgorithmFilter.tar has been downloaded and extracted,
cd AlgorithmFilter/build
If VTK is installed:
cmake ..
If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:
cmake -DVTK_DIR:PATH=/home/me/vtk_build ..
Build the project:
make
and run it:
./AlgorithmFilter
WINDOWS USERS
Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.