该组件用于操作面网格,组件中封装了简单的面网格划分、面网格特征识别与面网格操作等算法工具,本文介绍其中的两种,分别是封闭空间识别工具与割耳法三角形网格生成工具。
算法一:封闭空间识别
(1)应用场景
封闭空间识别组件用于对复杂结构内的封闭区域的检测与提取,基于船舶舱室的有限元网格模型进行识别,为后续舱室声腔的建立及声学性能分析提供基础。
(2)理论方法
图1 封闭空间识别流程图
- 获取网格模型,包括所有点的坐标,及面所对应的点索引信息,根据信息建立网格对象,存储半边及半面数据结构及拓扑信息。
- 进行网格预处理,将网格中具有自由边的面筛选出来。
- 取任意一个半面作为种子半面,向相邻的半面进行区域生长,识别出种子半面对应封闭空间的所有半面。重新指定种子半面,循环执行该过程,若所有半面均被访问,则已识别出所有封闭空间,循环结束。
- 利用体积法剔除最外层的封闭空间。
- 存储识别结果,包括所有封闭空间及组成封闭空间的半面。
(3)接口说明
接口函数 | 描述 |
bool initMesh(vector<meshPoint>& meshPoints, vector<meshFace>& meshFaces) | 初始化网格模型,构建半边及半面数据结构及拓扑关系。 |
vector<int> meshPreProcess() | 网格预处理,筛选单边面 |
void closedSpaceRec() | 封闭空间识别算法 |
vector< vector<int>> getFacesIndex() | 识别结果,封闭空间及组成该封闭空间的面 |
vector<meshEdge> getPlateBoundery() | 获取板的边界 |
(4)应用示例
1.//网格点及面的数据信息
2.std::vector<meshPoint> mesh_points{};
3.std::vector<meshFace> mesh_faces{};
4.//用于存储识别结果
5.std:: vector<std::vector<int>> faces_index{};
6.std::vector<meshEdge> mesh_edges{};
7.//新建算法对象
8.SpaceRec* test = new SpaceRecAlg;
9.//初始化网格模型
10.test->initMesh(mesh_points, mesh_faces);
11.//网格预处理,筛选出单边面
12.test->meshPreProcess();
13.//获取单边,板的边界
14.mesh_edges = test->getPlateBoundery();
15.//封闭空间识别算法
16.test->closedSpaceRec();
17.//存储组成封闭空间面及索引
18.faces_index = test->getFacesIndex();
模拟下述两种算例,算例一的网格数量为26个,单边面为2个,封闭空间数量为1,输出结果如下图所示
图2 算例一及输出结果
算例二的网格数量为28个,无单边面,封闭空间数量为2个,输出结果如下图所示
图3 算例二及输出结果
参考资料:
[1] 章志兵,杨明润,王丽荣,等.基于CAE模型的船舶舱室自动识别高效算法[J].精密成形工程,2020,12(04):160-165.
[2] 张志康,刘戈,陈乐昆,等.船舶有限元模型舱室识别方法[J].舰船科学技术,2023,45(20):40-43.
[3] Dyedov V , Ray N , Einstein D , et al.AHF: Array-Based Half-Facet Data Structure for Mixed-Dimensional and Non-manifold Meshes[J]. Springer International Publishing, 2014. DOI: 10.1007/978-3-319-02335-9_25.
算法二:割耳法三角形网格生成
(1)应用场景
割耳法生成三角形网格用于若干个顶点组成近似一个平面的多边形分解为三角形集合,可用于凹多边形分解与简单三角网格生成。
(2)理论方法
图4 割耳法三角单元生成流程图
耳朵:多边形顶点上的凸顶点(它的内角小于等于180度),并且除了当前这个点以及前后两个点上,当前顶点和前后两个点组成的三角形内部不存在多边形的其它顶点。
如下图所示,割耳法划分三角形的过程图。图5 割耳法划分三角形过程图
- 有6个点,依次连接形成一个多边形。
- P1是多边形的凸节点,P6,P1,P2组成的三角形不是耳朵。
- P2是多边形的凹节点。P1,P2,P3组成的三角形不是耳朵。
- P3是多边形的凸节点,P2,P3,P4组成的三角形是耳朵,记录三角形,并移除耳尖(P3),形成新的多边形。
- P4是多边形的凸节点,P2,P4,P5组成的三角形是耳朵,记录三角形,并移除耳尖(P4),形成新的多边形。
- P5是多边形的凹节点,P4,P5,P6组成的三角形不是耳朵。
- P6是多边形的凸节点,P5,P6,P1组成的三角形是耳朵,记录三角形,并移除耳尖(P4),形成新的多边形。
- 最后只剩P5,P1,P2,记录三角形,结束。
- 最终形成4个三角形Tri1(P2,P3,P4),Tri2(P2,P4,P5),Tri3(P5,P6,P1),Tri4(P5,P1,P2),
(3)接口说明
接口函数 | 描述 |
void setPointList(const QList<Core::FITKNode*>& nodeList) | 设置点数据 |
bool generateMesh() | 生成三角面 |
QList<FITKAbstractElement*> getTriangle() | 获取三角形列表 |
(4)应用示例
19.//初始化点数据
20.QList<Core::FITKNode*> nodeList;
21.nodeList.append(new Core::FITKNode(1, 0.0, 3.0, 0.0));
22.nodeList.append(new Core::FITKNode(2, 1.5, 1.1, 0.0));
23.nodeList.append(new Core::FITKNode(3, 4.5, 2.8, 0.0));
24.nodeList.append(new Core::FITKNode(4, 4.0, -1.0, 0.0));
25.nodeList.append(new Core::FITKNode(5, 1.0, 1.0, 0.0));
26. nodeList.append(new Core::FITKNode(6, 0.0, 0.0, 0.0));
27.//新建算法对象
28.FITKTriMeshGenEarCut* test = new FITKTriMeshGenEarCut;
29.//设置点数据
30.test->setPointList(nodeList);
31.//生成三角面
32.bool ok = test->generateMesh();
33.//获取三角形列表
34.QList<FITKAbstractElement*> elementList = test->getTriangle();
模拟实例,输出结果如下图所示
参考资料:
[1] Triangulation by Ear Clipping, https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf