Skip to content


# AlgorithmFilter

VTKEx/Cxx/Developers/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.

Question

If you have a simple question about this example contact us at VTKExProject If your question is more complex and may require extended discussion, please use the VTK Discourse Forum

### Code

AlgorithmFilter.cxx

    #include <vtkSmartPointer.h>

    #include "vtkTestAlgorithmFilter.h"
    #include "vtkTest.h"

    int main(int, char *[])
    {
      vtkSmartPointer<vtkTest> inputTest =
        vtkSmartPointer<vtkTest>::New();
      inputTest->SetValue(5.6);
      std::cout << "Input value: " << inputTest->GetValue() << std::endl;

      vtkSmartPointer<vtkTestAlgorithmFilter> filter = vtkTestAlgorithmFilter::New();
      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.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

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.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);
      }
    }

### CMakeLists.txt

    cmake_minimum_required(VERSION 3.3 FATAL_ERROR)

    project(AlgorithmFilter)

    find_package(VTK COMPONENTS
      vtkCommonCore QUIET)
    if (NOT VTK_FOUND)
      message("Skipping AlgorithmFilter: ${VTK_NOT_FOUND_MESSAGE}")
      return ()
    endif()
    message (STATUS "VTK_VERSION: ${VTK_VERSION}")
    if (VTK_VERSION VERSION_LESS "8.90.0")
      # old system
      include(${VTK_USE_FILE})
      add_executable(AlgorithmFilter MACOSX_BUNDLE AlgorithmFilter.cxx )
      target_link_libraries(AlgorithmFilter PRIVATE ${VTK_LIBRARIES})
    else ()
      # include all components
      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}
        )
    endif ()

### 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.