VTK交互-观察者/命令模式

观察者/命令模式

vtk中用到大量的面向对象设计模式,如工厂模式、观察者/命令模式、另外还用到引用计数与智能指针等高级内存管理知识。

前面的博客讲过观察者/命令模式这个模式了 这里就不细说了。

观察者/命令模式(Observer/Command)是vtk里用的较多的设计模式。vtk中 绝大多数的类都派生自vtkobject。查看类vtkobject的接口可以找到AddObserver()、RemoveObserver()、GetCommand()等函数,从函数的字面意思可以看出,这些函数是与观察者/命令模式相关的。

观察者/命令模式是指一个Object可以有多个Observer,它定义了对象间的一种多对多的依赖关系,当一个Object对象的状态发生改变时,所有依赖于它的Observer对象都得到通知而被自动更新。命令模式属于对象的行为模式,它将一个请求封装为一个对象,并提供一致性发送请求的接口,当一个事件发生时,它不直接把事件传递给事件调用者,而是在命令和调用者之间增加一个中间者,讲这种关系直接切断,同时将两者都隔离。事件调用者只是和接口打交道,不和具体时间实现交互,在vtk中,可以通过这两种方式来实现观察者/命令模式,它们分别是使用事件回调函数以及从VTK派生出来具体的子类。

事件回调函数

在vtkOBject中,有如下函数:

unsigned long AddObserver(unsigned long event,vtkCommand *,float priority=0.0f);
unsigned long AddObserver(unsigned char* event,vtkCommand *,float priority=0.0f);

AddObserver()函数的作用就是针对某个事件添加观察者到某个VTK对象中,当该对象发生观察者感兴趣的事件时,就会调用回调函数,执行相关的操作。

#include <vtkSmartPointer.h>
#include <vtkImageReader2.h>
#include <vtkMatrix4x4.h>
#include <vtkImageReslice.h>
#include <vtkLookupTable.h>
#include <vtkImageMapToColors.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkCommand.h>
#include <vtkImageData.h>
#include <vtkMetaImageReader.h>
#include <vtkImageCast.h>
#include"vtkPNGReader.h"
#include"vtkAutoInit.h"
#include"vtkImageViewer2.h"
#include"vtkProperty.h"
#include"vtkCallbackCommand.h"
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL);

long pressCounts = 0;
void MyCallbackFunc(vtkObject *,unsigned long eid,void *clientdata,void *calldata)
{
    std::cout << "You have clicked: " << ++pressCounts << " Times." << endl;
}

int main(int argc,char *argv[])
{
    std::string filename = "VTK-logo.png";
    vtkSmartPointer<vtkPNGReader> reader = vtkSmartPointer<vtkPNGReader>::New();
    reader->SetFileName(filename.c_str());


    vtkSmartPointer<vtkImageViewer2> viewer = vtkSmartPointer<vtkImageViewer2>::New();
    viewer->SetInputData(reader->GetOutput());

    vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    viewer->SetupInteractor(interactor);
    viewer->Render();

    vtkSmartPointer<vtkCallbackCommand> mouseCallback = vtkSmartPointer<vtkCallbackCommand>::New();
    mouseCallback->SetCallback(MyCallbackFunc);

    interactor->SetRenderWindow(viewer->GetRenderWindow());
    interactor->AddObserver(vtkCommand::LeftButtonPressEvent,mouseCallback);
    interactor->Initialize();
    interactor->Start();

    return 0;
}

这里写图片描述

vtkCommand子类

观察者/命令模式除了使用事件回调函数外,还可以直接从vtkCommand类中派生出子类来实现。

#include <vtkSmartPointer.h>
#include <vtkImageReader2.h>
#include <vtkMatrix4x4.h>
#include <vtkImageReslice.h>
#include <vtkLookupTable.h>
#include <vtkImageMapToColors.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkCommand.h>
#include <vtkImageData.h>
#include <vtkMetaImageReader.h>
#include <vtkImageCast.h>
#include"vtkPNGReader.h"
#include"vtkAutoInit.h"
#include"vtkImageViewer2.h"
#include"vtkProperty.h"
#include"vtkCallbackCommand.h"
#include"vtkPolyDataMapper.h"
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL);
#include"vtkConeSource.h"

class vtkMyCallback : public vtkCommand
{
public:
    static vtkMyCallback *New()
    {
        return new vtkMyCallback;
    }
    void SetObject(vtkConeSource *cone)
    {
        m_Cone = cone;
    }
    virtual void Execute(vtkObject *caller,unsigned long eventId,void *callData)
    {
        std::cout << "Left button pressed.\n"
            << "The Height:" << m_Cone->GetHeight() << "\n"
            << "The Radius:" << m_Cone->GetRadius() << std::endl;
    }
private:
    vtkConeSource *m_Cone;
};
int main()
{
    vtkSmartPointer<vtkConeSource> cone = vtkSmartPointer<vtkConeSource>::New();
    cone->SetHeight(3.0);
    cone->SetRadius(1.0);
    cone->SetResolution(1.0);

    vtkSmartPointer<vtkPolyDataMapper> coneMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    coneMapper->SetInputConnection(cone->GetOutputPort());

    vtkSmartPointer<vtkActor> coneActor = vtkSmartPointer<vtkActor>::New();
    coneActor->SetMapper(coneMapper);

    vtkSmartPointer<vtkRenderer> ren1 = vtkSmartPointer<vtkRenderer>::New();
    ren1->AddActor(coneActor);
    ren1->SetBackground(0.1,0.2,0.4);

    vtkSmartPointer<vtkRenderWindow> renwin = vtkSmartPointer<vtkRenderWindow>::New();
    renwin->AddRenderer(ren1);
    renwin->SetSize(300, 300);

    vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    iren->SetRenderWindow(renwin);

    vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    iren->SetInteractorStyle(style);

    vtkSmartPointer<vtkMyCallback> callback = vtkSmartPointer<vtkMyCallback>::New();
    callback->SetObject(cone);

    iren->AddObserver(vtkCommand::LeftButtonPressEvent,callback);
    iren->Initialize();
    iren->Start();
    return EXIT_SUCCESS;
}

这里写图片描述

上面的程序同样演示的是鼠标左键单击消息,如果监听到单击消息,就在控制台中打出主程序所设置的椎体的高和底面积等信息。vtkMyCallback是从vtkCommand类中派生的,SetObject()函数用于设置椎体对象。利用这种方式使用VTK的观察者/命令模式也应该遵循如下三个步骤。

**(1) 从vtkCommand类派生子类,并实现vtkCommand::Execute()虚函数,该函数的原型为:
** virtual void Execute(vtkObject *caller,unsigned long evemtId,void *callData)=0;

(3) 调用AddObserver()函数监听感兴趣的事件。如果所监听的事件会发生,会调用vtkCommand子类中的Execute()函数,针对所监听的事件,程序需要实现的功能一般都放在Execute()函数中。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值