VTK(2)—— 双view,显示并联动操作

前言:接到一个新的需求

window单窗口程序,双view,显示并联动操作,做了两种方式进行实现,代码思路和源码如下:


(一)代码思路

一、判定谁动了?
方法1:通过当前事件的窗口位置与窗口大小中心轴进行比对
方法2:通过移动后的相机位置与两个view中相机的位置进行比对

二、如何捕获事件?
方法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()方法

(二)源码

源码1:

#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 (    (isSame(act_position, leftCamera->GetPosition()))
              &&(isSame(act_FocalPoint, leftCamera->GetFocalPoint()))
              &&(isSame(act_ViewUp,leftCamera->GetViewUp())))
        {
            rightCamera->SetPosition(act_position);
            rightCamera->SetFocalPoint(act_FocalPoint);
            rightCamera->SetViewUp(act_ViewUp);
            this->m_rightRender->ResetCameraClippingRange();
        }
        else
        {
            leftCamera->SetPosition(act_position);
            leftCamera->SetFocalPoint(act_FocalPoint);
            leftCamera->SetViewUp(act_ViewUp);
            this->m_leftRender->ResetCameraClippingRange();
        }
                               
    }
    
private:
    
    //计算获取到的相机是否为leftRender或rightRender的相机
    static bool isSame(double *value0, double *value1) {
        bool result = true;
        for (int idx = 0; idx != 3; ++idx) {
            result = result && qFuzzyCompare(value0[idx], value1[idx]);
        }
        return result;
    }
    
private:
    //此处为双view,若为多view,可设置数组,通过提供参数进行设置
    vtkRenderer     *m_leftRender;
    vtkRenderer     *m_rightRender;
    
};


int main(int, char *[])
{

    vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
    cube->SetCenter(1, 1, 1);
    cube->Update();
    
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(cube->GetOutputPort());
    
    vtkSmartPointer<vtkActor> actor1 = vtkSmartPointer<vtkActor>::New();
    actor1->SetMapper(mapper);
    actor1->GetProperty()->SetColor(.2, .3, .4);
    
    vtkSmartPointer<vtkActor> actor2 = vtkSmartPointer<vtkActor>::New();
    actor2->SetMapper(mapper);
    actor2->GetProperty()->SetColor(.4, .5, .6);

    
    double leftViewStation[4] = {0.0, 0.0, 0.5, 1.0};
    double rightViewStation[4] = {0.5, 0.0, 1.0, 1.0};
    
    vtkSmartPointer<vtkRenderer>leftRender = vtkSmartPointer<vtkRenderer>::New();
    
    leftRender->AddActor(actor1);
    leftRender->SetBackground(.6, .5, .4);
    leftRender->SetViewport(leftViewStation);

    vtkSmartPointer<vtkRenderer>rightRender = vtkSmartPointer<vtkRenderer>::New();
    rightRender->AddActor(actor2);
    rightRender->SetBackground(.2, .4, .6);
    rightRender->SetViewport(rightViewStation);
    
    
    vtkSmartPointer<vtkRenderWindow>renwindow = vtkSmartPointer<vtkRenderWindow>::New();
    renwindow->AddRenderer(leftRender);
    renwindow->AddRenderer(rightRender);
    renwindow->SetSize(600, 300);
    renwindow->Render();
    
    
    
    vtkSmartPointer<vtkRenderWindowInteractor>interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    
    vtkSmartPointer<myCallbackFunc>callback = vtkSmartPointer<myCallbackFunc>::New();
    
    callback->SetLeftRender(leftRender);
    callback->SetRightRender(rightRender);

    leftRender->GetActiveCamera()->AddObserver(vtkCommand::ModifiedEvent,callback);
    rightRender->GetActiveCamera()->AddObserver(vtkCommand::ModifiedEvent,callback);
    
    
    //用户通过控制相机对物体旋转、放大、缩小等操作。
    vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    interactor->SetInteractorStyle(style);
    
    
    renwindow->SetInteractor(interactor);
    
    interactor->Initialize();
    interactor->Start();
    
    
    return EXIT_SUCCESS;
}

源码2:

