VTK源码分析:Type System

作为一款开源跨平台的数据可视化代码库,VTK以其清晰的流水线工作方式、丰富的后处理算法、异种渲染/交互方式,而被众多CAx软件选作后处理实施方案。而异种渲染/交互方式的实现,主要是倚重于VTK的类型系统,因此,有必要对这个问题予以研究分析。

另外,结合前面对FreeCAD类型系统的分析,本文旨在导出类型系统在设计与实现等方面的(非)技术约束

本文涉及的主要知识点包括,

  • Factory Method Pattern
  • Type Registration

注1:限于研究水平,分析难免不当,欢迎批评指正。

注2:文章内容会不定期更新。

一、相关组件

1.1 vtkObjectBase

vtkObjectBase定义了类型信息、引用计数等相关接口,而类型信息主要是基于其内部维护的类型名称字符串。

1.2 vtkObject

vtkObject派生于vtkObjectBase,增加了对象动态创建接口。

// Macro to use when you are a direct child class of vtkObjectBase, instead
// of vtkTypeMacro. This is required to properly specify NewInstanceInternal
// as a virtual method.
// It is used to determine whether a class is the same class or a subclass
// of the named class.

#define vtkBaseTypeMacro(thisClass, superclass)                                                    \
  vtkAbstractTypeMacro(thisClass, superclass);                                                     \
                                                                                                   \
protected:                                                                                         \
  virtual vtkObjectBase* NewInstanceInternal() const { return thisClass::New(); }                  \
                                                                                                   \
public:
// Same as vtkTypeMacro, but adapted for cases where thisClass is abstract.
#define vtkAbstractTypeMacro(thisClass, superclass)                                                \
  vtkAbstractTypeMacroWithNewInstanceType(thisClass, superclass, thisClass, #thisClass);           \
                                                                                                   \
public:


// Allows definition of vtkObject API such that NewInstance may return a
// superclass of thisClass.
#define vtkAbstractTypeMacroWithNewInstanceType(                                                   \
  thisClass, superclass, instanceType, thisClassName)                                              \
protected:                                                                                         \
  const char* GetClassNameInternal() const override { return thisClassName; }                      \
                                                                                                   \
public:                                                                                            \
  typedef superclass Superclass;                                                                   \
  static vtkTypeBool IsTypeOf(const char* type)                                                    \
  {                                                                                                \
    if (!strcmp(thisClassName, type))                                                              \
    {                                                                                              \
      return 1;                                                                                    \
    }                                                                                              \
    return superclass::IsTypeOf(type);                                                             \
  }                                                                                                \
  vtkTypeBool IsA(const char* type) override { return this->thisClass::IsTypeOf(type); }           \
  static thisClass* SafeDownCast(vtkObjectBase* o)                                                 \
  {                                                                                                \
    if (o && o->IsA(thisClassName))                                                                \
    {                                                                                              \
      return static_cast<thisClass*>(o);                                                           \
    }                                                                                              \
    return nullptr;                                                                                \
  }                                                                                                \
  VTK_NEWINSTANCE instanceType* NewInstance() const                                                \
  {                                                                                                \
    return instanceType::SafeDownCast(this->NewInstanceInternal());                                \
  }                                                                                                \
  static vtkIdType GetNumberOfGenerationsFromBaseType(const char* type)                            \
  {                                                                                                \
    if (!strcmp(thisClassName, type))                                                              \
    {                                                                                              \
      return 0;                                                                                    \
    }                                                                                              \
    return 1 + superclass::GetNumberOfGenerationsFromBaseType(type);                               \
  }                                                                                                \
  vtkIdType GetNumberOfGenerationsFromBase(const char* type) override                              \
  {                                                                                                \
    return this->thisClass::GetNumberOfGenerationsFromBaseType(type);                              \
  }

1.2 vtkObjectFactory

vtkObjectFactory定义了对象实例化的接口,同时将所有的对象工厂存储到静态成员变量RegisteredFactories。

二、关键流程

2.1 类型注册

在VTK中,CMake/vtkObjectFactory.cmake 定义了 vtk_object_factory_configure用于自动生成对应的vtkObjectFactory,

// CMake/vtkObjectFactory.cxx.in

@_vtk_object_factory_configure_EXPORT_MACRO@ void @_vtk_object_factory_library_name@_AutoInit_Construct()
{
  if(++@_vtk_object_factory_library_name@Count == 1)
  {
@_vtk_object_factory_configure_INITIAL_CODE@

    @_vtk_object_factory_library_name@ObjectFactory* factory = @_vtk_object_factory_library_name@ObjectFactory::New();
    if (factory)
    {
      // vtkObjectFactory keeps a reference to the "factory",
      vtkObjectFactory::RegisterFactory(factory);
      factory->Delete();
    }
  }
}

