【FastCAE源码阅读3】几何模型显示:从OCC对象到VTK对象

news2024/11/28 23:58:32

从几何到显示还是比较麻烦的,需要将几何对象转换成渲染对象,涉及几何建模、面的三角化、图形渲染等学科,阅读本文需了解一些基本的OCC、VTK编程

一、几何体显示基本流程

FastCAE几何内核使用的是OCC,显示渲染用的VTK,那么就存在将OCC建模后的几何对象变成VTK支持类型的数据这个过程。

FastCAE在用OCC创建完模型之后,会生成一个Geometry::GeometrySet对象,这个对象包含了最原始的OCC中TopoDS_Shape实例对象。创建完成后都会发出信号emit showSet(set);,这个信号会触发将TopoDS_Shape变成VTK显示对象。这个段代码是在void GeometryViewProvider::showGeoSet(Geometry::GeometrySet *set, bool render)函数中实现。

二、几何对象变成显示对象过程

几何体是由点、线、面构成的,进行显示的时候是分别提取这些数据,进行单独显示的。也就是说我们看到的一个立方体等几何对象是由三个VTK显示对象Actor拼起来的。注意一个体是没有直接的数据对象与其对应的,体只是逻辑上的概念,所以很多软件中隐藏一个体的面会发现内部是空的。这个函数代码如下:

void GeometryViewProvider::showGeoSet(Geometry::GeometrySet *set, bool render)
{
	QList<vtkPolyData *> viewPolys = _viewData->transferToPoly(set); // 对几何体进行点、线、面的拆分
	vtkPolyData *facePoly = viewPolys.at(0); // 面的多边形数据
	vtkPolyData *edgePoly = viewPolys.at(1); // 边的数据集
	vtkPolyData *pointPoly = viewPolys.at(2); // 点数据集
	GeoViewObj viewObj;
	if (facePoly != nullptr) // 创建显示面的Actor
	{
		vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
		vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
		mapper->SetInputData(facePoly);
		actor->SetMapper(mapper);
		bool vis = set->isVisible();
		bool show = Setting::BusAPI::instance()->getGraphOption()->isShowGeoSurface();
		actor->SetVisibility(show && vis); // 设置是否显示面
		actor->SetPickable(false);   // 不可鼠标拾取?哪里打开呢?
		actor->GetProperty()->SetRepresentationToSurface(); // 这个函数不调用也没看到啥影响
		_preWindow->AppendActor(actor, ModuleBase::D3, false); // 将面actor添加到场景中
		viewObj._faceObj = QPair<vtkActor *, vtkPolyData *>(actor, facePoly);
	}

	// 创建显示边的Actor
	if (edgePoly != nullptr) 
	{
		vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
		vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
		mapper->SetInputData(edgePoly);
		actor->SetMapper(mapper);
		bool vis = set->isVisible();
		bool show = Setting::BusAPI::instance()->getGraphOption()->isShowGeoEdge();
		actor->SetVisibility(show && vis);
		actor->SetPickable(false);
		actor->GetProperty()->SetRepresentationToWireframe();
		//			actor->GetProperty()->EdgeVisibilityOn();
		float width = Setting::BusAPI::instance()->getGraphOption()->getGeoCurveWidth();
		actor->GetProperty()->SetLineWidth(width);
		_preWindow->AppendActor(actor, ModuleBase::D3, false);
		viewObj._edgeObj = QPair<vtkActor *, vtkPolyData *>(actor, edgePoly);
	}

	// 创建显示点的Actor
	if (pointPoly != nullptr)
	{
		vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
		vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
		float size = Setting::BusAPI::instance()->getGraphOption()->getGeoPointSize();
		mapper->SetInputData(pointPoly);
		actor->SetMapper(mapper);
		bool vis = set->isVisible();
		bool show = Setting::BusAPI::instance()->getGraphOption()->isShowGeoPoint();
		actor->SetVisibility(show && vis);
		actor->SetPickable(false);
		actor->GetProperty()->SetRepresentationToPoints();
		actor->GetProperty()->SetPointSize(size);
		_preWindow->AppendActor(actor, ModuleBase::D3, false);
		viewObj._pointObj = QPair<vtkActor *, vtkPolyData *>(actor, pointPoly);
	}
	_geoViewHash.insert(set, viewObj);
	if (render)
		_preWindow->resetCamera();
}

