1.交互器样式遇到的难题

交互器样式(如vtkInteractorStyleImage)主要是根据不同的键盘、鼠标等消息来控制相机(vtkCamera)/Actor等相关参数,从而达到了交互的目的!
然而,在渲染场景中,这些交互器样式是没有表达实体的。也就是说,在交互之前,我们(用户)必须知道那些键盘消息或者鼠标消息是与哪些事件绑定的,在整个交互过程中,用户“看不到”交互器样式长什么样子,比如,使用vtkInteractorStyleImage交互器样式时,必须知道按键<R>是用于窗宽窗位、相机参数等的重置,鼠标中键可以平移图像,按住鼠标左键不放然后移动鼠标可以调节窗宽窗位等。
在与渲染场景中的对象进行交互时,如果可以“看得见”交互的样式,这样的交互过程就会更加的人性化,比如,要在地图上测量AB两点之间的距离,直观的做法就是:在A点上单击,当松开鼠标后,程序在单击的位置上生成一个端点(该端点可以是圆形、十字形或者其他任何形状),然后移动鼠标至终点,鼠标移动过程中,在A点与鼠标光标的当前位置生成一条直线,当鼠标移动至B点时,再单击B点位置,即可显示出AB两点的距离以及在两点之间生成一条直线。显然,这样的交互方式比交互器样式更加直观、生动。

2.交互部件

VTK提供了功能强大的、可以看得见的交互部件,即Widget。VTK的Widget类主要包括vtk3DWidget和vtkAbstractWidget两个父类。继承关系如下图所示:
从上图中,我们可以看到,vtk3DWidgetvtkAbstractWidget都派生自vtkInteractorObserver,其中,前者主要是在三维渲染场景中生成一个可以用于控制数据的可视化实体,比如点,线段(曲线)、平面、球体、包围盒(线框)等;而后者是VTK里实现“交互/表达实体”设计的所有Widget的基类
vtk3DWidget和vtkAbstractWidget的共同基类vtkInteractorObserver里的虚函数OnChar(),主要是用于响应交互的开关状态,对应的方法为:
vtkInteractorObserver::SetEnable(int);
vtkInteractorObserver::EnableOn();
vtkInteractorObserver::EnableOff();
vtkInteractorObserver::On();
vtkInteractorObserver::Off();
VTK中Widget的设计是从VTK 5.0版本开始引入的,最初的Widget是从vtk3DWidget派生出来的,从VTK5.1版本开始,VTK中的Widget重新进行设计,主要的设计理念是将Widget的消息处理与几何表达实体分离,但还是保留了vtk3DWidget及其子类

2.1 vtkAbstractWidget

vtkAbstractWidget作为基类,只定义一些公共的API以及实现了“交互/表达实体”分离的设计机制,其中,把从vtkRenderWindowInteractor路由过来的消息(事件)交给vtkAbstractWidget的“交互”部分处理,而Widget的“表达实体”则对应一个vtkProp对象(或者是vtkWidgetRepresentation的子类)。
这样做的好处是:事件处理与Widget的表达实体互不干扰,而且可以实现同类Widget使用不同的表达形式,比如,对于测量距离的Widget,可以定义两个十字形作为Widget的两个端点(也可以定义两个球体来表达)。
此外,vtkAbstractWidget类提供了访问vtkWidgetEventTranslator对象的函数,GetEventTranslator(),该对象的作用可以将VTK事件映射为Widget事件(定义在vtkWidgetEvent.h文件中),通过vtkWidgetEventTranslator类,我们可以定制与符合自己习惯使用的控制事件相绑定。比如,对于一个测量长度的vtkDistanceWidget,默认的操作是鼠标左键可以确定两个端点的位置,如果对这种操作不习惯,想用鼠标右键实现同样的功能,可以通过代码来实现:
vtkWidgetEventTranslation* eventTranslation = widget->GetEventTranslator();
eventTranslation->SetTranslation(vtkCommand::RightButtonPressEvent,vtkWidgetEvent::Select);
eventTranslation->SetTranslation(vtkCommand::RightButtonReleaseEvent,vtkWidgetEvent::Select);

2.2 VTK事件与Widget事件间的转换关系

上面已经初步分析了何如定制属于自己的Widget交互部件。下面进一步讨论:

每个vtkAbstractWidget子类的内部,都会根据各个子类的功能,使用类vtkWidgetEventTranslator,将VTK事件爱你翻译成Widget事件。同时,利用类vtkWidgetCallbackMapper将相应的Widget事件与各个受保护的静态操作函数关联起来,具体关系如下图所示:
以vtkDistanceWidget为例,在该类的构造函数中,有如下代码:
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonPressEvent,vtkWidgetEvent::AddPoint,this,vtkDistanceWidget::AddPointAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::MouseMoveEvent,vtkWidgetEvent::Move,this,vtkDistanceWidget::MoveAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonReleaseEvent,vtkWidgetEvent::EndSelect,this,vtkDistanceWidget::EndSelectAction);

上述代码中的CallbackMapper即为vtkWidgetCallbackMapper类型,SetCallbackMethod()函数代码如下:

void vtkWidgetCallbackMapper::SetCallbackMethod(unsigned long VTKEvent,unsigned long widgetEvent,vtkAbstractWidget* w,CallbackType f)
{this->EventTranslator->SetTranslation(VTKEvent, widgetEvent);this->SetCallbackMethod(widgetEvent,w,f);
}

