VTK之自定义Filter类

一个Filter类定义了RequestData()函数,当Filter调用Update()后,即可响应RequestData()函数。

VTK管线机制

  VTK中通过管线机制来实现组合各种算法处理数据。每一种算法是一个Filter,多个Filter连接子啊一起形成了VTK管线。每个Filter可以分为两个组成部分:一个是算法部分,继承自vtkAlgorithm,主要负责处理输入的数据和信息;另一个是执行对象,继承自vtkExecutive,负责通知算法对象何时运行以及传递需要处理的数据和信息。
  Filter类继承自vtkAlgorithm及其 子类,实例化时,其内部会生成一个默认的vtkExecutive对象,用于管理执行管线。
数据和信息通过端口在Filter中传递,根据数据流的方向,分为输入端口和输出端口。Filter之间通过端口(Port)建立连接(Connect)。例如一个标准的连接代码如下:

Filter2->SetInputConnection(Filter1->GetOutputPort())

  VTK中存在多种数据结构,如果每种数据类型都要定义一种Filter,将会产生非常庞大的Filter群,不利于定义一种通用的VTK执行管线。管线连接是通过逻辑端口(Logic Port)而不是数据流实现,因此在形成连接的过程中不需要知道实际的数据类型,而是在执行时进行数据类型检查,以决定管线是否执行。VTK中定义了一个vtkInformation类,用于存储和传递管线执行过程中的信息、请求和数据,实现执行管线的连接和控制。
  vtkInformation是实现VTK执行管线的一个非常重要的类。它是一个Map容器,采用Key-Value的映射方法,通过索引(Key)的类型来决定其对应的数据,用于存储管线中的各种信息和数据。
  vtkInformation类中 索引Key的类型为vtkInformationKey的子类,VTK定义了大量的索引类型,这些类都继承自vtkInformationKey。

管线执行模型

   请求是VTK执行管线的一个基本操作,一个管线执行模型右多个请求共同完成。管线中处理一个Filter的请求 时,通常会先传递至为其提供数据输入的上流Filter,待上流的Filter处理完请求再在当前Filter中进行处理。执行对象在处理请求时,通常需要算法对象的协助来完成。执行对象会将请求发送至算法对象,并由vtkAlgorithm::ProcessRequest()进行处理。所有Filter类中都会实现该函数,并处理相关请求。管线执行过程如下图所示。

这里写图片描述

自定义Filter基本步骤

  实现Filter类时需要根据需求选择合适的基类,vtkAlgorithm是所有Filter类的共同基类,通常很少直接使用其 作为基类,而是更多的是采用其子类。比如,图形类Filter通常使用vtkPolyDataAlgorithm或者vtkUnstructedGridAlgorithm作为基类。 实现一个Filter,需要以下三个重要步骤。

1、定义管线接口

  在构造函数中确定说输入和输出的端口数目和数据类型。设置输入端口个数和输出端口个数的函数分别是
vtkAlgorithm::SetNumberOfInputPorts()和vtkAlgorithm::SetNumberOfOutputPorts()。下图是vtkPolyDataAlgorithm类的构造函数定义。

这里写图片描述

  由前面内容可知,端口信息对象定义在vtkAlgorithm中,用于存储端口的需求信息。每个输入端口对应一个输入端口信息对象,使用vtkAlgorithm::FillInputPortInformation()设置输入端口信息;每个输出端口对应一个输出端口信息对象,使用vtkAlgorithm::FillOutputPortInformation()设置输出端口信息。vtkPolyDataAlgorithm类中定义如下图所示。

这里写图片描述

2、定义用户接口

  Filter需要定义多个用户接口来设置参数,以调节Filter执行效果。对于每个Filter,需要覆盖基类的PrintSelf()函数。

3、实现管线请求

  VTK管线执行是通过请求完成的,管线执行时Filter会收到多个请求来处理信息和数据,这些请求首先发送到Filter的执行对象中,并由vtkExecutive::ProcessReqquest()进行处理。vtkPolyDataAlgorithm中的ProcessReqquest()如下图。

这里写图片描述

REQUEST_DATA()是执行Filter的主要函数。

示例演示

 实现一个可以输出进度信息的Filer。

CMakeLists.txt代码

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(ReportProgressFilterTest)
FIND_PACKAGE(VTK REQUIRED)
INCLUDE(${VTK_USE_FILE})
ADD_EXECUTABLE(ReportProgressFilterTest    ReportProgressFilterTest.cpp
                                        vtkReportProgressFilter.h 
                                         vtkReportProgressFilter.cpp)
TARGET_LINK_LIBRARIES(ReportProgressFilterTest ${VTK_LIBRARIES})

vtkReportProgressFilter.h

#ifndef __vtkReportProgressFilter_h
#define __vtkReportProgressFilter_h

#include "vtkPolyDataAlgorithm.h"

class vtkReportProgressFilter : public vtkPolyDataAlgorithm 
{
public:
    vtkTypeMacro(vtkReportProgressFilter,vtkPolyDataAlgorithm);