三、几何面数据的提取

几何体的面、边、点转换为vtkPolyData对象的方式类似,都在函数GeometryViewData::transferToPoly()中,这里只分析面数据的提取。

/* 提取几何表面的多边形数据集 */
vtkPolyData *GeometryViewData::transferFace(Geometry::GeometrySet *gset)
{
	TopoDS_Shape *shape = gset->getShape(); // 获取OCC的Shape
	TopExp_Explorer faceExp(*shape, TopAbs_FACE); // 这个类可访问Shape的拓扑关系
	QList<Handle(TopoDS_TShape)> tshapelist; // 放置已访问的Face对象,防止重复访问
	vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
	vtkPolyData *polyData = vtkPolyData::New();
	int beg = 0;
	for (int index = 0; faceExp.More(); faceExp.Next(), ++index) // 开始遍历面
	{
		const TopoDS_Shape &s = faceExp.Current();
		Handle(TopoDS_TShape) ts = s.TShape();
		if (tshapelist.contains(ts)) // 防止重复访问,会存在这种情况吗?
			continue;
		tshapelist.append(ts);
		IVtkOCC_Shape::Handle aShapeImpl = new IVtkOCC_Shape(s); // OCC提供IVtkOCC_Shape类
		vtkSmartPointer<IVtkTools_ShapeDataSource> DS = vtkSmartPointer<IVtkTools_ShapeDataSource>::New(); // OCC提供的VTK数据源
		DS->SetShape(aShapeImpl); 
		vtkSmartPointer<vtkCleanPolyData> cleanFilter = vtkSmartPointer<vtkCleanPolyData>::New();
		cleanFilter->SetInputConnection(DS->GetOutputPort());
		cleanFilter->Update();
		vtkSmartPointer<vtkPolyData> tpolys = vtkSmartPointer<vtkPolyData>::New();
		vtkPolyData *tpolydata = cleanFilter->GetOutput();
		const int np = tpolydata->GetNumberOfPoints(); // 点的数量
		const int nc = tpolydata->GetNumberOfCells();  // cell的数量
		vtkPoints *points = vtkPoints::New();
		for (int i = 0; i < np; i++) //  提取几何点数据
		{
			double *coor = tpolydata->GetPoint(i);
			points->InsertNextPoint(coor);
		}
		tpolys->SetPoints(points); // 设置几何点数据
		vtkCellArray *cells = vtkCellArray::New();
		for (int i = 0; i < nc; ++i)
		{
			vtkCell *cell = tpolydata->GetCell(i);
			vtkIdList *ceid = cell->GetPointIds();
			if (ceid->GetNumberOfIds() == 3) // 只提取三角形,这里获取的cell包含点、线、三角形,一个立方体最后应该有12个三角形
			{
				vtkTriangle *triangle = vtkTriangle::New();
				triangle->DeepCopy(cell); // 有DeepCopy接口
				cells->InsertNextCell(triangle);
			}
		}
		tpolys->SetPolys(cells); // 设置拓扑多边形数据集的cell

		// 法线数据?打开与否貌似不影响显示效果
		vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
		normals->SetInputData(tpolys);
		normals->FlipNormalsOn();
		normals->Update();
		vtkPolyData *facePoly = normals->GetOutput();
		const int ncell = facePoly->GetNumberOfCells();
		if (ncell < 1)
			continue;
		GeometryViewObject *obj = new GeometryViewObject(GeometryViewObject::Face, beg, beg + ncell - 1, ts);
		beg += ncell;
		appendFilter->AddInputData(facePoly);  // 追加到appendFilter中
		auto setViewObj = this->getGeosetObj(gset);
		setViewObj->appendFaceViewObj(index, ts, obj);
	}
	appendFilter->Update();
	polyData->DeepCopy(appendFilter->GetOutput());
	auto setViewObj = this->getGeosetObj(gset);
	setViewObj->setFacePoly(polyData); // 保存面多边形数据
	const int npc = polyData->GetNumberOfCells();
	if (npc < 1)
		return nullptr;
	return polyData;
}

