若该文为原创文章,转载请注明出处
本文章博客地址:https://hpzwl.blog.csdn.net/article/details/151959697

长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…

OSG、VTK、OSGEARTH三维开发专栏(点击传送门)

上一篇:《VTK开发笔记(五):示例Cone2,熟悉观察者模式,在Qt窗口中详解复现对应的Demo
下一篇:敬请期待…


前言

  本篇详细解析Cone3.exe,实现多视口的方式,测试多视口操作。


Demo

在这里插入图片描述


多视口

概述

  VTK(Visualization Toolkit)中的多视口(Multi-Viewport)是一种在单个渲染窗口中同时显示多个独立视图的技术,广泛用于对比数据、展示不同视角或多维度分析结果。

  • 视口(Viewport):渲染窗口中用于绘制图像的矩形区域,通过标准化坐标(范围[0,1])定义位置和大小,例如(xmin, ymin, xmax, ymax)。
  • 多视口:在一个vtkRenderWindow中划分多个不重叠或部分重叠的视口,每个视口对应一个vtkRenderer(渲染器),可独立渲染不同数据、视角或样式。

核心组件及关系

  实现多视口需以下关键类,其关系如下:

  • vtkRenderWindow:顶级窗口容器,负责管理显示设备(如屏幕),可包含多个vtkRenderer。
  • vtkRenderer:每个渲染器对应一个视口,定义渲染区域(SetViewport()),并包含待渲染的vtkActor(演员)、vtkCamera(相机)等。
  • vtkActor:关联几何数据(vtkPolyData)和属性(vtkProperty),定义渲染对象的外观。
  • vtkRenderWindowInteractor:处理用户交互(如旋转、缩放),需与vtkRenderWindow绑定。

vtkRenderWindow → 包含多个 vtkRenderer(每个设置独立视口)→ 每个vtkRenderer包含 vtkActor + vtkCamera 等。


视口重叠与层级

  若视口坐标重叠,后添加到vtkRenderWindow的vtkRenderer会覆盖先添加的(可通过SetLayer()设置层级,层数高的在上)。

联动交互

  通过回调函数(vtkCommand)实现多视口相机联动,例如旋转一个视口的模型时,其他视口同步更新视角:

class CameraCallback
: public vtkCommand {
public:
static CameraCallback* New() {
return new CameraCallback;
}
void Execute(vtkObject* caller, unsigned long eventId, void* callData) override {
vtkRenderer* ren = static_cast<vtkRenderer*>
  (caller);
  vtkCamera* cam = ren->
  GetActiveCamera();
  // 同步其他渲染器的相机
  ren2->
  SetActiveCamera(cam);
  ren3->
  SetActiveCamera(cam);
  renWin->
  Render();
  }
  };
  // 绑定到渲染器的相机更新事件
  ren1->
  AddObserver(vtkCommand::ModifiedEvent, cameraCallback);

动态调整视口

  可通过vtkRenderer::SetViewport()实时修改视口大小和位置(需调用renWin->Render()刷新)。

多数据对比

  在不同视口渲染同一数据的不同处理结果(如原始图像与滤波后图像、CT 的不同断层),辅助分析。
多视口的实现步骤

步骤一:创建渲染器添加渲染和数据

  定义了2个视口:
在这里插入图片描述

在这里插入图片描述

步骤二:设置背景色和视口范围

在这里插入图片描述

步骤三:将视口设置到渲染窗口上即可

在这里插入图片描述


Demo源码

VTKWidget.cpp

