VTK开发笔记(九):示例Cone6,使用3D交互控件,在Qt窗口中详解复现对应的Demo

若该文为原创文章,转载请注明出处

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

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

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

上一篇:《VTK开发笔记(八):示例Cone5,交互器的实现方式,在Qt窗口中详解复现对应的Demo

下一篇:敬请期待...

前言

本篇详细解析Cone6.exe,了解预定义的交互器操作。

Demo

VTK的3D交互控件

概述

VTK(Visualization Toolkit)提供了丰富的3D交互控件,用于实现对 3D 场景的旋转、平移、缩放等操作,以及自定义交互逻辑。这些控件是构建交互式可视化应用的核心组件。

常用交互样式和功能

vtkInteractorStyleTrackballCamera(默认样式)

  • 功能:通过操作相机(Camera)来改变视图,适用于观察整个场景。
  • 交互方式:左键拖拽:旋转相机(场景绕视角中心旋转)。中键/滚轮:缩放(相机靠近/远离场景)。右键拖拽:平移相机(场景整体平移)。

vtkInteractorStyleTrackballActor

  • 功能:直接操作场景中的演员(Actor),而非相机,适用于编辑单个对象的位置和姿态。
  • 交互方式:左键拖拽:旋转选中的Actor。中键/滚轮:缩放选中的Actor(改变其大小)。右键拖拽:平移选中的Actor。
  • 注意:需要先通过SetCurrentActor()指定要操作的Actor。

vtkInteractorStyleJoystickCamera与vtkInteractorStyleJoystickActor

  • 功能:与Trackball 系列类似,但交互方式更接近"摇杆"逻辑------鼠标移动的方向和距离直接映射为旋转/平移的增量,而非持续拖拽。
  • 适用场景:需要更精准控制的交互(如医疗影像中的精细调整)。

vtkInteractorStyleFlight

  • 功能:模拟飞行视角,通过鼠标和键盘控制相机的移动方向和速度,适用于漫游大型场景(如地形、城市模型)。
  • 交互方式:左键拖拽:改变飞行方向。键盘W/S:加速/减速。键盘A/D:左右平移。

vtkInteractorStyleImage

  • 功能:专为2D图像(如切片数据)设计,支持切片的平移、缩放和层切换(适用于CT/MRI等医学影像的断层浏览)。
  • 交互方式:左键拖拽:平移图像。中键/ 滚轮:缩放图像。 右键拖拽:切换切片(沿 Z 轴方向)。

vtkBoxWidget交互控件

概述

创建一个可交互的立方体框(6个面、12条边、8个顶点)。通过拖拽顶点、边或面来调整立方体的大小和姿态。实时获取立方体的变换矩阵,用于控制关联对象的位置、旋转和缩放。框选场景中的部分对象进行操作。对体数据或网格模型进行立方体裁剪。交互式调整对象的包围盒(Bounding Box)。作为变换工具,控制模型的缩放、旋转和平移。

交互操作

vtkBoxWidget提供了丰富的交互操作,通过鼠标拖拽不同组件实现:

  • 拖拽顶点:调整立方体的角点位置,改变局部大小。
  • 拖拽边:沿边的方向拉伸或压缩立方体。
  • 拖拽面:沿面的法线方向移动整个面,改变立方体的整体尺寸。
  • Ctrl + 拖拽面/边/顶点:保持立方体的比例缩放。
  • Shift + 拖拽:仅平移立方体(不改变大小和方向)。
  • 右键点击:弹出上下文菜单,支持重置、对齐轴等操作(需开启默认 Representation)。

关键参数与方法

Demo实现步骤

步骤一:创建圆锥数据源

步骤二:创建多边形映射

步骤三:创建演员

步骤四:创建渲染器

步骤五:设置渲染器到渲染窗口

步骤六(关键):设置boxWidget交互器

Demo源码

VTKWidget.cpp