这里要注意几个类:

  1. TopExp_Explorer: OCC提供的遍历几何体拓扑结构的类;
  2. IVtkOCC_Shape、IVtkTools_ShapeDataSource:这俩类可以将面三角化,并变成VTK的cell,注意cell包含面上的点、边、三角形,所以提取面的时候只提取了三角形,这俩类同样是OCC提供的;
  3. vtkPolyDataNormals: 看类名猜测是生成法线的,但是不用这类显示也没啥问题;
  4. vtkAppendPolyData:可以将各个面的数据追加在一起。

最后来张图吧:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode—111.二叉树的最小深度【简单】

2023每日刷题&#xff08;十八&#xff09; Leetcode—111.二叉树的最小深度 DFS实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ int minDepth(struct TreeNode* root…

NCL颜色索引表---全平台可用

NCL颜色索引表—全平台可用

三维向量旋转

三维向量旋转 问题描述问题分析 v ⃗ ∣ ∣ \vec{v}_{||} v ∣∣​的旋转 v ⃗ ⊥ \vec{v}_{\bot} v ⊥​的旋转 v ⃗ \vec{v} v 的旋转结论致谢 问题描述 如图1所示&#xff0c;设一个向量 v ⃗ \vec{v} v 绕另一个向量 u ⃗ [ x , y , z ] T \vec{u}[x,y,z]^{T} u [x,y,z]T…

【电路笔记】-相位差和相移

相位差和相移 文章目录 相位差和相移1、概述2、相位差2.1 同频信号2.2 电流与电压信号2.3 相似频率的信号 3、干扰4、总结 当我们听歌曲时&#xff0c;我们将正弦声音波形感知为音乐。 它们的振幅告诉我们信号有多大&#xff0c;频率告诉我们声音是低音还是高音。 然而&#xf…

vue学习part01

02_Vue简介_哔哩哔哩_bilibili Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org) 1.简介 2.常用用法 新项目一般vue3&#xff0c;老项目vue2 3.vue两种风格&#xff1a;选项式api&#xff08;vue2&#xff09;和组合式api&#xff08;vue3&#xff09; 两种方式实现累…

JS异常处理——throw和try、catch以及debugger

让我为大家介绍一下异常处理吧&#xff01; 异常处理是指预估代码执行过程中可能发生的错误&#xff0c;然后最大程度的避免错误的发生导致整个程序无法继续运行 throw 抛异常 第一种写法 function fun(x, y) {// undefined是false 但取反就是trueif (!x || !y) {// 第一种写…

实习记录--(海量数据如何判重?)--每天都要保持学习状态和专注的状态啊!!!---你的未来值得你去奋斗

海量数据如何判重&#xff1f; 判断一个值是否存在&#xff1f;解决方法&#xff1a; 1.使用哈希表&#xff1a; 可以将数据进行哈希操作&#xff0c;将数据存储在相应的桶中。 查询时&#xff0c;根据哈希值定位到对应的桶&#xff0c;然后在桶内进行查找。这种方法的时间复…

在线词典项目-项目介绍及框架搭建

项目介绍 通过代码实现词典的注册、登录、单词注释查询、历史查询、查询记录。 有道词典分析图 客户端流程图 注释&#xff1a;首先开始-->创建流式套接字-->连接服务器-->输入需要执行的命令代码-->创建循环&#xff0c;判断需要执行的函数&#xff08;如果登录…

基于深度学习的行人重识别(person reid) 计算机竞赛

文章目录 0 前言1 技术背景2 技术介绍3 重识别技术实现3.1 数据集3.2 Person REID3.2.1 算法原理3.2.2 算法流程图 4 实现效果5 部分代码6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的行人重识别 该项目较为新颖&#xff0c;适合…