void VTKWidget::test_demo5_createCone()
{
// 步骤一:创建圆锥体数据源
vtkSmartPointer<vtkConeSource> pConeSource =
  VTKManager::createConeSource(0, 0, 0, 10, 30, 10);
  // 步骤二:创建多边形映射器
  #if 0
  vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper =
    VTKManager::createPolyDataMapper(pConeSource);
    #else
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper =
      VTKManager::createPolyDataMapper(pConeSource->
      GetOutputPort());
      #endif
      // 步骤三:创建演员
      vtkSmartPointer<vtkActor> pActor =
        VTKManager::createActor(pPolyDataMapper);
        // 步骤四:创建渲染器1,2
        vtkSmartPointer<vtkRenderer> pRenderer =
          VTKManager::createRenderer(pActor,
          0.1, 0.2, 0.4,
          0, 0, 0.5, 1.0);
          vtkSmartPointer<vtkRenderer> pRenderer2 =
            VTKManager::createRenderer(pActor,
            0.2, 0.2, 0.4,
            0.5, 0, 1.0, 1.0);
            // 步骤五:渲染器添加到QVTKWidget渲染
            _pQVTKWidget->
            GetRenderWindow()->
            AddRenderer(pRenderer);
            _pQVTKWidget->
            GetRenderWindow()->
            AddRenderer(pRenderer2);
            // 步骤六:过程循环的方式实现旋转
            QElapsedTimer elapsedTimer;
            for(int index = 0; index <
            360; index++)
            {
            LOG << index;
            if(!isVisible())
            {
            continue;
            }
            // 渲染一次
            _pQVTKWidget->
            GetRenderWindow()->
            Render();
            elapsedTimer.start();
            while(elapsedTimer.elapsed() <
            10)
            {
            qApp->
            processEvents();
            }
            if(!isVisible())
            {
            continue;
            }
            // 渲染器相机绕焦点旋转
            VTKManager::rotateAzimuth(pRenderer, 1);
            // 渲染器相机绕焦点旋转
            VTKManager::rotateAzimuth(pRenderer2, 2);
            }
            }

VTKManager.cpp

vtkSmartPointer<vtkConeSource>
  VTKManager::createConeSource(double x, double y, double z, double r, int h, int n)
  {
  // 步骤一:智能指针定义
  vtkSmartPointer<vtkConeSource> pConeSource;
    // 步骤二:智能指针实例化
    pConeSource = vtkSmartPointer<vtkConeSource>
      ::New();
      // 步骤三:设置中心坐标
      pConeSource->
      SetCenter(x, y, z);
      // 步骤三:设置半径
      pConeSource->
      SetRadius(r);
      // 步骤四:设置圆锥的高度
      pConeSource->
      SetHeight(h);
      // 步骤五:设置圆锥球体的经度分辨率,即横向的切片数量(横向/水平精细度)
      pConeSource->
      SetResolution(n);
      return pConeSource;
      }
      vtkSmartPointer<vtkPolyDataMapper>
        VTKManager::createPolyDataMapper(vtkAlgorithmOutput *pAlgorithmOutput)
        {
        // 步骤一:智能指针定义
        vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper;
          // 步骤二:智能指针实例化
          pPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>
            ::New();
            // 步骤三:设置
            pPolyDataMapper->
            SetInputConnection(pAlgorithmOutput);
            return pPolyDataMapper;
            }
            vtkSmartPointer<vtkActor>
              VTKManager::createActor(vtkPolyDataMapper *pPolyDataMapper)
              {
              // 步骤一:智能指针定义
              vtkSmartPointer<vtkActor> pActor;
                // 步骤二:智能指针实例化
                pActor = vtkSmartPointer<vtkActor>
                  ::New();
                  // 步骤三:设置映射器
                  pActor->
                  SetMapper(pPolyDataMapper);
                  return pActor;
                  }
                  vtkSmartPointer<vtkRenderer>
                    VTKManager::createRenderer(vtkActor *pActor, double r, double g, double b, double x1, double y1, double x2, double y2)
                    {
                    // 步骤一:智能指针定义
                    vtkSmartPointer<vtkRenderer> pRenderer;
                      // 步骤二:智能指针实例化
                      pRenderer = vtkSmartPointer<vtkRenderer>
                        ::New();
                        // 步骤三:设置映射器
                        pRenderer->
                        AddActor(pActor);
                        // 步骤四:设置背景色
                        pRenderer->
                        SetBackground(r, g, b);
                        // 步骤五:设置视口范围(注意三维视口范围[0,1]
                        pRenderer->
                        SetViewport(x1, y1, x2, y2);
                        return pRenderer;
                        }
                        void VTKManager::rotateAzimuth(vtkRenderer *pRenderer, double angle)
                        {
                        pRenderer->
                        GetActiveCamera()->
                        Azimuth(angle);
                        }

工程模板v1.4.0

在这里插入图片描述


上一篇:《VTK开发笔记(五):示例Cone2,熟悉观察者模式,在Qt窗口中详解复现对应的Demo
下一篇:敬请期待…


本文章博客地址:https://hpzwl.blog.csdn.net/article/details/151959697

posted on 2025-09-26 13:43  lxjshuju  阅读(8)  评论(0)    收藏  举报