当前位置: 首页 > article >正文

VTK随笔十三:QT与VTK的交互

一、基于 Ot的 VTK 应用程序

        以 VTK 读入一幅 JPG 图像,然后在 Qt 界面上使用 VTK 显示该图像为例,演示QT与VTK的交互。

1、创建QT项目QT_VTK_Demo

 

2、配置VTK库

 在CMakeLists.txt中添加如下代码:

 

 配置完成后重新打开工程加载VTK库。

3、编写代码

在mainwindow.ui中添加一个OpenGL Widget,提升为QVTKOpenGLNativeWidget ,头文件QVTKOpenGLNativeWidget.h

添加一个打开文件的菜单

mainwindow.h 

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <vtkEventQtSlotConnect.h>
#include <vtkImageViewer2.h>
#include <vtkRenderer.h>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_action_triggered(); //响应打开图像文件的槽函数
    void updateCoords(vtkObject* obj);//响应鼠标移动的消息,实时输出鼠标的当前位置

private:
    Ui::MainWindow *ui;

    vtkEventQtSlotConnect* m_Connections;
    vtkSmartPointer<vtkImageViewer2>  m_pImageViewer;
    vtkSmartPointer<vtkRenderer>  m_pRenderder;
};
#endif // MAINWINDOW_H

 mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDir>
#include <QFileDialog>
#include <vtkRenderWindow.h>
#include <vtkJPEGReader.h>
#include <vtkImageActor.h>
#include <vtkEventQtSlotConnect.h>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_pImageViewer  = vtkSmartPointer< vtkImageViewer2 >::New();
    m_pRenderder = vtkSmartPointer< vtkRenderer >::New();
    m_pRenderder->SetBackground(1.0,1.0,1.0);

    // 设置m_QVTKWidget的渲染器
    ui->renWin->renderWindow()->AddRenderer(m_pRenderder);

    m_Connections = vtkEventQtSlotConnect::New();
    m_Connections->Connect(ui->renWin->renderWindow()->GetInteractor(), vtkCommand::MouseMoveEvent,this,SLOT(updateCoords(vtkObject*)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_action_triggered()
{
    QString filter;
    filter = "JPEG image file (*.jpg *.jpeg)";

    QDir dir;
    QString fileName = QFileDialog::getOpenFileName( this, QString(tr("打开图像")), dir.absolutePath() , filter );
    if ( fileName.isEmpty() == true ) return;

    // 用vtkJPEGReader读取JPG图像
    vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
    reader->SetFileName(fileName.toUtf8().data());
    reader->Update();

    // 将reader的输出作为m_pImageViewer的输入,并设置m_pImageViewer与渲染器m_pRenderer的关联
    m_pImageViewer->SetInputData(reader->GetOutput());
    m_pImageViewer->UpdateDisplayExtent();
    m_pImageViewer->SetRenderWindow(ui->renWin->renderWindow());
    m_pImageViewer->SetRenderer(m_pRenderder);
    m_pImageViewer->SetupInteractor(ui->renWin->renderWindow()->GetInteractor());
    m_pImageViewer->SetSliceOrientationToXY(); //默认就是这个方向的
    m_pImageViewer->GetImageActor()->InterpolateOff();
    m_pRenderder->ResetCamera();
    m_pRenderder->DrawOn();
    ui->renWin->renderWindow()->Render();
}

void MainWindow::updateCoords(vtkObject* obj)
{
    // 获取交互器
    vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj);

    // 获取鼠标的当前位置
    int event_pos[2];
    iren->GetEventPosition(event_pos);

    QString str = QString("x=%1 : y=%2").arg(event_pos[0]).arg(event_pos[1]);
    ui->statusbar->showMessage(str);
}

 运行效果:

        vtkEventQtSlotConnect 类可以实现 VTK 的事件与 Qt 的槽函数的连接。示例中演示了当移动鼠标时,在窗口上显示当前鼠标的像素坐标值。

        在VTK中,可以通过两种方式来实现观察者/命令模式实现交互行为,它们分别是使用事件回调函数以及从 vtkCommand 派生出具体的子类。


1) 事件回调函数

在类 vtkObject 中,有如下函数:
  unsigned long AddObserver(unsigned long event, vtkCommand*, float priority = 0.0f);
  unsigned long AddObserver(const char* event, vtkCommand*, float priority = 0.0f);
函数的作用就是针对某个事件添加观察者到某个 VTK 对象中,当该对象发生观察者感兴趣的事件时,就会自动调用回调函数,执行相关的操作。

