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

【FastCAE源码阅读9】鼠标框选网格、节点的实现

一、VTK的框选支持类vtkInteractorStyleRubberBandPick

FastCAE的鼠标事件交互类是PropPickerInteractionStyle,它扩展自vtkInteractorStyleRubberBandPick。vtkInteractorStyleRubberBandPick类可以实现鼠标框选物体,默认情况下按下键盘r键开启框选模式,这时拖动鼠标可拾取物体。VTK官网有其例子:HighlightSelection。

二、FastCAE框选产品设计

我们看FastCAE的鼠标拾取产品设计。其只支持框选网格点与网格单元,几何点、线、面都不支持。框选网格单元效果如下:
请添加图片描述

在VTK的给的案例中,按r键是为了打开vtkInteractorStyleRubberBandPick类的框选开关,设置vtkInteractorStyleRubberBandPick字段CurrentMode=1(VTKISRBP_SELECT),表示开启框选模式。VTK中vtkInteractorStyleRubberBandPick.cxx源码如下:

void vtkInteractorStyleRubberBandPick::OnChar()
{switch (this->Interactor->GetKeyCode()){case 'r':case 'R':// r toggles the rubber band selection mode for mouse button 1if (this->CurrentMode == VTKISRBP_ORIENT){this->CurrentMode = VTKISRBP_SELECT;}else{this->CurrentMode = VTKISRBP_ORIENT;}break;case 'p':case 'P':{vtkRenderWindowInteractor* rwi = this->Interactor;int* eventPos = rwi->GetEventPosition();this->FindPokedRenderer(eventPos[0], eventPos[1]);this->StartPosition[0] = eventPos[0];this->StartPosition[1] = eventPos[1];this->EndPosition[0] = eventPos[0];this->EndPosition[1] = eventPos[1];this->Pick();break;}default:this->Superclass::OnChar();}
}

而在FastCAE框选时,不需要按下r键,其原因在用切换拾取模式时,直接改掉了CurrentMode的值,源码如下(注意看这个函数最后一行):

void PropPickerInteractionStyle::setSelectModel(int m)
{_selectModel = (SelectModel)m;this->CurrentMode = 0;if (_actor != nullptr)_actor->GetProperty()->DeepCopy(_property);_actor = nullptr;_preGeoSeltctActor = nullptr;_selectItems.clear();emit grabKeyBoard(false);switch (_selectModel){case ModuleBase::MeshNode:case ModuleBase::MeshCell:case ModuleBase::GeometryWinPoint:case ModuleBase::GeometryWinCurve:case ModuleBase::GeometryWinSurface:case ModuleBase::GeometryWinBody:emit grabKeyBoard(true);break;case ModuleBase::GeometryPoint:case ModuleBase::GeometryCurve:case ModuleBase::GeometrySurface:case ModuleBase::GeometryBody:break;case ModuleBase::BoxMeshNode: // 当选择方式是框选时,直接设置开始框选case ModuleBase::BoxMeshCell:case ModuleBase::DrawSketch:this->CurrentMode = 1;break;}
}

这种设计的好处是不用按键盘进行交互,但造成激活框选按钮之后,视图的角度无法更改。本来按住左键拖拽可以旋转视图的,打开框选之后就失效了。

其框选还有一个比较严重的问题:框选会同时拾取物体的表面与背面单元,效果如下:
请添加图片描述

这种效果惊不惊喜,意不意外!?很多场景下,这种拾取是不满足要求的。进一步分析其框选逻辑就很好理解这种现象了。

三、框选计算逻辑

PropPickerInteractionStyle::OnLeftButtonUp()处理鼠标抬起事件,框选计算哪些物体要被选中的逻辑也在这里被触发。

void PropPickerInteractionStyle::OnLeftButtonUp()
{vtkInteractorStyleRubberBandPick::OnLeftButtonUp();if (_selectModel == None && !_mouseMoved)emit this->clearAllHighLight();if ((_selectModel != BoxMeshCell) && (_selectModel != BoxMeshNode) && (_selectModel != DrawSketch))return;if (this->CurrentMode == 0)return;//		_selectItemIDs->SetNumberOfValues(0);_selectItems.clear();int *endPos = this->GetInteractor()->GetEventPosition();_endPos[0] = endPos[0];_endPos[1] = endPos[1];//		qDebug() << "end  " << _endPos[0] << "   " << _endPos[1];if (_selectModel != DrawSketch){vtkActor *ac = nullptr;vtkAreaPicker *areaPicker = dynamic_cast<vtkAreaPicker *>(this->GetInteractor()->GetPicker());ac = areaPicker->GetActor();if (ac == nullptr)return;}switch (_selectModel){case ModuleBase::BoxMeshNode: // 计算哪些节点被选中boxSelectMeshNode();break;case ModuleBase::BoxMeshCell: // 计算哪些单元要被选中boxSelectMeshCell();break;case ModuleBase::DrawSketch:_coordinate->SetCoordinateSystemToDisplay();_coordinate->SetValue(endPos[0], endPos[1], 0);double *d = _coordinate->GetComputedWorldValue(_renderer);emit mouseReleasePoint(d);break;}_mouseMoved = false;_leftButtonDown = false;
}

boxSelectMeshNode()、boxSelectMeshCell()函数分别哪些节点、单元要被拾取。

void PropPickerInteractionStyle::boxSelectMeshNode()
{emit clearAllHighLight(); // 清除掉当前高亮_selectItems.clear(); // 清理当前选择项// Forward eventsint range[4];this->getBoxRange(range);  // 获取框选矩形的坐标vtkActorCollection *actors = _renderer->GetActors(); // 获取当前的场景中所有actoractors->InitTraversal();const int nac = actors->GetNumberOfItems();for (int i = 0; i < nac; ++i) // 对Actor进行遍历{vtkActor *actor = actors->GetNextActor();if (actor == nullptr)if (!actor->GetVisibility())continue;if (!actor->GetPickable())continue;vtkMapper *mapper = actor->GetMapper();if (mapper == nullptr)continue;vtkDataSet *dataset = mapper->GetInputAsDataSet();if (dataset == nullptr)continue;vtkDataArray *IDS = dataset->GetPointData()->GetArray("IDS"); // 提取Actor的点数据if (IDS == nullptr)continue;this->selectMesh(dataset, range);}emit highLight(&_selectItems);
}void PropPickerInteractionStyle::selectMesh(vtkDataSet *dataSet, int *range)
{vtkRenderer *render = this->GetInteractor()->GetRenderWindow()->GetRenderers()->GetFirstRenderer();vtkSmartPointer<vtkCoordinate> coordinate = vtkSmartPointer<vtkCoordinate>::New();coordinate->SetCoordinateSystemToWorld();coordinate->GetComputedDisplayValue(render);if (_selectModel == BoxMeshNode){vtkDataArray *ids = dataSet->GetPointData()->GetArray("IDS"); // 获取点集const int npoint = dataSet->GetNumberOfPoints();for (int i = 0; i < npoint; ++i){double coor[3];dataSet->GetPoint(i, coor); // 获取点的坐标coordinate->SetValue(coor); // 将点的坐标设置给coordinateint *va = coordinate->GetComputedDisplayValue(render); // 计算屏幕坐标if (isPointInRange(va, range)) // 是否在鼠标框内部{double *k_id = ids->GetTuple2(i); // 看不懂?_selectItems.insert(k_id[0], k_id[1]);}}}else if (_selectModel == BoxMeshCell){vtkDataArray *ids = dataSet->GetCellData()->GetArray("IDS"); // 获取cell数据const int ncell = dataSet->GetNumberOfCells();for (int i = 0; i < ncell; ++i) // 遍历cell{vtkCell *cell = dataSet->GetCell(i); // 当前的celldouble pcenter[3] = {0};cell->GetParametricCenter(pcenter); // 获取当前cell的中心点参数坐标int subid;double coor[3];double w[100];cell->EvaluateLocation(subid, pcenter, coor, w); // 根据参数坐标获取中心点世界空间坐标coordinate->SetValue(coor);int *va = coordinate->GetComputedDisplayValue(render); // 计算屏幕坐标if (isPointInRange(va, range)) // 屏幕坐标是否在选择框内{double *k_id = ids->GetTuple2(i);_selectItems.insert(k_id[0], k_id[1]);}}}
}

根据以上代码,框选点时,直接根据点坐标计算其投影到屏幕上的坐标,判断是否在选择框内。单元是判断中心点是否在选择框内部。因为投影之后,丢弃了深度方向的信息,没有考虑物体的遮挡信息,所以框选时表面、背面均可选择。而且其计算框选时遍历所有网格,没有借助一些加速结构,如BVH树等,造成框选效率较低,当网格数量较多时,这种方式很慢。

总结:

FastCAE的框选逻辑过于简单,只是demo阶段,实际的CAE软件的拾取逻辑要远比这复杂。

相关文章:

【FastCAE源码阅读9】鼠标框选网格、节点的实现

一、VTK的框选支持类vtkInteractorStyleRubberBandPick FastCAE的鼠标事件交互类是PropPickerInteractionStyle&#xff0c;它扩展自vtkInteractorStyleRubberBandPick。vtkInteractorStyleRubberBandPick类可以实现鼠标框选物体&#xff0c;默认情况下按下键盘r键开启框选模式…...

【ArcGIS处理】行政区划与流域区划间转化

【ArcGIS处理】行政区划与流域区划间转化 引言数据准备1、行政区划数据2、流域区划数据 ArcGIS详细处理步骤Step1&#xff1a;统计行政区划下子流域面积1、创建批量处理模型2、添加批量裁剪处理3、添加计算面积 Step2&#xff1a;根据子流域面积占比均化得到各行政区固定值 参考…...

Session、Token、Jwt三种登录方案介绍

新开发一个应用首先要考虑的就是登录怎么去做&#xff0c;登录本身就是判断一下输入的用户名和密码与系统存储的是否一致&#xff0c;但因为Http是无状态协议&#xff0c;用户请求其它接口时是怎么判断该用户已经登录了呢&#xff1f;下面聊一个三种实现方案。 一、传统sessio…...

Linux操作系统使用及C高级编程-D5Linux shell命令(进程管理、用户管理)

进程管理 查看进程ps 其中ps -eif可显示父进程 实时查看进程top 按q退出 树状图显示进程pstree 以父进程&#xff0c;子进程以树状形式展示 发送信号kill kill -l&#xff1a;查看都有哪些信号 9&#xff1a;进程终止 kill不指定信号&#xff0c;默认发送的是15信号SIGT…...

【TDSQL-PG数据库简单介绍】

TDSQL-PG数据库简单介绍 TDSQL-PGTDSQL-PG 设计目标 TDSQL-PG 腾讯 TDSQL-PG 分布式关系型数据库是一款面向海量在线实时分布式事务交易和 MPP 实时数据分析 通用型高性能数据库系统。 面对应用业务产生的不定性数据爆炸需求&#xff0c;不管是高并发的交易还是海量的实时数据…...

【文件包含】metinfo 5.0.4 文件包含漏洞复现

1.1漏洞描述 漏洞编号————漏洞类型文件包含漏洞等级⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐漏洞环境windows攻击方式 MetInfo 是一套使用PHP 和MySQL 开发的内容管理系统。MetInfo 5.0.4 版本中的 /metinfo_5.0.4/about/index.php?fmodule文件存在任意文件包含漏洞。攻击者可利用漏洞读取网…...

差分信号的末端并联电容到底有什么作用?

差分信号的末端并联电容到底有什么作用&#xff1f; 在现代电子系统中&#xff0c;差分信号是一种常见的信号形式&#xff0c;它们通过两根互补的信号线传输信号&#xff0c;具有较低的噪声和更高的抗干扰能力。然而&#xff0c;当差分信号线长度较长或者遇到复杂的电路环境时&…...

pandas教程:GroupBy Mechanics 分组机制

文章目录 Chapter 10 Data Aggregation and Group Operations&#xff08;数据汇总和组操作&#xff09;10.1 GroupBy Mechanics&#xff08;分组机制&#xff09;1 Iterating Over Groups&#xff08;对组进行迭代&#xff09;2 Selecting a Column or Subset of Columns (选中…...

通过右键用WebStorm、Idea打开某个文件夹或者在某一文件夹下右键打开当前文件夹用上述两个应用

通过右键用WebStorm、Idea打开某个文件夹或者在某一文件夹下右键打开当前文件夹用上述两个应用 通过右键点击某个文件夹用Idea打开 首先打开注册表 win R 输入 regedit 然后找到HKEY_CLASSES_ROOT\Directory\shell 然后右键shell 新建一个项名字就叫 Idea 第一步&#xf…...

Android 10.0 framework层设置后台运行app进程最大数功能实现

1. 前言 在10.0的定制开发中,在系统中,对于后台运行的app过多的时候,会比较耗内存,导致系统运行有可能会卡顿,所以在系统优化的 过程中,会限制后台app进程运行的数量,来保证系统流畅不影响体验,所以需要分析下系统中关于限制app进程的相关源码来实现 功能 2.framewo…...

如何快速找到华为手机中下载的文档

手机的目录设置比较繁杂&#xff0c;尤其是查找刚刚下载的文件&#xff0c;有时候需要捣鼓半天&#xff0c;如何快速找到这些文件呢&#xff1f;以下提供了几种方法&#xff1a; 方法一&#xff1a; 文件管理-》搜索文档 方法二&#xff1a; 文件管理-》最近 方法三&#xf…...

iceoryx(冰羚)-Architecture

Architecture 本文概述了Eclipseiceoryx体系结构&#xff0c;并解释了它的基本原理。 Software layers Eclipse iceoryx所包含的主要包如下所示。 接下来的部分将逐一简要介绍组件及其库。 Components and libraries 下面描述了不同的库及其名称空间。 ### iceoryx hoofs …...

LeetCode2-两数相加

大佬解法 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val x; }* }*/ class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode pre new ListNode(0);ListNo…...

css 灰质彩色的边框

border: 4px solid transparent; background-color:#fff; background-clip: padding-box,border-box; background-origin:padding-box, border-box; background-image: linear-gradient(90deg,#F5F6FA,#F5F6FA 42%,#F5F6FA),linear-gradient(151deg,#33e9bf,#c7e58a,#b1e8cc);...

OpenCV实现手势音量控制

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天来学习一下如何使用OpenCV实现手势音量控制&#xff0c;欢迎大家一起前来探讨学习~ 一、需要的库及功能介绍 本次实验需要使用OpenCV和mediapipe库进行手势识别&#xff0c;并利用手势距离控制电脑音量。 导入库&am…...

pytorch 深度学习之余弦相似度

文章目录 用处定理代码F.normalize() 和 F.norm() 的区别 用处 此方法特别重要&#xff0c;经常可以用来修改论文&#xff0c;提出创新点. 定理 余弦相似度是通过计算两个向量之间的夹角余弦值来衡量它们的相似性。给定两个非零向量 x 和 y&#xff0c;它们之间的余弦相似度…...

Postman的常规断言/动态参数断言/全局断言

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 断言&#xff0c;包括状态码断言和业务断言&#xff0c;状态码断言有一个&#xff0c;业务断言有多个。 一&#xff09;常规的…...

ruoyi若依前端请求接口超时,增加响应时长

问题&#xff1a; 前端查询请求超时 解决&#xff1a; 找到request.js的timeout属性由10秒改成了20秒&#xff0c;因为默认是10秒&#xff0c;请求肯定是超出了10秒 祝您万事顺心&#xff0c;没事点个赞呗&#xff0c;关注一下也行啊&#xff0c;有啥要求您评论哈...

贪吃蛇小游戏

一. 准备工作 首先获取贪吃蛇小游戏所需要的头部、身体、食物以及贪吃蛇标题等图片。、 然后&#xff0c;创建贪吃蛇游戏的Java项目命名为snake_game&#xff0c;并在这个项目里创建一个文件夹命名为images&#xff0c;将图片素材导入文件夹。 再在src文件下创建两个包&#…...

cocos----1

1 前言 刚体&#xff08;Rigidbody&#xff09;是运动学&#xff08;Kinematic&#xff09;中的一个概念&#xff0c;指在运动中和受力作用后&#xff0c;形状和大小不变&#xff0c;而且内部各点的相对位置不变的物体。在 Unity3D 中&#xff0c;刚体组件赋予了游戏对…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

C++_哈希表

本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、基础概念 1. 哈希核心思想&#xff1a; 哈希函数的作用&#xff1a;通过此函数建立一个Key与存储位置之间的映射关系。理想目标&#xff1a;实现…...

Cursor AI 账号纯净度维护与高效注册指南

Cursor AI 账号纯净度维护与高效注册指南&#xff1a;解决限制问题的实战方案 风车无限免费邮箱系统网页端使用说明|快速获取邮箱|cursor|windsurf|augment 问题背景 在成功解决 Cursor 环境配置问题后&#xff0c;许多开发者仍面临账号纯净度不足导致的限制问题。无论使用 16…...

简约商务通用宣传年终总结12套PPT模版分享

IOS风格企业宣传PPT模版&#xff0c;年终工作总结PPT模版&#xff0c;简约精致扁平化商务通用动画PPT模版&#xff0c;素雅商务PPT模版 简约商务通用宣传年终总结12套PPT模版分享:商务通用年终总结类PPT模版https://pan.quark.cn/s/ece1e252d7df...

VSCode 没有添加Windows右键菜单

关键字&#xff1a;VSCode&#xff1b;Windows右键菜单&#xff1b;注册表。 文章目录 前言一、工程环境二、配置流程1.右键文件打开2.右键文件夹打开3.右键空白处打开文件夹 三、测试总结 前言 安装 VSCode 时没有注意&#xff0c;实际使用的时候发现 VSCode 在 Windows 菜单栏…...

深入理解 C++ 左值右值、std::move 与函数重载中的参数传递

在 C 编程中&#xff0c;左值和右值的概念以及std::move的使用&#xff0c;常常让开发者感到困惑。特别是在函数重载场景下&#xff0c;如何合理利用这些特性来优化代码性能、确保语义正确&#xff0c;更是一个值得深入探讨的话题。 在开始之前&#xff0c;先提出几个问题&…...