    static vtkReportProgressFilter *New();

protected:
    vtkReportProgressFilter(){}
    ~vtkReportProgressFilter(){}

    int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);

private:
    vtkReportProgressFilter(const vtkReportProgressFilter&);  // Not implemented.
    void operator=(const vtkReportProgressFilter&);  // Not implemented.
};

#endif

vtkReportProgressFilter.cpp

#include "vtkReportProgressFilter.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkInformationVector.h"
#include "vtkInformation.h"
#include "vtkDataObject.h"
#include "vtkSmartPointer.h"

vtkStandardNewMacro(vtkReportProgressFilter);

int vtkReportProgressFilter::RequestData(vtkInformation *vtkNotUsed(request),
                                         vtkInformationVector **inputVector,
                                         vtkInformationVector *outputVector)
{
    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
    vtkInformation *outInfo = outputVector->GetInformationObject(0);

    vtkPolyData *input = vtkPolyData::SafeDownCast(
        inInfo->Get(vtkDataObject::DATA_OBJECT()));

    vtkPolyData *output = vtkPolyData::SafeDownCast(
        outInfo->Get(vtkDataObject::DATA_OBJECT()));

    for(vtkIdType i = 0; i < input->GetNumberOfPoints(); i++)
    {
        this->UpdateProgress(static_cast<double>(i)/input->GetNumberOfPoints());
    }

    output->ShallowCopy(input);

    return 1;
}

ReportProgressFilterTest.cpp

#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkSphereSource.h>
#include <vtkCallbackCommand.h>
#include <vtkCommand.h>
#include "vtkReportProgressFilter.h"

void ProgressFunction(vtkObject* caller, long unsigned int eventId, void* clientData, void* callData);

int main(int, char *[])
{ 
    vtkSmartPointer<vtkSphereSource> sphereSource =
        vtkSmartPointer<vtkSphereSource>::New();
    sphereSource->Update();

    vtkSmartPointer<vtkCallbackCommand> progressCallback = 
        vtkSmartPointer<vtkCallbackCommand>::New();
    progressCallback->SetCallback(ProgressFunction);

    vtkSmartPointer<vtkReportProgressFilter> testFilter = 
        vtkSmartPointer<vtkReportProgressFilter>::New();
    testFilter->SetInputConnection(sphereSource->GetOutputPort());
    testFilter->AddObserver(vtkCommand::ProgressEvent, progressCallback);
    testFilter->Update();

    system("pause");
    return EXIT_SUCCESS;
}

void ProgressFunction ( vtkObject* caller,
                       long unsigned int vtkNotUsed(eventId),
                       void* vtkNotUsed(clientData),
                       void* vtkNotUsed(callData) )
{
    vtkReportProgressFilter* testFilter = static_cast<vtkReportProgressFilter*>(caller);
    std::cout << "Progress: " << testFilter->GetProgress() << std::endl;
}

运行结果:

这里写图片描述

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VTK_CURSOR_CUSTOM是VTK(Visualization Toolkit)中提供的一种自定义光标的方式。使用VTK_CURSOR_CUSTOM可以让用户在VTK应用程序中使用自己定义的光标图像,从而增强应用程序的个性化和用户体验。 要使用VTK_CURSOR_CUSTOM,需要按照以下步骤进行操作: 1. 创建自定义光标图像。可以使用任何绘图工具创建PNG、JPEG或BMP格式的图像。 2. 将光标图像加载到VTK中。可以使用vtkImageDatavtkTexture等VTK来加载图像数据。 3. 创建vtkCursor2D对象并设置自定义光标。vtkCursor2D是VTK中的一个2D光标,可以在视图中显示自定义光标。 4. 将vtkCursor2D对象添加到vtkRenderWindow中。vtkRenderWindow是VTK中的一个窗口,可以显示3D场景和2D元素。 5. 最后,将vtkRenderWindow显示出来,用户就可以看到自定义光标了。 下面是一个使用VTK_CURSOR_CUSTOM创建自定义光标的示例代码: ```python import vtk # 创建自定义光标图像 cursor_image = vtk.vtkPNGReader() cursor_image.SetFileName("custom_cursor.png") # 创建vtkCursor2D对象并设置自定义光标 cursor = vtk.vtkCursor2D() cursor.SetImageData(cursor_image.GetOutput()) # 创建vtkRenderWindow对象并添加vtkCursor2D对象 ren = vtk.vtkRenderer() renWin = vtk.vtkRenderWindow() renWin.AddRenderer(ren) iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) iren.SetInteractorStyle(vtk.vtkInteractorStyleImage()) iren.Initialize() cursor.SetRenderer(ren) cursor.SetDisplayPosition(100, 100) cursor.Update() # 显示vtkRenderWindow renWin.Render() iren.Start() ``` 这个示例代码会创建一个自定义的光标图像custom_cursor.png,并将它加载到vtkCursor2D对象中。然后将vtkCursor2D对象添加到vtkRenderWindow中,并显示出来。用户可以在vtkRenderWindow中看到自定义光标,并在应用程序中使用它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值