【FastCAE源码阅读5】使用VTK实现鼠标拾取对象并高亮

鼠标拾取对象是很多软件的基本功能。FastCAE的拾取比较简单,是通过VTK实现的。

对几何而言,拾取类型切换在工具栏上,单击后再来单击视图区对象进行拾取,拾取后的对象会高亮显示。效果如下图:
在这里插入图片描述

一、拾取对象

拾取对象是在PropPickerInteractionStyle类实现的,该类是vtkInteractorStyleRubberBandPick的子类,重写原来的鼠标处理函数。当鼠标左键按下,会触发以下代码:

void PropPickerInteractionStyle::clickSelectGeometry(bool preSelect)
{
	int *clickPos = this->GetInteractor()->GetEventPosition(); // 获取鼠标点击位置
	int success = -1, index = -1;
	vtkActor *actor = nullptr;
	if (_selectModel == GeometryPoint || _selectModel == GeometryWinPoint) // 几何点
	{
		vtkSmartPointer<vtkPointPicker> picker = vtkSmartPointer<vtkPointPicker>::New();
		success = picker->Pick(clickPos[0], clickPos[1], 0, this->GetDefaultRenderer());
		if (0 != success)
		{
			index = picker->GetPointId(); // 点的id
			actor = picker->GetActor(); // 点对应的Actor
		}
	}
	else
	{
		vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();
		if (_selectModel == GeometryCurve || _selectModel == GeometryWinCurve)
			picker->SetTolerance(0.0025);
		success = picker->Pick(clickPos[0], clickPos[1], 0, this->GetDefaultRenderer());
		if (0 != success)
		{
			index = picker->GetCellId(); // cell的id
			actor = picker->GetActor(); // 对应的actor
		}
	}
	emit selectGeometry(preSelect, actor, index);
}

这段代码就是鼠标拾取对象的核心逻辑。其实现是借助了VTK提供的vtkPointPicker、vtkCellPicker。其中当拾取模式是点的时候,使用vtkPointPicker,如果拾取成功返回点的id及对应的Actor(一个Actor可能包含多个点)。当拾取模式是线、面、体的时候,使用vtkCellPicker,成功则返回对应cell id及Actor(一个Actor可能包含多个cell)。注意当拾取线的时候,需要提高拾取Tolerance,不然线很难拾取到。

另外要注意的是,当拾取线的时候,面Actor是拾取不到的,同样当拾取面的时候,线Actor也是拾取不到。这是通过在用户切换选择模式的时候,设置面或边Actor是否可以拾取实现的。核心代码在GeometryViewProvider类中,如下:

void GeometryViewProvider::setGeoSelectMode(int m)
{
	_viewData->updateGraphOption();
	ModuleBase::SelectModel selectType = (ModuleBase::SelectModel)m;
	QList<GeoViewObj> viewObjs = _geoViewHash.values();
	vtkActor *actor = nullptr;
	for (GeoViewObj vobj : viewObjs)
	{
		actor = vobj._faceObj.first;
		if (actor != nullptr)
			actor->SetPickable(false);
		actor = vobj._edgeObj.first;
		if (actor != nullptr)
			actor->SetPickable(false);
		actor = vobj._pointObj.first;
		if (actor != nullptr)
			actor->SetPickable(false);
		switch (selectType)
		{
		case ModuleBase::GeometryBody:
		case ModuleBase::GeometrySurface:
		case ModuleBase::GeometryWinBody:
		case ModuleBase::GeometryWinSurface:
			actor = vobj._faceObj.first;
			if (actor != nullptr)
				actor->SetPickable(true);
			break;
		case ModuleBase::GeometryWinCurve:
		case ModuleBase::GeometryCurve:
			actor = vobj._edgeObj.first;
			if (actor != nullptr)
				actor->SetPickable(true);
			break;
		case ModuleBase::GeometryWinPoint:
		case ModuleBase::GeometryPoint:
			actor = vobj._pointObj.first;
			if (actor != nullptr)
				actor->SetPickable(true);
			break;
		default:
			break;
		}
	}
}

这个代码相对比较简单,不再分析。

二、从信号到槽函数

拾取对象之后,会发出emit selectGeometry信号,参数中带有Actor及cell或点的id。这个信号是QT框架提供的编程机制。其对应的槽函数在如下图中能找到:
在这里插入图片描述

三、高亮拾取对象

高亮拾取对象处理过程代码如下:

void GeometryViewProvider::selectGeometry(bool pre, vtkActor *ac, int index)
{
	if (ac == nullptr || index < 0) // 无效拾取
	{
		_viewData->preHighLight(nullptr);
		_preWindow->reRender();
		return;
	}
	ModuleBase::SelectModel selectMod = _preWindow->getSelectModel(); // 选择模式
	vtkDataSet *dataSet = ac->GetMapper()->GetInputAsDataSet(); // 获取Actor的多边形数据集vtkPolyData
	vtkPolyData *poly = vtkPolyData::SafeDownCast(dataSet);
	if (poly == nullptr)
		return;
	GeometryViewObject *vobj = nullptr;
	switch (selectMod)
	{
	case ModuleBase::GeometryWinBody:
	case ModuleBase::GeometryBody:
		vobj = _viewData->getSolidViewObj(poly, index);
		break;
	case ModuleBase::GeometryWinSurface:
	case ModuleBase::GeometrySurface:
		vobj = _viewData->getFaceViewObj(poly, index); // 输入多边形数据+cell id
		break;
	case ModuleBase::GeometryWinCurve:
	case ModuleBase::GeometryCurve:
		vobj = _viewData->getEdgeViewObj(poly, index);
		break;
	case ModuleBase::GeometryWinPoint:
	case ModuleBase::GeometryPoint:
		vobj = _viewData->getPointViewObj(poly, index);
		break;
	default:
		break;
	}
	if (vobj == nullptr)
		return;
	if (pre)
		_viewData->preHighLight(vobj); // 设置预高亮
	else
	{
		vobj->highLight(); // 高亮对象
		_viewData->preHighLight(nullptr);
		emit geoShapeSelected(vobj->getGeometySet(), vobj->getIndex());
	}
	_preWindow->reRender();
}

同样,这里也只分析面的高亮,其他的高亮逻辑类似。高亮处理的时候,直接先根据Actor获取了其vtkPolyData数据集,找到哪个面需要高亮,最后更改其颜色。如何根据cell id找到这个面,需要理解其数据结构才能看懂其逻辑。对于面的数据结构,这篇文章【FastCAE源码阅读3】几何模型显示:从OCC对象到VTK对象有详细描述。其核心原理是查找cell id落在哪个面包含的cell区间上,确定高亮哪个面。最后调用_preWindow->reRender()重新绘制整个场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/118356.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nacos-2.2.2源码修改集成高斯数据库GaussDB,postresql

一 &#xff0c;下载代码 Release 2.2.2 (Apr 11, 2023) alibaba/nacos GitHub 二&#xff0c; 执行打包 mvn -Prelease-nacos -Dmaven.test.skiptrue -Drat.skiptrue clean install -U 或 mvn -Prelease-nacos ‘-Dmaven.test.skiptrue’ ‘-Drat.skiptrue’ clean instal…

【vscode】Window11环境下vscode使用Fira Code字体【教程】

【vscode】Window11环境下vscode使用Fira Code字体【教程】 文章目录 【vscode】Window11环境下vscode使用Fira Code字体【教程】1. 下载Fira Code字体2. 安装Fira Code字体3. 配置vscode4. 效果如下Reference 如果想要在Ubuntu环境下使用Fira Code字体&#xff0c;可以参考我的…

三:ffmpeg命令帮助文档

目录 一&#xff1a;帮助文档的命令格式 二&#xff1a;将帮助文档输出到文件 一&#xff1a;帮助文档的命令格式 ffmpeg -h帮助的基本信息ffmpeg -h long帮助的高级信息ffmpeg -h full帮助的全部信息 ffmpeg的命令使用方式&#xff1a;ffmpeg [options] [[infile options] …

FreeRTOS_任务通知

目录 1. 任务通知简介 2. 发送任务通知 2.1 函数 xTaskNotify() 2.2 函数 xTaskNotifyFromISR() 2.3 函数 xTaskNotifyGive() 2.4 函数 vTaskNotifyGiveFromISR() 2.5 函数 xTaskNotifyAndQuery() 2.6 函数 xTaskNotifyAndQueryFromISR() 3. 任务通知通用发送函数 3.…

『亚马逊云科技产品测评』活动征文|EC2云服务器一键部署wordpress博客

『亚马逊云科技产品测评』活动征文&#xff5c;EC2云服务器一键部署wordpress博客 授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技…

CCLINK IEFB总线转ETHERNET/IP网络的协议网关使欧姆龙和三菱的数据互通的简单配置方法

想要实现CCLINK IEFB总线和ETHERNET/IP网络的数据互通。 捷米JM-EIP-CCLKIE是一款ETHERNET/IP从站功能的通讯网关&#xff0c;该产品主要功能是实现CCLINK IEFB总线和ETHERNET/IP网络的数据互通。本网关连接到ETHERNET/IP总线和CCLINK IEFB总线上都可以做为从站使用。网关分别…

全面的Docker快速入门教程

前言&#xff1a; 都2023年了&#xff0c;你还在为了安装一个开发或者部署环境、软件而花费半天的时间吗&#xff1f;你还在解决开发环境能够正常访问&#xff0c;而发布正式环境无法正常访问的问题吗&#xff1f;你还在为持续集成和持续交付&#xff08;CI / CD&#xff09;工…

Android Framework学习之Activity启动原理

Android Activity启动原理 Android 13.0 Activity启动原理逻辑流程图如下&#xff1a;

[直播自学]-[汇川easy320]搞起来(2)看文档