cpp 复制代码
void VTKWidget::test_demo8_createCone(VTKManager::INTERACTOR_STYLE interactorStyle)
{
    // 步骤一:创建圆锥体数据源
    vtkSmartPointer<vtkConeSource> pConeSource =
            VTKManager::createConeSource(0, 0, 0, 10, 30, 100);
    // 步骤二:创建多边形映射器
    vtkSmartPointer<vtkPolyDataMapper> pPolyDataMapper =
            VTKManager::createPolyDataMapper(pConeSource->GetOutputPort());
    // 步骤三:创建演员
    vtkSmartPointer<vtkActor> pActor =
            VTKManager::createActor(pPolyDataMapper, 0.5, 0.3, 0.2);
    // 步骤四:创建渲染器
    vtkSmartPointer<vtkRenderer> pRenderer =
            VTKManager::createRenderer(pActor, 0.1, 0.1, 0.1);
    // 步骤五:设置渲染器到QVTKWidget渲染窗口
    _pQVTKWidget->GetRenderWindow()->AddRenderer(pRenderer);
    // 步骤六:设置交互器
    VTKManager::createRenderWindowInteractorBoxWidget(_pQVTKWidget->GetRenderWindow(),
                                                      pActor,
                                                      interactorStyle);
}

VTKManager.h

cpp 复制代码
public:
    /** 预定义的交互器类型
     *     操作对象(摄像机 vs 演员);交互连续性(平滑 Trackball vs 步进 Joystick);场景类型(图像、地形、通用 3D 等)。
     *     实际使用时,可根据具体场景选择合适的样式,或基于 vtkInteractorStyleUser 扩展自定义交互逻辑。 */
    enum INTERACTOR_STYLE {
        // 基础交互器样式
        INTERACTOR_STYLE_TRACKBALL_CAMERA = 0x00,   //  摄像机       鼠标左键旋转、中键平移、右键 / 滚轮缩放,交互平滑连续(类似 "轨迹球" 效果),通用 3D 场景浏览,操作摄像机以改变观察视角。
        INTERACTOR_STYLE_TRACKBALL_ACTOR,           //  选中的演员    先点击选中演员,再通过鼠标左键旋转、中键平移、右键缩放该演员。仅修改单个对象的姿态,不改变摄像机位置。
        // 遥感式交互器样式
        INTERACTOR_STYLE_JOYSTICK_CAMERA,           //  摄像机       类似TrackballCamera,但交互是 "步进式"(拖动鼠标后松开才执行操作),而非连续平滑,需要精确控制交互幅度的场景。
        INTERACTOR_STYLE_JOYSTICK_ACTOR,            //  选中的演员    步进式操作单个演员,与 JoystickCamera 逻辑类似,但针对演员而非摄像机。
        // 图像与切片交互器样式
        INTERACTOR_STYLE_IMAGE,                     //  专为 2D/3D 图像(如 CT、MRI 切片)设计。交互方式:左键平移图像、右键缩放、键盘 / 下键切换切片层,默认禁用摄像机旋转(保持正交视角)。扩展功能:支持图像窗宽窗位调整(通过键盘或鼠标)。
        // 选择与区域操作样式
        INTERACTOR_STYLE_RUBBER_BAND_ZOOM,          //  核心功能:支持 "框选缩放"------ 拖动鼠标绘制矩形区域,场景自动缩放至该区域。适用场景:快速聚焦到局部区域(如病灶、细节)。
        INTERACTOR_STYLE_RUBBER_BAND_PICK,          //  支持框选区域内的对象(如演员、点集),配合拾取器(Picker)使用。
        INTERACTOR_STYLE_DRAW_POLYGON,              //  支持用鼠标绘制多边形区域,用于复杂区域的选择或裁剪。
        // 特殊场景与特殊场景样式
        INTERACTOR_STYLE_TERRAIN,                   //  专为地形数据(如高程图、地形模型)设计。交互方式:模拟 "在地形上行走",支持前后移动、左右转向,避免摄像机穿入地形。
        INTERACTOR_STYLE_FLIGHT,                    //  模拟 "飞行" 视角,通过鼠标控制飞行方向和速度,适合大规模场景(如城市、地形)浏览。
        INTERACTOR_STYLE_UNICAM,                    //  基于 "单摄像机" 模型,优化了 3D 交互的直观性,减少操作歧义。
        // 扩展与集成样式
        INTERACTOR_STYLE_USER,                      //  用于自定义交互逻辑的基类,可通过重写事件回调函数实现个性化操作。
        INTERACTOR_STYLE_SWITCH,                    //  支持动态切换多种交互器样式(如在 Trackball 和 Image 样式间切换)。
    };

VTKManager.cpp

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, double r, double g, double b)
{
    // 步骤一:智能指针定义
    vtkSmartPointer<vtkActor> pActor;
    // 步骤二:智能指针实例化
    pActor = vtkSmartPointer<vtkActor>::New();
    // 步骤三:设置映射器
    pActor->SetMapper(pPolyDataMapper);
    // 步骤四:设置颜色
    pActor->GetProperty()->SetColor(r, g, b);

    return pActor;
}

