3. CATIA对象模型核心概念
CATIA的二次开发本质上是在操作一棵由COM对象组成的树。理解这棵树的层次关系,比记住任何一段代码都重要。因为一旦你清楚“谁包含谁、谁引用谁”,就能自己推导出访问路径,而不是靠死记硬背API文档。
一、对象层次:从Application到Sketch
CATIA的自动化对象模型是一棵严格的父子树。最顶层是Application,它代表整个CATIA进程本身,是所有操作的入口。Application之下挂着一个Documents集合,这个集合里存放着当前打开的所有文档。每个文档根据类型不同,可能是PartDocument、ProductDocument、DrawingDocument等。对于零件设计自动化来说,我们最关心的是PartDocument。
PartDocument本身是一个“容器文档”,它并不直接包含几何特征。真正的几何数据藏在它内部的Part对象里。Part之下是Bodies集合,一个Part可以包含多个Body,其中第一个通常是PartBody(主实体)。每个Body内部又包含Sketches集合、Shapes集合等。Sketch就是我们常说的草图,它是二维轮廓的载体,也是大多数三维特征的起点。
这条链路可以概括为:Application → Documents → PartDocument → Part → Bodies → Body → Sketches → Sketch。每一层都是通过上一层的属性或方法来获取的,不存在“跳级”访问的捷径。
二、对象引用:如何拿到你想要的节点
在VBA或C#中,访问这棵树有两种典型方式。第一种是逐级向下,从Application开始一层层取属性:
Dim app As Application
Set app = CATIA
Dim docs As Documents
Set docs = app.Documents
Dim pd As PartDocument
Set pd = docs.Item(1) ' 按索引取第一个文档
Dim prt As Part
Set prt = pd.Part
Dim bodies As Bodies
Set bodies = prt.Bodies
Dim body As Body
Set body = bodies.Item("PartBody") ' 按名称取主实体
Dim sketches As Sketches
Set sketches = body.Sketches
Dim sk As Sketch
Set sk = sketches.Item(1)
第二种是利用ActiveDocument快捷入口。当CATIA当前激活的窗口就是目标零件时,可以直接写:
Dim pd As PartDocument
Set pd = CATIA.ActiveDocument
Dim prt As Part
Set prt = pd.Part
两种方式没有优劣之分,但逐级访问更稳健,因为它不依赖“当前激活的是哪个文档”。在批量处理多个文档时,逐级访问几乎是唯一可靠的选择。
三、集合遍历:Bodies与Sketches的循环访问
Bodies和Sketches都是集合对象,它们支持Count属性和Item方法。遍历的标准写法是:
Dim i As Integer
For i = 1 To bodies.Count
Dim b As Body
Set b = bodies.Item(i)
Debug.Print "Body名称: " & b.Name
Next i
注意CATIA集合的索引从1开始,不是0。这是COM自动化中常见的约定,写循环时务必确认。Sketches的遍历同理:
Dim j As Integer
For j = 1 To body.Sketches.Count
Dim s As Sketch
Set s = body.Sketches.Item(j)
Debug.Print "草图: " & s.Name
Next j
如果只想找特定名称的对象,可以用Item("名称")直接定位,比循环遍历更高效。但要注意,如果名称不存在,Item会抛出错误,所以实际代码中通常配合错误处理使用。
四、一个完整的遍历示例
下面这段代码遍历当前零件文档中的所有Body,并打印每个Body下的草图数量。它把前面讲的层次关系和集合遍历串在了一起:
Sub ListAllSketches()
Dim pd As PartDocument
Set pd = CATIA.ActiveDocument
Dim prt As Part
Set prt = pd.Part
Dim bodies As Bodies
Set bodies = prt.Bodies
Dim i As Integer, j As Integer
For i = 1 To bodies.Count
Dim b As Body
Set b = bodies.Item(i)
Debug.Print "Body: " & b.Name & " | 草图数: " & b.Sketches.Count
For j = 1 To b.Sketches.Count
Dim s As Sketch
Set s = b.Sketches.Item(j)
Debug.Print " - " & s.Name
Next j
Next i
End Sub
运行后,立即窗口会输出类似下面的结果(示例数据):
Body: PartBody | 草图数: 3
- Sketch.1
- Sketch.2
- Sketch.3
Body: Body.2 | 草图数: 1
- Sketch.4
这个输出直接反映了对象树的实际结构:PartBody下有3个草图,Body.2下有1个草图。如果你在开发中拿到的结果与预期不符,第一件事就是检查遍历的起点是否正确——是遍历了所有Body,还是只遍历了PartBody。
五、常见陷阱与验证方法
第一个陷阱是空引用。如果ActiveDocument不是PartDocument(比如当前激活的是ProductDocument),那么pd.Part会直接报错。稳妥的做法是先判断文档类型:
If TypeName(CATIA.ActiveDocument) = "PartDocument" Then
' 安全访问
End If
第二个陷阱是集合索引越界。在遍历前先检查Count是否大于0,可以避免不必要的运行时错误。第三个陷阱是对象未更新。通过API创建草图或特征后,有时需要调用Part.Update()才能让几何数据真正生效,否则后续遍历可能读不到刚创建的对象。
验证对象引用是否正确,最直接的方法是在立即窗口打印对象的Name属性。如果打印出的名称与你预期的一致,说明引用链路是通的;如果报错或名称为空,就需要往回追溯是哪一层取错了对象。