2.3 小结

通过上面可知,vtkWidgetCallbackMapper::SetCallbackMathod()将VTK消息与实际的操作函数联系起来,SetCallbackMethod()函数内部则是调用vtkWidgetEventTranslator::SetTranslation方法将VTK事件翻译成Widget事件,这种实现机制有点类似Qt里的信号-槽连接。

3.参看资料

1.《C++ primer》
2.《The VTK User’s Guide – 11thEdition》
3.  张晓东, 罗火灵. VTK图形图像开发进阶[M]. 机械工业出版社, 2015.

VTK修炼之道73:交互部件_Widget应用综述相关推荐

  1. VTK修炼之道77:交互部件_分割/配准类Widget与其他Widget

    1.分割/配准交互部件 图像分割与配准是数字图像处理技术两大主要的应用领域,特别是在医学图像处理中. 著名的医学图像分割与配准工具包ITK(Insight Segmentation & Reg ...

  2. VTK修炼之道71:交互与Widget_观察者/命令模式

    1.前言 一个强大的可视化系统不仅需要强大的数据处理能力,也需要方便易用的交互功能.图形处理软件ParaView(hhttp://www.paraview.org).德国癌症研究中心研发的MITK(h ...

  3. VTK修炼之道74:交互部件_Widget的创建

    1.创建Widget交互的步骤 虽然每个Widget都提供了不同的功能以及不同的API,但是,Widget的创建以及使用基本都是类似的.创建Widget的一般步骤如下: 1.实例化Widget: 2. ...

  4. VTK修炼之道75:交互部件_测量类Widget的应用

    1.与测量类相关的主要Widget 与测量类相关的主要Widget如下: vtkDistanceWidget:用于在二维平面上测量两点之间的距离. vtkAngleWidget:用于在平面的角度测量. ...

  5. VTK修炼之道76:交互部件_标注类Widget的应用

    1.标注类Widget 在可视化程序中,经常会对某个对象做一些标注说明,比如,在医学图像诊断中,常常会手动标注出被诊断为肿瘤的区域或者其他病变区域,并用文字进行标注. VTK中,与标注相关的Widge ...

  6. VTK修炼之道78:交互与拾取_点拾取

    1.拾取 选择拾取是人机交互过程的一个重要功能. 一个最经典的例子就是,在玩3D游戏时,场景中可能会存在多个角色,有时需要用鼠标来选择所要控制的角色,这就要用到拾取功能. 另外,在某些三维图形的编辑软 ...

  7. VTK修炼之道27:图像基本操作_三维图像切片交互提取(回调函数、观察者-命令模式)

    1.鼠标滑动提取三维图像切片 学习三维图像切面的提取后,我们可以实现一个稍微复杂的程序--通过滑动鼠标来切换三维图像切片,这也是医学图像处理软件中一个很基本的功能.实现该功能难点是怎样在VTK中控制鼠 ...

  8. VTK修炼之道79:交互与拾取_单位拾取

    1.单位拾取 示例代码: #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL) VTK_MODULE_INIT(vtkI ...

  9. VTK修炼之道70:体绘制讨论_光照阴影、VTKLODProp3D

    1.光照与阴影 通过VTKVolumeProperty可以设置体绘制阴影效果(Shading).阴影效果主要受环境光系数.散射光系数.反射光系数和高光强度四个参数影响. vtkVolumeProper ...

最新文章

  1. proguaid 混淆代码
  2. python爬虫代码1000行-最精简的爬虫 --仅需4行代码(python)
  3. OBJC依赖库管理利器cocoapods 安装及使用详细图解
  4. 计算硼原子的基态能级B---交换能
  5. [转] ROS-I simple_message 源码分析:MessageManager
  6. Windows Live Writer 在win2003 的安装方法
  7. 在Docker中部署Asp.net core2.1以及修改发布
  8. vue 项目如何引入微信sdk,使用微信接口
  9. SpringBoot集成Es使用ElasticSearchTemplate7.x版本自动注入失败解决
  10. 高斯滤波matlab函数,matlab自带函数实现高斯滤波(gauss filter)快速算法
  11. 《光剑文集》青玉案: 27首
  12. 李维:我的回忆和一些有趣的事(About Borland)(转载)
  13. HDU 6638 Snowy Smile(线段树)
  14. ubuntu借助windows的网络共享上网
  15. HTML简单静态页面的编写
  16. win10系统每天凌晨3点左右,自动关机重启
  17. android 雷达图 蜘蛛图
  18. mysql 客户端简单搭建
  19. 2020年第十五届全国大学生智能汽车竞赛技术报告
  20. Python基础 | Python的组合数据类型

热门文章

  1. 互联网IP路由的逐跳全局最优化原则-Dijkstra算法证明
  2. 网站页面设计基本尺寸
  3. Linux基本网路配置及软件包的安装
  4. k8s之VelaQL简单理解
  5. BZOJ3451 Normal 期望、点分治、NTT
  6. 线上环境HBASE-1.2.0出现oldWALs无法自动回收情况;
  7. 遇到的Ajax相关问题
  8. WEB安全_csrf攻击
  9. 草根版创业网站学巴菲特售时间 获天使投资
  10. 吴恩达 coursera ML 第十三课总结+作业答案