2)vtkCommand 子类
观察者/命令模式除了使用事件回调函数外,还可以直接从vtkCommand 类中派生出子类来实现。

        vtkRenderWindowInteractor 提供了一种独立于平台的交互机制,用来响应不同平台的鼠标、按键和时钟等消息。当渲染窗口中有事件发生时,如单击消息,vkRenderWimndowInteractor内部会调用与平台相关的子类,将该消息转换成对应平台的消息。 

 

二、选择拾取 

        选择拾取是人机交互过程的一个重要功能。

1. 点拾取

        vtkPointPicker是vtkPicker的子类,它返回选择点的ID以及坐标。它也是通过发射光线与Actor相交而拾取对象的,除了返回坐标值,Actor和Mapper,它也返回在指定容差内沿着光线,最靠近光线的那个点的ID。vtkPointPicker::GetPointId()可以获取点的ID号。
  vtkPointPicker不能单一拾取,其速度比vtkPicker慢,但比vtkCellPicker要快。 

2. 单元拾取

         vtkCellPicker是vtkPicker的子类,它返回选择单元的ID以及坐标。它也是通过发射光线与Actor相交而拾取对象的,除了返回坐标值,Actor和Mapper,它也返回在指定容差内沿着光线,最靠近光线的那个单元的ID。vtkPointPicker::GetCellId()可以获取单元的ID号。vtkCellPicker可以单一拾取,其速度是所有Picker中最慢的,当然,提供的信息也是最丰富的。

3. Actor 的拾取(vtkPropPicker)

         vtkPropPicker是基于图形硬件拾取一个Actor/Prop实例,速度比vtkCellPicker/vtkPointPicker快。这个类在世界坐标系统中判定Actor/Prop和拾取位置,对于点和单元的ID则不作判定。 

	vtkSmartPointer<vtkPropPicker>			
    m_pPropPicker{ nullptr };
	m_pPropPicker = vtkSmartPointer<vtkPropPicker>::New();

//启用拾取列表,之后的拾取仅从该列表内匹配
	m_pPropPicker->SetPickFromList(true);

//添加Actor
	vtkNew<vtkActor> actor;
	vtkNew<vtkActor> actor1;
	m_pPropPicker->AddPickList(actor);
	m_pPropPicker->AddPickList(actor1);

//拾取
	if (m_pPropPicker->Pick(displayPos[0], displayPos[1], 0, DefaultRenderer) > 0)
		{
		
		//拾取结果是Assembly
			auto pPickAssembly = m_pPropPicker->GetAssembly();
		//拾取结果是Actor
			auto pPickActor = m_pPropPicker->GetActor();
		}


http://www.kler.cn/news/290667.html

相关文章:

  • jupyter 笔记本中如何判定bash块是否执行完毕
  • CentOS7 yum 报错解决方案
  • FFmpeg源码:get_audio_frame_duration、av_get_audio_frame_duration2函数分析
  • Splasthop 安全远程访问帮助企业对抗 Cobalt Strike 载荷网络攻击
  • 鸿蒙(API 12 Beta6版)图形【NativeImage开发指导 (C/C++)】方舟2D图形服务
  • git---gitignore--忽略文件
  • 【C++】对比讲解构造函数和析构函数
  • 智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序(KNN分类器)
  • idea对项目中的文件操作没有权限
  • 海外合规|新加坡网络安全认证计划简介(三)-Cyber Trust
  • SpringBoot+Redis极简整合
  • springboot集成七牛云上传文件
  • Python画笔案例-030 实现打点之斜正方
  • MATLAB 中的对数计算
  • torch、torchvision、torchtext版本兼容问题
  • ubuntu 22.04安装NVIDIA驱动和CUDA
  • 传统CV算法——基于 SIFT 特征点检测与匹配实现全景图像拼接
  • Java实现根据某个字段对集合进行去重并手动选择被保留的对象
  • vuex 基础使用
  • 网页版修改本地数据器:重新布局,引入 highlight.js高亮显示代码
  • 鸿蒙Next-拉起支付宝的三种方式——教程
  • 【Linux】理解Linux中的软链接与硬链接
  • 传统CV算法——背景建模算法介绍
  • 架构基础 -- 打点系统之FastAPI、python、grafana、prometheus实现
  • Unity数据持久化 之 文件操作(增删查改)
  • 【赵渝强老师】大数据生态圈中的组件
  • 8 自研rgbd相机基于rk3566之sensor图像解析与AWB算法原理
  • SQL语言的规则和规范
  • 盘点成都产业园前十,寻找你的理想创业地!
  • Pencils Protocol生态新进展,即将上线 Vault 产品