vtkSmartPointer<vtkRenderer> VTKManager::createRenderer(std::vector<vtkActor *> vectorPActor, double r, double g, double b)
{
    // 步骤一:智能指针定义
    vtkSmartPointer<vtkRenderer> pRenderer;
    // 步骤二:智能指针实例化
    pRenderer = vtkSmartPointer<vtkRenderer>::New();
    // 步骤三:设置映射器
    for(int index = 0; index < vectorPActor.size(); index++)
    {
        pRenderer->AddActor(vectorPActor.at(index));
    }
    // 步骤四:设置背景色
    pRenderer->SetBackground(r, g, b);

    return pRenderer;
}

vtkSmartPointer<vtkRenderWindowInteractor> VTKManager::createRenderWindowInteractorBoxWidget(vtkRenderWindow *pRenderWindow, vtkActor *pActor, VTKManager::INTERACTOR_STYLE interactorStyle)
{

    // 步骤一:智能指针定义、实例化
    vtkSmartPointer<vtkRenderWindowInteractor> pRenderWindowInteractor =
            vtkSmartPointer<vtkRenderWindowInteractor>::New();
    // 步骤二:智能指针定义、实例化
    vtkSmartPointer<vtkInteractorObserver> pInteractorObserver;
    // 步骤三:设置交换器
    switch (interactorStyle)
    {
    // 基础交互器样式
    case INTERACTOR_STYLE_TRACKBALL_CAMERA: //  摄像机       鼠标左键旋转、中键平移、右键 / 滚轮缩放,交互平滑连续(类似 "轨迹球" 效果),通用 3D 场景浏览,操作摄像机以改变观察视角。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
        break;
    case INTERACTOR_STYLE_TRACKBALL_ACTOR:  //  选中的演员    先点击选中演员,再通过鼠标左键旋转、中键平移、右键缩放该演员。仅修改单个对象的姿态,不改变摄像机位置。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleTrackballActor>::New();
        break;
    // 遥感式交互器样式
    case INTERACTOR_STYLE_JOYSTICK_CAMERA:  //  摄像机       类似TrackballCamera,但交互是 "步进式"(拖动鼠标后松开才执行操作),而非连续平滑,需要精确控制交互幅度的场景。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleJoystickCamera>::New();
        break;
    case INTERACTOR_STYLE_JOYSTICK_ACTOR:   //  选中的演员    步进式操作单个演员,与 JoystickCamera 逻辑类似,但针对演员而非摄像机。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleJoystickActor>::New();
        break;
    // 图像与切片交互器样式
    case INTERACTOR_STYLE_IMAGE:            //  专为 2D/3D 图像(如 CT、MRI 切片)设计。交互方式:左键平移图像、右键缩放、键盘 / 下键切换切片层,默认禁用摄像机旋转(保持正交视角)。扩展功能:支持图像窗宽窗位调整(通过键盘或鼠标)。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleImage>::New();
        break;
    // 选择与区域操作样式
    case INTERACTOR_STYLE_RUBBER_BAND_ZOOM: //  核心功能:支持 "框选缩放"------ 拖动鼠标绘制矩形区域,场景自动缩放至该区域。适用场景:快速聚焦到局部区域(如病灶、细节)。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleRubberBandZoom>::New();
        break;
    case INTERACTOR_STYLE_RUBBER_BAND_PICK: //  支持框选区域内的对象(如演员、点集),配合拾取器(Picker)使用。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleRubberBandPick>::New();
        break;
    case INTERACTOR_STYLE_DRAW_POLYGON:     //  支持用鼠标绘制多边形区域,用于复杂区域的选择或裁剪。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleDrawPolygon>::New();
        break;
    // 特殊场景与特殊场景样式
    case INTERACTOR_STYLE_TERRAIN:          //  专为地形数据(如高程图、地形模型)设计。交互方式:模拟 "在地形上行走",支持前后移动、左右转向,避免摄像机穿入地形。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleTerrain>::New();
        break;
    case INTERACTOR_STYLE_FLIGHT:           //  模拟 "飞行" 视角,通过鼠标控制飞行方向和速度,适合大规模场景(如城市、地形)浏览。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleFlight>::New();
        break;
    case INTERACTOR_STYLE_UNICAM:           //  基于 "单摄像机" 模型,优化了 3D 交互的直观性,减少操作歧义。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleUnicam>::New();
        break;
    // 扩展与集成样式
    case INTERACTOR_STYLE_USER:              //  用于自定义交互逻辑的基类,可通过重写事件回调函数实现个性化操作。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleUser>::New();
        break;
    case INTERACTOR_STYLE_SWITCH:           //  支持动态切换多种交互器样式(如在 Trackball 和 Image 样式间切换)。
        pInteractorObserver = vtkSmartPointer<vtkInteractorStyleSwitch>::New();
        break;
    default:
        break;
    }
    pRenderWindowInteractor->SetInteractorStyle(pInteractorObserver);
    // 步骤四:设置处理的渲染窗口
    pRenderWindowInteractor->SetRenderWindow(pRenderWindow);
    // 步骤五:智能指针定义、实例化
    vtkSmartPointer<vtkBoxWidget> pBoxWidget =
            vtkSmartPointer<vtkBoxWidget>::New();
    // 步骤六:设置boxWidget的交互器
    pBoxWidget->SetInteractor(pRenderWindowInteractor);
    // 步骤七:设置位置因子,位置因子控制小部件相对于小部件输入边界框的初始大小。
    pBoxWidget->SetPlaceFactor(1.25);
    // 步骤八:box添加控制的演员
    pBoxWidget->SetProp3D(pActor);
    // 步骤九:
    pBoxWidget->PlaceWidget();
    // 步骤十:定义观察者回调处理类、智能指针定义、实例化
    class vtkMyCallback : public vtkCommand
    {
    public:
        static vtkMyCallback *New() {
            return new vtkMyCallback;
        }
        void Execute(vtkObject *caller, unsigned long, void*) override
        {
            // 变换矩阵
            vtkTransform *pTransform = vtkTransform::New();
            // 获取被观察(这里是对BoxWidget添加观察者,所以BoxWidget是被观察者)
            vtkBoxWidget *pBoxWidget = reinterpret_cast<vtkBoxWidget*>(caller);
            // 获取被观察者的举证
            pBoxWidget->GetTransform(pTransform);
            // 讲BoxWidget下的3D模型都设置为其变换的矩阵
            pBoxWidget->GetProp3D()->SetUserTransform(pTransform);
            // 删除
            pTransform->Delete();
        }
    };
    vtkSmartPointer<vtkMyCallback> pMyCallback = vtkSmartPointer<vtkMyCallback>::New();
    // 步骤十一:添加时间观察回调
    pBoxWidget->AddObserver(vtkCommand::InteractionEvent, pMyCallback);
    // 步骤十二:启用BoxWidget
    pBoxWidget->On();
    // 步骤十三:初始化交互器
    pRenderWindowInteractor->Initialize();
    // 步骤十四:开始进入交互器时间循环
    pRenderWindowInteractor->Start();

    return pRenderWindowInteractor;
}