2023.11.06.NIGHT 一 、读 《Easy320可编程逻辑控制器用户手册-CN-A02.PDF》 21&#xff1a;30 好现在看文档 里面提到 I/O滤波可设置&#xff1a; I/O支持短路保护&#xff0c;I/O指示灯程序控制 热量是向上走的&#xff0c;而PLC是大脑&#xff0c;所以放到最下面&am…

matlab图像处理

1.图片的读取&#xff08;下左&#xff09; Iimread(可爱猫咪.jpg);%图像读取&#xff0c;这里内为路径\名称,如&#xff1a;E:\examples\可爱猫咪.jpg figure,imshow(I);%图像显示 title(原图) 2.转为灰度图像&#xff08;上右&#xff09; I_grayrgb2gray(I); figure,imsho…

MySQL主从搭建,实现读写分离(基于docker)

一 主从配置原理 mysql主从配置的流程大体如图&#xff1a; 1&#xff09;master会将变动记录到二进制日志里面&#xff1b; 2&#xff09;master有一个I/O线程将二进制日志发送到slave; 3) slave有一个I/O线程把master发送的二进制写入到relay日志里面&#xff1b; 4&#xf…

【逗老师的无线电】Debian Linux手工编译安装MMDVM

看我干了啥&#xff0c;在Vmware里面装了一个Debian Linux并且运行了MMDVMHost&#xff0c;来支持业余无线电通联 开始之前先举个手&#xff0c;有多少朋友能分清MMDVM和Pi-Star关系的&#xff1f; MMDVM、Pi-Star和树莓派的关系 咱们先科普一下这个小知识点。各位HAM们应…

【Head First 设计模式】-- 策略模式

一、背景 Head First 设计模式第一章设计模式入门–策略模式 二、工具箱的工具&#xff08;本章&#xff09; 1、OO基础 封装 继承 多态 抽象 2、OO原则 封装变化 面向接口编程&#xff0c;而非面向实现编程 组合优于继承 3、OO模式 策略模式&#xff0c;所谓策略模式就是定义…

操作系统:文件管理(二)文件系统

一战成硕 4.3 文件系统4.3.1 文件系统结构4.3.2 文件系统布局4.3.3 外存空闲空间管理4.3.4 虚拟文件系统 4.3 文件系统 4.3.1 文件系统结构 4.3.2 文件系统布局 文件系统在磁盘中的结构 文件系统在内存中的结构 内存中的信息用于管理文件系统并通过缓存提高性能&#xff0c;这…

【JavaEE】JVM 剖析

JVM 1. JVM 的内存划分2. JVM 类加载机制2.1 类加载的大致流程2.2 双亲委派模型2.3 类加载的时机 3. 垃圾回收机制3.1 为什么会存在垃圾回收机制?3.2 垃圾回收, 到底实在做什么?3.3 垃圾回收的两步骤第一步: 判断对象是否是"垃圾"第二步: 如何回收垃圾 1. JVM 的内…

数仓分层能减少重复计算,为啥能减少?如何减少?这篇文章包懂!

很多时候&#xff0c;看一些数据领域的文章&#xff0c;说到为什么做数据仓库、数据仓库要分层&#xff0c;我们经常会看到一些结论&#xff1a;因为有ABCD…等等理由&#xff0c;比如降低开发成本、减少重复计算等等好处 然后&#xff0c;多数人就记住了ABCD。但是&#xff0…

python3 阿里云api进行巡检发送邮件

python3 脚本爬取阿里云进行巡检 不确定pip能不能安装上&#xff0c;使用时候可以百度一下&#xff0c;脚本是可以使用的&#xff0c;没有问题的 太长时间了&#xff0c;pip安装依赖忘记那些了&#xff0c;使用科大星火询问了下&#xff0c;给了下面的&#xff0c;看看能不能使…

知识注入以对抗大型语言模型(LLM)的幻觉11.6

知识注入以对抗大型语言模型&#xff08;LLM&#xff09;的幻觉 摘要1 引言2 问题设置和实验2.1 幻觉2.2 生成响应质量 3 结果和讨论3.1 幻觉3.2 生成响应质量 4 结论和未来工作 摘要 大型语言模型&#xff08;LLM&#xff09;内容生成的一个缺点是产生幻觉&#xff0c;即在输…

WPF中的Binding的常见知识点与技巧

完全来源于十月的寒流&#xff0c;感谢大佬讲解 在XAML中&#xff0c;可以绑定到许多不同类型的数据源和属性。以下是一些可以绑定的常见数据源和属性&#xff1a; 属性&#xff1a;可以绑定到对象的属性&#xff0c;例如控件的Text、Visibility、IsEnabled等属性。 集合&am…

linux内的循环

格式 while 【 条件判断 】 do 语句体 done 上图 第一次代码&#xff0c;输入语句在外面&#xff0c;结果输入完&#xff08;非hello&#xff09;程序不断循环&#xff0c;没办法&#xff0c;ctrlc给程序终止了&#xff0c;然后把用户输入的语句放到了循环体里面…