AIGC | 如何用“Flow”,轻松解决复杂业务问题

随着LLM&#xff08;大语言模型&#xff09;的爆火&#xff0c;不少企业都在寻找通过LLM解决企业业务问题的方法&#xff0c;以达到降本增效的效果。但是&#xff0c;当面对较为复杂的业务问题&#xff08;如&#xff1a;背景资料多、问题分类多、条件判断复杂、涉及模块多等&a…

Java高级互联网架构师之路:垃圾回收器的介绍

本文重点 从本文开始我们将开启垃圾回收器的介绍了,我们知道垃圾回收算法是逻辑改变,而垃圾回收器是具体的实现。我们前面介绍的垃圾回收器有7个,本文将在添加三个,但是这三个目前来看不是很常用,我们只了解一下,我们主要还是讲解这7个垃圾回收器。 十个垃圾回收器 目…

天空卫士为集度智能汽车系上“安全带”

10月27日&#xff0c;集度汽车在北京正式发布了旗下首款量产车型——极越 01 SUV。极越 01 SUV 是一款集科技、智能、美学于一身的纯电动中大型SUV&#xff0c;号称全球首款“AI 汽车机器人”。作为集度的合作伙伴&#xff0c;天空卫士第一时间送上祝福&#xff0c;祝愿极越大卖…

鸿蒙应用开发取消标题栏

在config.json中的module下添加如下内容&#xff1a; "metaData": {"customizeData": [{"name": "hwc-theme","extra": "","value": "androidhwext:style/Theme.Emui.Light.NoTitleBar"}] }…

深度学习_4 数据训练之线性回归

训练数据 线性回归 基本原理 比如我们要买房&#xff0c;机器学习深度学习来预测房价。房价的影响因素有&#xff1a;卧室数量&#xff0c;卫生间数量&#xff0c;居住面积。此外&#xff0c;还需要加上偏差值来计算。我们要找到一个正确率高的计算方法来计算。 首先&#…

web3 React dapp中编写balance组件从redux取出并展示用户资产

好啊 上文WEB3 在 React搭建的Dapp中通过redux全局获取并存储用户ETH与自定义token与交易所存储数量中 我们拿到了用户的一个本身 和 交易所token数量 并放进了redux中做了一个全局管理 然后 我们继续 先 起来ganache的一个模拟环境 ganache -d然后 我们启动自己的项目 顺手发…

SaveToDisk属性

大家好&#xff0c;才是真的好。 Domino Designer的帮助文档里面充满了宝藏&#xff0c;最近就发现一个notesitem对象的SaveToDisk属性&#xff0c;你可以设置它为false&#xff0c;这样&#xff0c;虽然文档保存了&#xff0c;但这个字段本身可以不用保存&#xff0c;不仅可以…

激光雷达标定板如何提高激光雷达避免误判的精准度

激光雷达在提高自动驾驶的安全性方面具有重要作用。它通过高精度测量、避免误判、实时感知、适应不同环境和结合其他传感器等方式&#xff0c;为自动驾驶系统提供准确、可靠的感知数据&#xff0c;从而确保行驶的安全性和稳定性。 激光雷达可以通过以下方式避免误判&#xff1a…

测试用例设计方法:正交试验法详解!

01、正交试验法介绍 正交试验法是研究多因素、多水平的一种试验法&#xff0c;它是利用正交表来对试验进行设计&#xff0c;通过少数的试验替代全面试验&#xff0c;根据正交表的正交性从全面试验中挑选适量的、有代表性的点进行试验&#xff0c;这些有代表性的点具备了“均匀…

2023.11.03 homework

小学4年级数学 1 2 3 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 19…

代码随想录算法训练营第四十二天丨 动态规划part05

1049.最后一块石头的重量II 思路 本题其实就是尽量让石头分成重量相同的两堆&#xff0c;相撞之后剩下的石头最小&#xff0c;这样就化解成01背包问题了。 感觉和昨天讲解的416. 分割等和子集 (opens new window)非常像了。 本题物品的重量为 stones[i]&#xff0c;物品的价…