【VTK】基于读取出来的 STL 模型,当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点
知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。
文章目录
- `class PointPickedSignal : public QObject`
- `class MouseInteractorCommand : public vtkCommand`
- `void A::on_pushButtonSelected_clicked()`
- `void A::onPointPicked(double* pos)`
- `A.h`
- `A.cpp`
- Ref.
基于读取出来的 STL 模型,实现当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点。
详细流程为:点击 Select
按钮,鼠标具备选择的功能。当按下 Select Done
鼠标删除掉此功能。
主要是通过两个类和一个函数来实现的:
class PointPickedSignal : public QObject
class MouseInteractorCommand : public vtkCommand
void A::on_pushButtonSelected_clicked()
void A::onPointPicked(double* pos)
下边依次分析。
class PointPickedSignal : public QObject
class PointPickedSignal : public QObject
{Q_OBJECT
public:PointPickedSignal(QObject* parent = nullptr) : QObject(parent) {}signals:void pointPicked(double* pos);
};
这个类继承自 QObject
类,用于实现一个名为 pointPicked
的 Qt 信号,当一个点被选中时发出该信号。这个信号将被用于通知其他对象选中的点的坐标。
class MouseInteractorCommand : public vtkCommand
class MouseInteractorCommand : public vtkCommand
{
public:vtkTypeMacro(MouseInteractorCommand, vtkCommand);static MouseInteractorCommand* New(){return new MouseInteractorCommand;}virtual void Execute(vtkObject* caller, unsigned long eventId, void* vtkNotUsed(callData)){vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::SafeDownCast(caller);int* clickPos = interactor->GetEventPosition();vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();picker->SetTolerance(0.0005);if (picker->Pick(clickPos[0], clickPos[1], 0, interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer())){double* pos = picker->GetPickPosition();memcpy(pickedPoint, pos, sizeof(double) * 3);emit signal->pointPicked(pickedPoint);}}double pickedPoint[3];PointPickedSignal* signal; // this will emit the pointPicked signal when a point is picked
};
这个类继承自 vtkCommand
类,其功能是监听鼠标左键的点击事件。当用户点击鼠标左键时,会触发 Execute
方法。在这个方法中,代码首先从事件的发起者中获取交互器,并从交互器中获取点击的位置。然后,它创建一个 vtkCellPicker
对象并尝试拾取点击位置的点。如果成功拾取了一个点,它将获取该点的坐标,并使用 memcpy
将这些坐标复制到 pickedPoint
数组中。最后,它发出 pointPicked
信号,将选中的点的坐标作为参数。
void A::on_pushButtonSelected_clicked()
void A::on_pushButtonSelected_clicked() {ui.textBrowser->insertPlainText("Button Clicked");PointPickedSignal* signal = new PointPickedSignal(this);vtkSmartPointer<MouseInteractorCommand> command = vtkSmartPointer<MouseInteractorCommand>::New();command->signal = signal;ui.qvtkWidget->interactor()->AddObserver(vtkCommand::LeftButtonPressEvent, command);QEventLoop loop;connect(signal, &PointPickedSignal::pointPicked, this, &A::onPointPicked);connect(signal, &PointPickedSignal::pointPicked, &loop, &QEventLoop::quit);loop.exec();onPointPicked(command->pickedPoint);
}
这个方法首先创建一个 PointPickedSignal
对象和一个 MouseInteractorCommand
对象。然后,它将 PointPickedSignal
对象赋值给 MouseInteractorCommand
对象的 signal 成员,然后将这个 MouseInteractorCommand
对象添加为 QVTKWidget
对象的交互器的观察者,这样当交互器收到左键按下事件时,就会执行 MouseInteractorCommand
对象的 Execute
方法。
然后,这个方法创建一个 QEventLoop
对象并开始执行事件循环。在事件循环中,当 pointPicked
信号被发出时,它将调用 A::onPointPicked()
方法,并结束事件循环。
void A::onPointPicked(double* pos)
void A::onPointPicked(double* pos) {ui.textBrowser->insertPlainText(QString("Point picked: %1 %2 %3\n").arg(pos[0]).arg(pos[1]).arg(pos[2]));ui.textBrowser->moveCursor(QTextCursor::End);mandibleActor->SetOrigin(pos);
}
当这个方法被调用时,它将在文本浏览器中显示选中的点的坐标,并将这个点设置为模型的旋转原点。
通过这种方式,当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点。
完整版代码如下:
A.h
// A.h
#pragma once#include <QtWidgets/QMainWindow>
#include "ui_A.h"#include <vtkSmartPointer.h>
#include <vtkSTLReader.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkRenderWindowInteractor.h>#include <vtkCellPicker.h>
#include <vtkCommand.h>
#include <vtkObjectFactory.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkRendererCollection.h>
#include <vtkPropPicker.h>
#include <QObject>#include <qtimer.h>class A : public QMainWindow
{Q_OBJECTpublic:A(QWidget* parent = nullptr);~A();private slots:void on_pushButtonSelect_clicked();void on_pushButtonSelDone_clicked();void onPointPicked(double* pos);void rotate();private:Ui::AClass ui;void initVTK();vtkSmartPointer<vtkActor> actor;vtkSmartPointer<vtkRenderer> renderer;vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow;QTimer* timer;
};class PointPickedSignal : public QObject
{Q_OBJECT
public:PointPickedSignal(QObject* parent = nullptr) : QObject(parent) {}signals:void pointPicked(double* pos);
};class MouseInteractorCommand : public vtkCommand
{
public:vtkTypeMacro(MouseInteractorCommand, vtkCommand);static MouseInteractorCommand* New(){return new MouseInteractorCommand;}virtual void Execute(vtkObject* caller, unsigned long eventId, void* vtkNotUsed(callData)){vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::SafeDownCast(caller);int* clickPos = interactor->GetEventPosition();vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();picker->SetTolerance(0.0005);if (picker->Pick(clickPos[0], clickPos[1], 0, interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer())){double* pos = picker->GetPickPosition();memcpy(pickedPoint, pos, sizeof(double) * 3);emit signal->pointPicked(pickedPoint);}}double pickedPoint[3];PointPickedSignal* signal; // this will emit the pointPicked signal when a point is picked
};
A.cpp
// A.cpp
#include "A.h"A::A(QWidget* parent): QMainWindow(parent)
{ui.setupUi(this);// 配置 VTK 的初始设置initVTK();// 定时器,50ms 更新触发一次 checkPositionChange()timer = new QTimer(this);connect(timer, SIGNAL(timeout()), this, SLOT(rotate()));timer->start(100);
}A::~A()
{
}void A::initVTK()
{// 读取 STL 文件vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();reader->SetFileName("skull_50.stl"); // 请替换为你的 STL 文件路径reader->Update();// 创建映射器和演员vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();mapper->SetInputConnection(reader->GetOutputPort());actor = vtkSmartPointer<vtkActor>::New();actor->SetMapper(mapper);// 创建渲染器renderer = vtkSmartPointer<vtkRenderer>::New();// 添加演员到渲染器renderer->AddActor(actor);// 创建渲染窗口和渲染窗口交互器renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();renderWindow->AddRenderer(renderer);// 添加到 qvtkWidget 控件中显示ui.qvtkWidget->setRenderWindow(renderWindow);}void A::on_pushButtonSelect_clicked() {ui.textBrowser->insertPlainText("Select button clicked!\n");PointPickedSignal* signal = new PointPickedSignal(this);vtkSmartPointer<MouseInteractorCommand> command = vtkSmartPointer<MouseInteractorCommand>::New();command->signal = signal;ui.qvtkWidget->interactor()->AddObserver(vtkCommand::LeftButtonPressEvent, command);QEventLoop loop;connect(signal, &PointPickedSignal::pointPicked, this, &A::onPointPicked);connect(signal, &PointPickedSignal::pointPicked, &loop, &QEventLoop::quit);loop.exec();onPointPicked(command->pickedPoint);
}void A::onPointPicked(double* pos) {ui.textBrowser->insertPlainText(QString("Point picked: %1 %2 %3\n").arg(pos[0]).arg(pos[1]).arg(pos[2]));ui.textBrowser->moveCursor(QTextCursor::End);actor->SetOrigin(pos);
}void A::on_pushButtonSelDone_clicked() {ui.textBrowser->insertPlainText("Selection done, restore the default interactor style.\n");// 移除左键按下事件的观察者ui.qvtkWidget->interactor()->RemoveObservers(vtkCommand::LeftButtonPressEvent);// 恢复默认的交互器样式。vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();ui.qvtkWidget->interactor()->SetInteractorStyle(style);
}void A::rotate()
{actor->RotateX(5);renderWindow->Render();
}
Ref.
- 骷髅3D打印3D模型
相关文章:

【VTK】基于读取出来的 STL 模型,当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点
知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 文章目录 class PointPickedSignal : public QObjectclass MouseInteractorCommand : public vtkCommandvoid A::on_pushButtonSelected_clicked()void A::on…...

【第一阶段】kotlin的when表达式
1.Java 的if /when是语句 kotlin的if/when是表达式,表达式是有返回值的 java中void是个关键字,Unit在kotlin中是个类 2.当使用when语句的时候必须有一个不满足的值即else: fun main() {var week:Int5val info when(week){1->"今天是星期一"…...
C#中Convert.ToInt32() 和 int.Parse()的区别
都是用于将字符串转换为整数类型(int)的方法,但它们在处理转换过程中有一些区别: 1. 错误处理方式不同: - Convert.ToInt32():如果字符串无法成功转换为整数类型,Convert.ToInt32()…...

安全学习DAY14_JS信息打点
信息打点——前端JS框架 文章目录 信息打点——前端JS框架小节概述-思维导图JS安全概述什么是JS渗透测试?前后端差异JS安全问题流行的Js框架如何判定JS开发应用? 测试方法(JS文件的获取以及分析方法1、手工搜索分析2、半自动Burp分析插件介绍…...

windows下配置vue开发环境
安装nodejs,配置npm 1.下载安装包:下载地址:https://nodejs.org/en/download 2.安装node:下载完成后进行安装,记住安装的文件夹。本人安装路径为 D:\Program Files\nodejs 3.配置环境变量: ①安装完成后…...
AndroidTV 获取焦点View放大效果实现方式
需求 电视开发最常见的就是view获焦后要有放大效果,让用户明显看到。这里总结两个实现方法,以后遇到其他的再补充。 方式一:ViewCompat.animate(view) 1、注册焦点变化监听 mBtnFocus1.setOnFocusChangeListener(this);2、有焦点变化的时…...

访问者模式——操作复杂对象结构
1、简介 1.1、概述 访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分。这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。访问者模式使得用户可以在不修改现有系统的情况下扩展系…...

指针经典笔试题强训(附图详解)
目录 笔试题1: 解析: 运行结果: 笔试题2 解析: 运行结果: 笔试题3 解析: 运行结果: 笔试题4 解析: 运行结果: 笔试题5 解析: 运行结果:…...

Python:列表(list)与元组(tuple)
列表与元组 列表:list元组:tuple 比较直观的区分:列表是中括号"[ ]“,元组是小括号”( )"元组可以看成列表的只读形式 # 列表 list1 [hello, world] list2 [1, 2, 3, 4, 5] list3 ["a", "b", &…...
常见的相似性度量方法
有如下几种计算相似性方法: 点积相似度 X ⋅ Y ∣ X ∣ ∣ Y ∣ c o s θ ∑ i 1 n x i ∗ y i \begin{aligned} X \cdot Y & |X||Y|cos\theta \\ & \sum_{i1}^n x_i * y_i \end{aligned} X⋅Y∣X∣∣Y∣cosθi1∑nxi∗yi 向量内积的结果是没…...
Day06-JS高级编程
Day01-JS高级编程 一 变量和常量 1 概念 在程序中,变量是值可以改变的量,常量是值不可以改变的量 在ES6以前变量的创建使用var关键字 (可以创建多个同名变量) 从ES6开始变量的创建推荐使用let关键字 (不可以创建多个同名变量) 从ES6开始常量的创建使用const关键 (不可以创建…...

针对高可靠性和高性能优化的1200V硅碳化物沟道MOSFET
目录 标题:1200V SiC Trench-MOSFET Optimized for High Reliability and High Performance摘要信息解释研究了什么文章创新点文章的研究方法文章的结论 标题:1200V SiC Trench-MOSFET Optimized for High Reliability and High Performance 摘要 本文详…...

开发框架软件公司:与之携手,共同开启办公流程化之路!
在快节奏的社会里,如何提高企业的办公效率?如何让各部门之间的协作关系更为顺畅?如何把企业内部的数据真正利用起来,成为高层做出经营决策的重要依据?其实,要做到这些,与开发框架软件公司联手合…...

openCV C++环境配置
文章目录 一、openCV 安装二、新建项目三、配置环境变量四、测试使用 编译器:vs2017 OpenCV:4.5.4 一、openCV 安装 将openCV安装到一个路径下,我安装到了D盘根目录下 二、新建项目 在vs2017新建控制台空项目,打开项目属性 在VC目录 -> 包含目录下…...

8.3 作业 c高级
1.递归实现,输入一个数,输出这个数的每一位: #include<myhead.h>void print_digit(int num) {if(num<10){printf("%d",num);puts("");}else{print_digit(num/10); //递归打印除最后一位外的数printf("%…...

django实现部门表的增删改查界面
1、前期准备 部署好mysql数据库,创建好unicom数据库下载好bootstap的插件下载好jquery的插件下载好mysqlclient-1.4.6-cp36-cp36m-win_amd64.whl的安装包,根据python的版本下载 2、创建项目 在pycharm中创建项目 在pycharm的终端创建虚拟环境 py -m v…...

Tomcat的介绍和安装配置、eclipse中动态web项目的创建和运行、使用IDEA创建web项目并运行
一、Tomcat的介绍和安装配置 安装tomcat: 环境变量的配置: 配置之后重启cmd,执行startup命令,启动tomcat 在localhost:8080,能进入tomcat主界面,说明配置成功 二、eclipse中动态web项目的创建和运行 tomca…...

idea操作——已经push到远程的代码回滚(不保留本地更改)
1. git: 2. 找到相应分支--->找到要回滚的代码的位置----->右键,然后选择如图的选项: 3.下图的选项选择hard,然后选择reset 4.操作完成后等一会,待同步结束后push代码到远程,选择force push.…...

无涯教程-Lua - 垃圾回收
Lua使用自动内存管理,该管理使用基于Lua内置的某些算法的垃圾回收。 垃圾收集器暂停 垃圾收集器暂停用于控制垃圾收集器之前需要等待多长时间; Lua的自动内存管理再次调用它。值小于100意味着Lua将不等待下一个周期。同样,此值的较高值将导…...

DP(各种模型)
数字三角形模型 摘花生 Hello Kitty想摘点花生送给她喜欢的米老鼠。 她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。 地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...