CATIA二次开发—遍历结构树

简介: CATIA二次开发—遍历结构树

一、前言


春节期间,笔者发布了一个关于 CATIA 获取结构树信息的视频,算是一个预热,这期内容咱们就来解析该功能的底层代码。学会如何遍历结构树,对于CATIA二开来说,是一项很重要的技术手段。但坦白地说,遍历结构树这样的需求并不常见,大部分情况下,我们只需要拿到当前激活的零件activePart即可,而复杂的项目如果需要跨零件或者跨产品进行自动化操作,就必须按层级遍历树上的元素,以便获取非激活产品(零件)内的几何元素。

[video(video-4TEyKyuS-1613828469640)(type-bilibili)(url-https://player.bilibili.com/player.html?aid=929173635)(image-https://ss.csdn.net/p?http://i1.hdslb.com/bfs/archive/8ca89a73408b83e5d6fef4cfca639bcdbaeec347.jpg)(title-获取 CATIA 结构树信息)]
// 获取当前激活的零件
activePart = catia.ActiveEditor.ActiveObject as Part;

在遍历结构树之前,应该确保CATIA软件已经打开一个模型文件,即存在一个ActiveEditor。为了方便后续代码的测试工作,笔者新建了一个极具破环性💣的试验模型树结构:根节点下包含两个产品子节点,每个产品子节点下又包含一个或多个零件,每个零件下包含一个3D Shape。


二、方法及步骤

自己挖坑还得自己填😂。为了帮助读者们理解其中的层次和逻辑关系,笔者绘制了图2,结合图示,看代码会更轻松。

cbf346a083f470788e8daad219afd6c0.png

遍历的第一步必然是获取模型文件的根节点,这里就用到了我们**《CATIA二次开发—API梳理》**一期中提到的Service,通过 editor-level 的service获取根节点的Occurrence model;

// 调用 editor-level service
PLMProductService service = (PLMProductService)CATIA.ActiveEditor.GetService("PLMProductService");
// Getting the root occurrence of the editor
VPMRootOccurrence vpmRootOcc = service.RootOccurrence;

从Occurrence model中获得根产品的Reference ,这一步很重要,需要从Occurrence model切换为Reference-instance model,才能往纵深处遍历;

VPMReference vPMRefOnRoot = vpmRootOcc.ReferenceRootOccurrenceOf;

从根节点中获取所有的instance(即图2中的1.1和 1.2),vpmInstsL1是一个集合;

VPMInstances vpmInstsL1 = vpmRefOnRoot.Instances;

遍历第一层子节点(变量命名中也包含当前节点所在层数,例如上述vpmInstsL1中的L1表示其位于第一层),并获取每个instance 的reference,以便获取下一个层级的实例;

for (int i = 1; i < vpmInstsL1.Count + 1; i++)
{
    VPMInstance vpmInstL1 = vpmInstsL1.Item(i) as VPMInstance;
    // 拿到reference才能拿到instances
    VPMReference vpmRefInstL1 = vpmInstL1.ReferenceInstanceOf;
    ...
    ...
}

除了根节点,所有PLM实体都具有 Reference 和 Instance, Reference作用在于获取该节点子实例的集合


18920f227b226384f06f7b9aca25d65e.png

此时我们已经可以拿到1.1 A.1(1.1.1)这个产品节点,需要继续往下递进,同样通过Instances属性获取此节点的所有实例,并再次遍历;

VPMInstances vpmInstsL2 = vpmRefInstL1.Instances;
for (int j = 1; j < vpmInstsL2.Count + 1; j++)
{
    VPMInstance vpmInstL2 = vpmInstsL2.Item(j) as VPMInstance;
    VPMReference vpmRefInstL2 = vpmInstL2.ReferenceInstanceOf;
    ...
    ...
}

这时已经到了第二层,我们可以顺利地拿到1.1.1 A.1(Physical Product00029)这个节点,如果还需要再递进一层,那就是第三层,即到了3D Shape,此时获取实例集合的方式有所变化,因为该层是实际用于表达几何元素的层级,且没有子节点,获取方式由原先的Instances属性变为RepInstances属性。

🔔3D Shape中的几何图形集、零件几何体等不算作其子节点

VPMRepInstances vpmRefInstsL3 = vpmRefInstL2.RepInstances;
for (int k = i; k < vpmRefInstsL3.Count + 1; k++)
{
    VPMRepInstance vpmRepInstL3 = vpmRefInstsL3.Item(k) as VPMRepInstance;
    VPMRepReference vpmRepRefL3 = vpmRepInstL3.ReferenceInstanceOf;
}

到此,对于图2的结构树已完成遍历,大家完全可以根据此逻辑,举一反三。但又有另外一个问题浮出水面:假如我们不知道结构树长啥样,我们又该如何去遍历呢❓ 能不能实现提供任意一个模型文件都能像图3所示返回其结构树的层次关系❓ 关于这个问题,正是我视频中所实现的功能,这部分功能本期不展开,留给读者们独立思考的空间。


3435d7f27274548c353b119fac8b2536.png


图3.产品模型结构示意


🔉 当然,遍历结构树的方法不限于此。以下是笔者在 COE 论坛的QA,提供了另一种解决的思路。


Q(cao bingyong):


Hi, I am new in V6 COM development, and recently encountered a problem of getting the GeoSet from another part (not in active) which is in another product. I can use the following code to get the root product , but have no idea to find the child product of the root one by name, not to mention, to find the part inside. So, can anyone help? Thanks a lot!


pLMProductService.EditedContent.Item(1)

A(Mahefa Ralijaona):

Hello,
There are I think several ways to do this. Here is one of them: not necessarily the fastest or the simplest, but it's one way. Hope it helps.
Sub CATMain()
    ' Getting active editor (the current tab)
    Dim oActiveEditor As Editor
    Set oActiveEditor = CATIA.ActiveEditor
    ' Getting the root occurrence of the editor
    Dim vpmRootOcc As VPMRootOccurrence
    Set vpmRootOcc = oActiveEditor.GetService("PLMProductService").RootOccurrence
    ' Getting all its children
    Dim vpmRootChildrenOcc As VPMOccurrences
    Set vpmRootChildrenOcc = vpmRootOcc.Occurrences
    ' Getting the first one (28629.1 in your case)
    Dim vpmRootChild1Occ As VPMOccurrence
    Set vpmRootChild1Occ = vpmRootChildrenOcc.Item(1)
    ' Getting the first part inside your 28629.1 (instance 28628.2 of the 3DPart in your case)
    Dim vpmPart1Occ As VPMOccurrence
    Set vpmPart1Occ = vpmRootChild1Occ.Occurrences.Item(1)
    ' Getting the part instance, then the reference
    Dim vpminstPart As VPMInstance
    Set vpminstPart = vpmPart1Occ.InstanceOccurrenceOf
    Dim vpmrefPart As VPMReference
    Set vpmrefPart = vpminstPart.ReferenceInstanceOf
    ' Getting the 3DShape instance, then the 3DShape reference
    Dim vpmrepinstPart As VPMRepInstance
    Set vpmrepinstPart = vpmrefPart.RepInstances.Item(1)
    Dim vpmreprefPart As VPMRepReference
    Set vpmreprefPart = vpmrepinstPart.ReferenceInstanceOf 
End Sub

三、参考资料

《3DEXPEROENCE Automation Help》

相关文章
|
15小时前
|
存储
构建二叉树的基本功能
构建二叉树的基本功能
|
15小时前
|
BI 数据库
如何使用 SAPGUI 中的树控件绘制树状数据结构试读版
如何使用 SAPGUI 中的树控件绘制树状数据结构试读版
13 0
|
15小时前
|
C语言
【数据结构入门指南】二叉树链式结构的实现(保姆级代码思路解读,非常经典)
【数据结构入门指南】二叉树链式结构的实现(保姆级代码思路解读,非常经典)
42 0
|
15小时前
|
存储 算法 Linux
速学数据结构 | 树 森林 二叉树 的概念详讲篇
速学数据结构 | 树 森林 二叉树 的概念详讲篇
44 1
|
15小时前
|
存储 机器学习/深度学习 算法
第六章 树【数据结构和算法】【精致版】
第六章 树【数据结构和算法】【精致版】
69 0
|
10月前
|
存储 C++ 容器
使用C++编写一个图的深度和广度优先遍历的代码
使用C++编写一个图的深度和广度优先遍历的代码
77 0
构建系统发育树简述
构建系统发育树简述
128 0
|
存储 算法 C++
STL设计之链表设计,分块分组件分析,迭代器设计思路
STL设计之链表设计,分块分组件分析,迭代器设计思路
STL设计之链表设计,分块分组件分析,迭代器设计思路
树的概念及结构(一篇足以让你认识树)(1)
树的概念及结构(一篇足以让你认识树)
92 0
树的概念及结构(一篇足以让你认识树)(1)
|
存储
树的概念及结构(一篇足以让你认识树)(2)
树的概念及结构(一篇足以让你认识树)
116 0
树的概念及结构(一篇足以让你认识树)(2)