工程模板v1.7.0

上一篇:《VTK开发笔记(八):示例Cone5,交互器的实现方式,在Qt窗口中详解复现对应的Demo

下一篇:敬请期待...

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

相关推荐
大势智慧2 小时前
DasViewer 4.0 重磅发布,全面增强3DGS处理能力
3d·渲染·应用·效率·实景三维·高斯·成果
YAY_tyy2 小时前
基于矩形区域的相机自动定位与飞行控制实现
前端·javascript·3d·cesium
思茂信息3 小时前
CST软件对Customer Success OPPO手机电源适配器EMC仿真
开发语言·嵌入式硬件·matlab·3d·智能手机·cst
m***11903 小时前
开源模型应用落地-FastAPI-助力模型交互-进阶篇-中间件(四)
开源·交互·fastapi
GISer_Jing14 小时前
SSE Conf大会分享支付宝xUI引擎:AI时代的多模态交互革命
前端·人工智能·交互
reddingtons17 小时前
Illustrator 3D Mockup:零建模,矢量包装一键“上架”实拍
人工智能·ui·3d·aigc·illustrator·设计师·平面设计
远瞻。1 天前
【环境配置】【bug调试】pytorch3d 安装
人工智能·pytorch·3d·调试
老黄编程1 天前
点云SIFT3D特征点云原理、算法描述及参数详细说明
算法·3d·sift3d
BoBoZz191 天前
OrientedArrow 在两个随机生成的点之间绘制一根带箭头的线,以可视化一个向量
python·vtk·图形渲染·图形处理