跳转至

自定义交互

官方文档

自定义交互并不神秘,只是事件驱动下的矩阵更新。

VTK 交互的本质是:相机矩阵 + Actor 变换矩阵

所有复杂行为,最后都会落到这两件事。

1 常见的 vtk 交互

vtkInteractorStyle 是所有交互风格的基类。本身实现了操纵杆风格的默认行为,同时定义大量可覆盖的交互事件(鼠标按键、移动、滚轮、键盘等)。

其提供了一个 “事件 → 交互行为” 的框架,但并不直接实现丰富的默认行为。

1.1 基础相机/对象控制

类名 主要用途
vtkInteractorStyleTrackballCamera 标准 Trackball 式相机控制:旋转/缩放/平移视图。最常用。
vtkInteractorStyleTrackballActor 使用鼠标直接旋转/平移/缩放所拾取的 Actor,而不是相机。
vtkInteractorStyleJoystickCamera 操纵杆式相机控制(运动量与指针位置相关),类似默认 Behavior。
vtkInteractorStyleJoystickActor 操纵杆式控制 Actor,而不是相机。

1.2 2D图像交互

类名 主要用途
vtkInteractorStyleImage 用于 2D 图像渲染的交互(窗位/窗宽、平移、缩放),常用于医学图像显示。

1.3 选择 / 绘制 / 多触控

类名 主要用途
vtkInteractorStyleRubberBand2D/3D 用来绘制橡皮带选择框(2D/3D),用于框选场景中的元素。
vtkInteractorStyleRubberBandPick 框选并触发 Pick 事件。
vtkInteractorStyleAreaSelectHover 在某个区域悬停高亮(用于交互式图表等)。
vtkInteractorStyleDrawPolygon 允许用户绘制多边形选择区域。
vtkInteractorStyleTreeMapHover 用于 treemap 等图形的悬停事件交互。

1.4 图表 / 平行坐标

类名 主要用途
vtkParallelCoordinatesInteractorStyle 平行坐标图的交互
vtkGeoInteractorStyle 地理地图交互风格
vtkFlightInteractorStyle 航迹式飞行控制

1.5 特殊控制

类名 主要用途
vtkInteractorStyleSwitch 允许在多个风格间切换
vtkInteractorStyleUser 一个可配置风格,可在不子类化的情况下调整交互
vtkInteractorStyleMultiTouchCamera 多点触控交互
vtkInteractorStyle3D 针对 3D 输入设备和 6 自由度控制 (VR)

2 自定义交互 Demo

标准风格能解决“浏览”,解决不了“产品交互”。实际项目里常见需求:

  • 只允许选中,不允许移动
  • 相机和模型混合控制
  • 指定旋转中心
  • 鼠标点击点作为旋转中心
  • UI 状态驱动交互模式切换
  • ......

这类需求必须自定义。

源码

请随便吐槽这个 main 这么长,作为 Demo :可读性 > 结构优雅

Qt → VTK Widget → Renderer → Models → Style → UI 绑定

为了展示清楚 VTK 初始化流程、Renderer / Actor / Interactor 关系、不同 InteractorStyle 怎么切换、UI 和 VTK 是如何联动的

    /*
     * vtkInteractorStyleSceneCamera 相机模式
     *      vtk默认,直接交互相机,旋转、平移、缩放等都是直接作用于相机的
     * vtkInteractorStyleSelectionOnly 选择模式
     *      只选择模型,无交互,UI 和渲染双向绑定
     * vtkInteractorStyleSingleModel 模型模式
     *      vtk默认,直接交互指定模型
     * vtkInteractorStyleHybrid 模型+场景混合模式
     *      组合了相机模式和模型模式,根据鼠标位置判断交互整体还是单个模型
     * vtkInteractorStyleFixedCenter 指定中心模式
     *      指定一个固定的中心点,所有交互都以这个点为中心进行旋转、缩放等操作
     * vtkInteractorStylePickCenter 鼠标点中心模式
     *      根据鼠标点击的位置设置交互中心点,交互以这个点为中心进行旋转、缩放等操作
     */