#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#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 myInteractorStyle:public vtkInteractorStyleTrackballCamera
{
public:

    static myInteractorStyle* New()
    {
        return new myInteractorStyle;
    }
    
    void    SetLeftRender(vtkRenderer *render)
    {
        this->m_leftRender = render;
    }
    
    void    SetRightRender(vtkRenderer *render)
    {
        this->m_rightRender = render;
    }
       
    void    OnMouseMove()
    {
        vtkInteractorStyleTrackballCamera::OnMouseMove();
        this->CameraSynchronous();
    }
   
    void OnLeftButtonDown()
    {
        vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
        this->CameraSynchronous();
    }

    void OnLeftButtonUp()
    {
        vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
        this->CameraSynchronous();
    }

    void OnMiddleButtonDown()
    {
        vtkInteractorStyleTrackballCamera::OnMiddleButtonDown();
        this->CameraSynchronous();
    }

    void OnMiddleButtonUp()
    {
        vtkInteractorStyleTrackballCamera::OnMiddleButtonUp();
        this->CameraSynchronous();
    }

    void OnRightButtonDown()
    {
        vtkInteractorStyleTrackballCamera::OnRightButtonDown();
        this->CameraSynchronous();
    }

    void OnRightButtonUp()
    {
        vtkInteractorStyleTrackballCamera::OnRightButtonUp();
        this->CameraSynchronous();
    }

    void OnMouseWheelForward()
    {
        vtkInteractorStyleTrackballCamera::OnMouseWheelForward();
        this->CameraSynchronous();
    }

    void OnMouseWheelBackward()
    {
        vtkInteractorStyleTrackballCamera::OnMouseWheelBackward();
        this->CameraSynchronous();
    }
    
    
    
    void Rotate()
    {
        vtkInteractorStyleTrackballCamera::Rotate();
        this->CameraSynchronous();
    }

    void Spin()
    {
        vtkInteractorStyleTrackballCamera::Spin();
        this->CameraSynchronous();
    }

    void Pan()
    {
        vtkInteractorStyleTrackballCamera::Pan();
        this->CameraSynchronous();
    }

    void Dolly()
    {
        vtkInteractorStyleTrackballCamera::Dolly();
        this->CameraSynchronous();
    }
    
    
    
    
private:
    void    CameraSynchronous()
    {
        vtkCamera *leftCamera = m_leftRender->GetActiveCamera();
        vtkCamera *rightCamera = m_rightRender->GetActiveCamera();
        
        //获取窗口大小
        int *winSize = this->GetInteractor()->GetRenderWindow()->GetSize();
        
        //获取事件窗口位置
        int eventStation[3];
        this->GetInteractor()->GetEventPosition(eventStation);
        
        if (eventStation[0] < winSize[0]/2)
        {
            rightCamera->SetPosition(leftCamera->GetPosition());
            rightCamera->SetFocalPoint(leftCamera->GetFocalPoint());
            rightCamera->SetViewUp(leftCamera->GetViewUp());
            m_rightRender->ResetCameraClippingRange();
        
        }
        else
        {
            leftCamera->SetPosition(rightCamera->GetPosition());
            leftCamera->SetViewUp(rightCamera->GetViewUp());
            leftCamera->SetFocalPoint(rightCamera->GetFocalPoint());
            m_leftRender->ResetCameraClippingRange();
                       
        }
        
        
        this->GetInteractor()->GetRenderWindow()->Render();
    }
    
private:
    vtkRenderer     *m_leftRender;
    vtkRenderer     *m_rightRender;

};


int main(int, char *[])
{

    vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
    cube->SetCenter(0, 0, 0);
    cube->SetXLength(1);
    cube->SetYLength(1);
    cube->SetZLength(1);
    cube->Update();
    
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(cube->GetOutputPort());
    
    vtkSmartPointer<vtkActor> actor1 = vtkSmartPointer<vtkActor>::New();
    actor1->SetMapper(mapper);
    actor1->GetProperty()->SetColor(.2, .3, .4);
    
    vtkSmartPointer<vtkActor> actor2 = vtkSmartPointer<vtkActor>::New();
    actor2->SetMapper(mapper);
    actor2->GetProperty()->SetColor(.4, .5, .6);

    
    double leftViewStation[4] = {0.0, 0.0, 0.5, 1.0};
    double rightViewStation[4] = {0.5, 0.0, 1.0, 1.0};
    
    vtkSmartPointer<vtkRenderer>leftRender = vtkSmartPointer<vtkRenderer>::New();
    
    leftRender->AddActor(actor1);
    leftRender->SetBackground(.6, .5, .4);
    leftRender->SetViewport(leftViewStation);

    vtkSmartPointer<vtkRenderer>rightRender = vtkSmartPointer<vtkRenderer>::New();
    rightRender->AddActor(actor2);
    rightRender->SetBackground(.2, .4, .6);
    rightRender->SetViewport(rightViewStation);
    
    
    vtkSmartPointer<vtkRenderWindow>renwindow = vtkSmartPointer<vtkRenderWindow>::New();
    renwindow->AddRenderer(leftRender);
    renwindow->AddRenderer(rightRender);
    renwindow->SetSize(600, 300);
    renwindow->Render();
    
    
    
    vtkSmartPointer<vtkRenderWindowInteractor>interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
      
    
    vtkSmartPointer<myInteractorStyle> style = vtkSmartPointer<myInteractorStyle>::New();
    style->SetLeftRender(leftRender);
    style->SetRightRender(rightRender);
    interactor->SetInteractorStyle(style);
    
    
    renwindow->SetInteractor(interactor);
    
    interactor->Initialize();
    interactor->Start();
    
    
    return EXIT_SUCCESS;
}

(其他实现方法与思路欢迎补充)

猜你喜欢

转载自blog.csdn.net/Jecklin_online/article/details/82187558