然后,借助于VTK_MODULE_INIT宏完成vtkObjectFactory的注册。

// Common/Core/vtkAutoInit.h


// Description:
// Initialize the named module, ensuring its object factory is correctly
// registered. This call must be made in global scope in the
// translation unit of your executable (which can include a shared library, but
// will not work as expected in a static library).
//
// @code{.cpp}
// #include "vtkAutoInit.h"
// VTK_MODULE_INIT(vtkRenderingOpenGL2);
// @endcode
//
// The above snippet if included in the global scope will ensure the object
// factories for vtkRenderingOpenGL2 are correctly registered and unregistered.
#define VTK_MODULE_INIT(M)                                                                         \
  VTK_AUTOINIT_DECLARE(M) namespace                                                                \
  {                                                                                                \
    static struct M##_ModuleInit                                                                   \
    {                                                                                              \
      /* Call <mod>_AutoInit_Construct during initialization.  */                                  \
      M##_ModuleInit() { VTK_AUTOINIT_CONSTRUCT(M) }                                               \
    } M##_ModuleInit_Instance;                                                                     \
  }

2.2 对象创建

vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname, bool)
{
  if (!vtkObjectFactory::RegisteredFactories)
  {
    vtkObjectFactory::Init();
  }

  vtkObjectFactory* factory;
  vtkCollectionSimpleIterator osit;
  for (vtkObjectFactory::RegisteredFactories->InitTraversal(osit);
       (factory = vtkObjectFactory::RegisteredFactories->GetNextObjectFactory(osit));)
  {
    vtkObject* newobject = factory->CreateObject(vtkclassname);
    if (newobject)
    {
      return newobject;
    }
  }

  return nullptr;
}

三、总结

由上述对VTK类型系统的分析,同时结合<FreeCAD源码分析:Type System>一文,可以总结出类型系统实现的要点,

  • 定义对象基类
  • 定义构造器及其接口
  • 将构造器(手动/自动)注册到类型注册表
  • 根据类型名字获取构造器,然后实例化对象
VTK FreeCAD
基类 vtkObjectBase Base::BaseClass
构造器 vtkObjectFactory Base::Type
类型注册表 vtkObjectFactory::RegisteredFactories Base::Type::typedata

参考文献

  • Erich Gamma. Design Patterns:elements of reusable object-oriented software. Addison Wesley, 1994.

网络资料

VTKicon-default.png?t=N7T8https://vtk.org/

大型CAx(CAD/CAE/CAM)软件研发中的职责编排icon-default.png?t=N7T8https://blog.csdn.net/qq_26221775/article/details/136975550?spm=1001.2014.3001.5502

FreeCAD源码分析:Type Systemicon-default.png?t=N7T8https://blog.csdn.net/qq_26221775/article/details/140468677?spm=1001.2014.3001.5502

相关推荐

  1. SDWebImage分析

    2024-07-21 16:16:02       23 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 16:16:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 16:16:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 16:16:02       45 阅读
  4. Python语言-面向对象

    2024-07-21 16:16:02       55 阅读

热门阅读

  1. 牛客暑假训练2 C.Red Walking on Grid

    2024-07-21 16:16:02       17 阅读
  2. Python之后端Django(六)

    2024-07-21 16:16:02       13 阅读
  3. blender和3dmax和maya和c4d比较

    2024-07-21 16:16:02       17 阅读
  4. 数据结构第33节 在不同领域的应用

    2024-07-21 16:16:02       12 阅读
  5. 【软考】UML中的关联关系

    2024-07-21 16:16:02       20 阅读
  6. firefly rk3288 ubuntu23.10 网卡名为end0 改为eth0

    2024-07-21 16:16:02       15 阅读
  7. C++狼人杀游戏(真的能运行!!!)

    2024-07-21 16:16:02       14 阅读
  8. 跨平台游戏引擎 Axmol-2.1.4 发布

    2024-07-21 16:16:02       21 阅读
  9. 使用 hutool工具实现导入导出功能。

    2024-07-21 16:16:02       21 阅读
  10. https证书申请

    2024-07-21 16:16:02       18 阅读
  11. feign 报错 Connection reset executing POST

    2024-07-21 16:16:02       14 阅读
  12. Python 热门面试题(七)

    2024-07-21 16:16:02       15 阅读
  13. 基本的DQL语句-单表查询

    2024-07-21 16:16:02       19 阅读
  14. ios CCUIFont.m

    2024-07-21 16:16:02       19 阅读