VTK之类的实现

vtkObject类分析

  vtkObjectBase主要实现引用计数,因此vtkObject及其子类也都继承了该特性。vtkObject中实现了在VTK中非常广泛使用的观察者/命令机制,能够方便地处理消息响应,例如处理鼠标消息、键盘消息、进度消息等,VTK中Widget中大量使用了该机制进行消息处理。vtkObject中定义了一个vtkSubjectHelper对象来管理观察者。vtkSubjectHelper内部定义了一个观察者vtkObserver对象链表。vtkObserver表示一个观察者,其内部定义了一个vtkCommand指针,一个消息ID以及一个表示优先级的变量。当观察者监听到一个消息ID,就响应vtkCommand定义的回调函数。
  vtkObject通过如下函数添加和删除观察者:

unsigned long AddObserver(unsigned long event, vtkCommand*,float priority = 0.0f);
void RemoveObserver(unsigned long tag);

AddObserver用于添加一个观察者。当执行该函数时,vtkSubjectHelper对象根据event、vtkCommand对象和priority参数封装为一个vtkObserver,并根据优先级priority顺序添加至观察者列表中。

VTK类的实现

  vtkObjectBase is the base class for all reference counted classes in the VTK. These classes include vtkCommand classes, vtkInformationKey classes, and vtkObject classes.
  vtkObject作为VTK类库中目标对象的基类。vtkObject通过注册感兴趣的事件,把Command和事件联系在一起,然后编写回调函数响应事件的发生。例如vtkRenderer当信息StartEvent发生时,开始对数据进行渲染,而当消息EndEvent发生时停止渲染。任意一个VTKObject的实例可以通过调用AddObserver()方法来添加对事件的观察,只需要将事件的id和自定义的回调函数进行关联,VTK就能方便的实现消息的处理。
  vtkObject的所有的子类必须用New()方法创建,用Delete()方法删除。因为构造函数时保护的。New()一个静态方法,使用Factory设计模式来创建一个实例。VTK里的类,构造函数和析构函数都是受保护类型。
  vtkObjectBase的构造函数、析构函数、拷贝函数以及“=”操作符都被声明为“protected”类型。

VTK类的实现步骤

第一步:定义类的构造函数、析构函数、赋值运算符以及拷贝构造函数。


VTK对象都是通过内部定义静态函数New()来生成,因此构造函数、析构函数都要定义为protected类型。而对与赋值“=”运算符和拷贝构造函数定义为private类型,只做声明不用实现。如上图所示。

第二步:定义标准创建和删除函数。

VTK之类的实现_第1张图片
对于继承自vtkObjectBase的类,必须覆盖New()来生成一个实际类的对象,而不是得到一个vtkObjectBase对象;对于Delete()函数,直接继承自vtkObjectBase类即可。在类定义中声明一个共有静态函数New(),如上图所示,在头文件中加入

static vtkTestClass *New();

在实现文件构造函数之前加入如下代码:

vtkStandardNewMacro(vtkTestClass);

如下图所示:

VTK之类的实现_第2张图片

vtkStandardNewMacro是VTK中定义的一个宏,作用是定义一个通用的New()函数 ,使用时需要将实际的类名传递给它。

第三步:定义VTK类的基本函数。

  这些基本函数包括GetClassNameInternal()、IsTypeOf()、IsA()、SaftDownCast()、NewInstanceInternal()、NewInstance()等。这些函数在vtkObjectBase中定义,用户需要在子类中覆盖这些函数。不过,借助VTK的宏定义,不需要重新实现这些函数。

vtkTypeMacro(vtkTestClass,vtkObject);

第四步:添加成员变量及相关函数。

  对于一个类的成员变量,通常都需要定义相应的Set()和Get()函数。VTK也提供了多种类型的宏来定义一不同类型的成员变量设置函数。比如对于一个标量数据成员,可以使用vtkSetMacro和vtkGetMacro宏。

第五步:添加PrintSelf()函数。

覆盖基类PrintSelf()函数,实现打印当前类对象的状态。

示例代码

vtkTestClass.h

#ifndef __vtkTestClass_h
#define __vtkTestClass_h

#include 

class vtkTestClass: public vtkObject
{
public:
    vtkTypeMacro(vtkTestClass,vtkObject);
    static vtkTestClass *New();

    vtkGetMacro(Flag,  bool);
    vtkGetMacro(Speed, double);
    vtkGetVector3Macro(Position,double);

    vtkSetMacro(Flag,bool);
    vtkSetMacro(Speed,double);
    vtkSetVector3Macro(Position,double);

    vtkBooleanMacro(Flag, bool);

    void PrintSelf(ostream &os, vtkIndent indent);

private:
    double Speed;
    double Position[3];
    bool   Flag;

protected:
    vtkTestClass();
    ~vtkTestClass();

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

};

#endif

vtkTestClass.cpp

#include "vtkTestClass.h"
#include "vtkObjectFactory.h"

vtkStandardNewMacro(vtkTestClass);

vtkTestClass::vtkTestClass()
{
    Flag = false;

    Speed = 0;

    Position[0] = 0;
    Position[1] = 0;
    Position[2] = 0;

}

vtkTestClass::~vtkTestClass()
{
}

void vtkTestClass::PrintSelf(ostream &os, vtkIndent indent)
{
    this->Superclass::PrintSelf(os, indent);
    os << "Position: " << Position[0] << " " 
        << Position[1] << " " 
        << Position[2] << std::endl
        << "Speed: "<<Speed<<std::endl
        << "Flag:"<<Flag<<std::endl;
}

你可能感兴趣的:(Study-VTK)