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

来源:互联网 发布:淘宝授权书psd模板 编辑:程序博客网 时间:2024/06/03 12:30

观察者/命令模式

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()函数中。

原创粉丝点击