前言:接到一个新的需求
window单窗口程序,双view,显示并联动操作,做了两种方式进行实现,代码思路和源码如下:
(一)代码思路
一、判定谁动了?
方法1:通过当前事件的窗口位置与窗口大小中心轴进行比对
方法2:通过移动后的相机位置与两个view中相机的位置进行比对
方法3:获取当前renderer, 与两个renderer 做对比
二、如何捕获事件?
方法1:继承自vtkCommand重写回调
Step1: 定义回调函数,继承自vtkCommand
Step2: 设置回调函数
Step3: 为两个view的相机添加观察者,通过AddObserver(vtkCommand::ModifiedEvent,callback)
(其中ModifiedEvent可以接收任意发生事件,
当有事件产生时,interactor底层会调用ModifiedEvent事件,callback为step1自定义的回调函数)
方法2:vtkInteractorStyleTrackballCamera 重写响应事件
Step1: 自定义交互类型,继承自vtkInteractorStyleTrackballCamera
Step2: 重写OnMouseMove()等方法
三、如何根据一个view变化设置另一个view?
方法1:将要设置的view中的相机的状态设置为变化的相机状态
(因为在vtk中图像变化默认采用的是相机移动方式,在此先不讨论actor变化方式)
(注:vtk中的相机,主要由三个因素决定:1.焦点 2.相机位置 3.向上方向)(另外也可以通过直接获取相机来设置想让变化的相机状态)
Step1: 获取改变的相机的状态,通过GetPosition(), GetFocalPoint(), GetViewUp() 进行获得
Step2: 设置要改变的相机的状态,通过SetPosition(), SetFocalPoint(), SetViewUp() 进行设置
Step3: 使用vtkRenderer的ResetCameraClippingRange()方法重置图像的法向量
Step4: 如果信号没有进行同步,需要手动调用vtkRendererWindow的Render()方法
方法2:创建一个相机对象,给左右两个renderer添加同一个相机对象
方法3:通过获取当前相机,将两个renderer的相机设置为当前相机
四、同类型问题思考?
一个view中,两个actor,根据鼠标指向不同,可挪动不同的物体。(这个实现起来相对简单一点,vtk有现成的函数)
方法:使用 vtkInteractorStyleTrackballActor 的互动模式即可实现
(二)Demo源码
第1种实现方式:
方法说明:
- 实现方式:继承自vtkCommand重写回调
- 相机设置:两个 renderer 公用一个相机(注:当不使用一个 camera 设置两个 renderer 的时候,如果viewsation不是对称的 会出现互动最开始两个相机相对物体的位置进行同步)
- 联动函数:通过判断当前相机 与左右两个相机比对判定哪边动了,包含两种判断方法
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkCallbackCommand.h>
#include <vtkTransform.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCamera.h>
#include <QDateTime>
class myCallbackFunc:public vtkCommand
{
public:
static myCallbackFunc *New()
{
return new myCallbackFunc;
}
void SetLeftRender(vtkRenderer *leftRender)
{
this->m_leftRender = leftRender;
}
void SetRightRender(vtkRenderer *rightRender)
{
this->m_rightRender = rightRender;
}
virtual void Execute(vtkObject *caller, unsigned long eventId, void* callData)
{
vtkCamera *camera = reinterpret_cast<vtkCamera*>(caller);
vtkCamera *leftCamera = m_leftRender->GetActiveCamera();
vtkCamera *rightCamera = m_rightRender->GetActiveCamera();
double *act_position = camera->GetPosition();
double *act_FocalPoint = camera->GetFocalPoint();
double *act_ViewUp = camera->GetViewUp();
//方法一:指针判断
if (leftCamera == camera)
{
if (rightCamera->GetPosition() != act_position)
{
rightCamera->SetPosition(act_position);
}
if (rightCamera->GetViewUp() != act_ViewUp)
{
rightCamera->SetFocalPoint(act_FocalPoint);
}
if (rightCamera->GetViewUp() != act_ViewUp)
{
rightCamera->SetViewUp(act_ViewUp);
}
}
else if (rightCamera == camera)
{
if (leftCamera->GetPosition() != act_position)
{
leftCamera->SetPosition(act_position);
}
if (leftCamera->GetViewUp() != ac