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

这篇具有很好参考价值的文章主要介绍了【FastCAE源码阅读5】使用VTK实现鼠标拾取对象并高亮。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

对几何而言,拾取类型切换在工具栏上,单击后再来单击视图区对象进行拾取,拾取后的对象会高亮显示。效果如下图:
fastcae源码,FastCAE源码阅读,图形渲染,c++

一、拾取对象

拾取对象是在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框架提供的编程机制。其对应的槽函数在如下图中能找到:
fastcae源码,FastCAE源码阅读,图形渲染,c++

三、高亮拾取对象

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

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()重新绘制整个场景。文章来源地址https://www.toymoban.com/news/detail-786261.html

到了这里,关于【FastCAE源码阅读5】使用VTK实现鼠标拾取对象并高亮的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【源码】hamcrest 源码阅读 空对象模式、模板方法模式的应用

    hamcrest ,一个被多个测试框架依赖的包。听说 hamcrest 的源码质量很高,特此来学习一下。建议fork原仓库,拉到本地看代码。 代码仓库 hamcrest github 仓库 看个大概的类图。很经典的接口、抽象类、子类实现 将源码逐一拆解,提取有借鉴意义的编码方式。 2.1 抽象类 BaseMatcher

    2024年02月07日
    浏览(39)
  • Open3D-GUI系列教程(五)鼠标事件(拾取顶点)

    这里实现一下鼠标拾取顶点的操作。open3d本身提供了交互选点的操作 gui.SceneWidget.Controls.PICK_POINTS ,但是出于某些超出我认知范围的因素,这玩意儿根本不起作用。所以只能另辟蹊径。 最新的open3d 0.15.1好像修复了这个bug,我试了一下好像还不行,或许是我真的不会用。 open

    2024年02月02日
    浏览(50)
  • VTK——设置交互样式上的鼠标回调函数

    VTKPointPickerInteractorStyle是一个自定义的交互样式类,它是VTK库中vtkInteractorStyleTrackballCamera类的子类。VTK(Visualization Toolkit)是一个开源的,跨平台的库,用于处理、渲染和视觉化科学数据。它包括一系列的类和方法用于3D计算机图形、图像处理和可视化。 vtkInteractorStyleTrackba

    2024年02月10日
    浏览(51)
  • VTK & QT QVTKWidget自定义鼠标和键盘交互事件

    目录 一、问题描述 二、代码实现 1. 自定义鼠标交互事件 2. 移除默认鼠标交互监听事件,塞入自定义监听事件 在使用VTK显示的过程中,通常会使用QT来进行界面设计。这里通常使用QVTKWidget将VTK的渲染窗口显示到QT的组件中。 QVTKWidget组件自带交互器vtkRenderWindowInteractor和Rende

    2024年02月14日
    浏览(57)
  • Qt/C++音视频开发60-坐标拾取/按下鼠标获取矩形区域/转换到视频源真实坐标

    通过在通道画面上拾取鼠标按下的坐标,然后鼠标移动,直到松开,根据松开的坐标和按下的坐标,绘制一个矩形区域,作为热点或者需要电子放大的区域,拿到这个坐标区域,用途非常多,可以直接将区域中的画面放大,也可以将该圈起来的区域位置发给设备,由设备设定

    2024年02月03日
    浏览(52)
  • 【unity小技巧】使用贝塞尔曲线实现导弹随机攻击敌人,也可以用于平滑拾取物品

    参考原视频链接: 【视频】:https://www.bilibili.com/video/BV1aU4y1v7yM/ 注意 :本文为学习笔记记录,推荐支持原作者,去看原视频自己手敲代码理解更加深入

    2024年02月13日
    浏览(39)
  • 【Python】使用VTK实现3D可视化医学图像(格式.nii.gz)

    需要安装依赖 itk 和 vtk ,效果如下 参考: A NIfTI (nii.gz) 3D Visualizer using VTK and Qt5 Load nifti image with vtk () ITK笔记–读取3D NIFTI图像并用VTK可视化

    2024年02月11日
    浏览(57)
  • 《vtk9 book》 官方web版 第2章 - 面向对象设计

     备注:本篇偏向面向对象基础知识,可以略过。               面向对象的系统因为很好的原因在计算机行业变得越来越普遍。面向对象的系统比传统的过程式系统更模块化、更易于维护,也更容易描述。由于可视化工具包是使用面向对象设计进行设计和实现的,我们在

    2024年01月23日
    浏览(41)
  • Unity实现按键拾取物品

    本来是想通过OnTriggerStay来检测玩家与物品的碰撞,如果一直处于碰撞中,且按下了K键,那么就能拾取。 但是用这种方法总会有某种延迟的问题(可能是跟碰撞检测频率有关),导致我按多次K键才有可能捡起物品。 所以换一种思路,开始碰撞时将某bool值设为true,结束碰撞时

    2024年02月01日
    浏览(31)
  • 【测试】pywinauto的简单使用(安装、常用对象、元素控件、鼠标操作、键盘操作)

    1.说明 pywinauto是一个用于自动化Python 模块,适合Windows系统的软件(GUI),可以通过Pywinauto遍历窗口(对话框)和窗口里的控件,也可以控制鼠标和键盘输入,所以它能做的事情比之前介绍的pysimplegui更多 2.安装 一般使用pip安装就行了 官网文档:https://pywinauto.readthedocs.io/en/

    2024年02月11日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包