13.装配
OCCT Assembly 装配概念
前面我们聊的全都是单个零件(Solid实体),但真实工业场景绝大多数都是装配体:一台机器几十上百个零件,还有子装配。STEP文件也大量存储装配结构。 OCCT没有一个叫
TopoDS_Assembly的独立类,装配能力是基于TopoDS_Compound+ 局部坐标系(Trsf 变换矩阵)实现,这是很多新人最容易懵的地方。
1. 两个核心概念:零件 vs 装配
- Part零件 一个独立B‑Rep实体,比如一颗螺丝、一块板。本身自带几何,顶点坐标是零件自身局部坐标系下的坐标。
- Assembly装配 装配不产生新几何!装配本身没有形状、没有面、没有顶点。 它的工作:引用各个零件,给每个零件设置一个空间变换矩阵Trsf(平移+旋转),把零件摆到整机空间的正确位置。 还可以嵌套:大装配里面包含若干子装配,子装配再包含零件。
举个通俗例子: 零件 = 桌子的桌腿模型,它的坐标原点在桌腿底面中心。 装配:4根桌腿,分别设置4套不同的平移变换,摆到桌面四个角。 装配不会修改桌腿原始B‑Rep数据,只是记录“这个实例放在哪个位置”。
⚠️关键:实例(Instance)
同一个零件,可以多次实例化。比如桌子4根桌腿,只保存一份桌腿B‑Rep数据,创建4个实例,每一个实例用不同变换矩阵摆放。 👉极大节省内存,不需要复制4份一模一样几何。这就是装配的核心价值。
2. OCCT的数据结构怎么承载装配
-
TopoDS_Shape:所有拓扑对象的基类 -
TopoDS_Solid:实体(单个零件) -
TopoDS_Compound:组合体,用来充当装配/子装配容器Compound就是一个容器,可以往里面塞各种Shape:Solid、别的Compound。 Compound本身没有几何,只负责持有子元素。
Trsf(gp_Trsf 变换矩阵) 每一个子Shape,都可以附带一个Location(TopoDS_Location),内部存储变换矩阵。
Location就是这个实例在装配空间的摆放位置。
重点坑:
TopoDS_Shape是句柄引用,不是拷贝。 把同一个Solid放到Compound多次,只是引用,不会复制几何;修改原始Solid,所有实例全部跟着变。
3. STEP文件中的装配
STEP有两种存储模式:
- 非装配模式(简单Part) 整个STEP就一个零件,没有层级,读出来直接是Solid/Shell。就是我们前面练习的模型。
- STEP装配模式(AP214 / AP242) STEP内部存在装配层级树:
根装配
├─子装配A
│ ├─零件1 (变换矩阵A1)
│ └─零件2 (变换矩阵A2)
└─零件3(变换矩阵A3)
STEP文件内部:零件几何只定义一次;装配部分记录实例引用和变换。
OCCT读取STEP装配的时候(
STEPControl_Reader): 开启装配模式,会输出嵌套的TopoDS_Compound树,每个子shape携带自己的Location变换。
非常容易踩的大坑:局部坐标 vs 全局坐标
零件的B‑Rep顶点,存储的是零件自身局部坐标系坐标。 不是世界空间最终坐标! 如果你直接拿Face、Vertex去读取坐标,拿到的是零件本地坐标,不是装配摆放之后的真实世界位置。
想要拿到装配后的全局坐标,必须把Location()变换矩阵乘上去。
//获取实例的局部到全局变换
gp_Trsf trsf = myShape.Location().Transformation();
//用trsf把局部点变换得到世界空间点
gpPnt globalPnt = localPnt.Transformed(trsf);
无数新人bug:读取装配模型顶点坐标,坐标全部不对,就是忘记乘Location变换。
4. AIS如何显示装配
AIS_Shape可以接收Compound。 AIS会自动读取每一个子Shape自带的Location变换,渲染的时候把三角网格做矩阵变换,绘制到正确屏幕位置。
两种工作模式:
-
保留装配层级(推荐) Compound树完整保留,每一个零件对应一个AIS对象,或者用AIS_InteractiveCompound;可以单独选中某一个零件实例,隐藏、高亮单个零件。
这才是工业软件交互:点装配里某一颗螺丝,可以单独选中它。
-
炸开(Explode / Flatten) 把所有实例全部展开,把变换矩阵直接作用到几何顶点,把所有零件顶点全部计算到世界坐标系,合并成一个大Solid/Compound。
⚠️炸开之后:丢失装配层级、丢失实例信息。原本4个桌腿实例,变成4份独立复制出来的几何,内存暴涨,再也区分不开哪一个是哪一个。 很多简单demo图省事直接炸开装配,业务项目尽量不要这么做。
5. 装配场景下,之前学过的老问题会全部升级
①网格化BRepMesh
每一个零件实例,原始B‑Rep在自己局部坐标系。 网格化是在零件本地坐标系做!不是全局装配空间。 每个零件单独做BRepMesh_IncrementalMesh生成三角缓存;渲染阶段,GPU把顶点按照实例Location矩阵做变换,摆放到对应位置。
不要把装配Compound整体丢给BRepMesh,会出问题,应该遍历每一个底层Part实体,逐个网格化。
②网格缓存Clean
修改某一个原始零件,所有引用这个零件的实例,都需要BRepTools::Clean,重新网格化。
③拾取(鼠标点选零件)
装配下拾取会更复杂:VTK拿到的是变换之后的网格;需要反向把屏幕射线,乘上实例变换的逆矩阵,映射回零件局部坐标系,才能定位到原始B‑Rep的Face/Edge。
如果直接炸开装配,拾取就失去零件实例信息,只能拿到面片。
④容差Tolerance
每个零件的容差,是零件局部坐标系下的容差。 装配只是摆放零件,装配不会修改零件内部顶点容差。
注意:不能跨装配实例做布尔运算! 两个不同零件实例,只是空间摆在一起,几何上互相穿插,只是视觉重叠;底层B‑Rep互相独立。布尔运算只能对同一个Shape内部拓扑生效。 想做两个装配零件的布尔,必须先把几何炸开合并到同一个坐标系同一个Shape。
6.装配带来的现实工程痛点
- 大装配性能灾难 上百上千个零件,如果全部加载完整B‑Rep,内存爆炸。 于是引出轻量化:不加载原始B‑Rep,只加载网格三角,只保留装配层级和变换矩阵,用于浏览查看,无法编辑。这就是工业软件大装配浏览的主流方案。
- 同一个零件多实例 要区分:原始零件原型,和N个实例。很多业务逻辑(选中、隐藏、属性绑定)要绑定实例,而不是原始零件。
- STEP装配的坑 很多第三方导出STEP装配不规范;有的STEP名义是装配,实际把所有几何炸开平铺,丢失实例信息。
7.串联完整装配STEP导入流程
1.读取STEP AP242装配文件
2.OCCT解析,输出嵌套TopoDS_Compound装配树
每个子节点:携带Location变换,引用原始Part零件B‑Rep
3.遍历树拿到每一个底层Part实体
可选:FixShape做零件级修复(每个零件单独修复)
4.逐个零件:BRepTools::Clean → BRepMesh网格化(在零件局部坐标系)
5.把装配Compound交给AIS交互上下文
6.AIS渲染:读取每个子shape的Location矩阵,网格顶点做矩阵变换,绘制到屏幕
7.鼠标拾取:射线反向逆变换,定位到对应的零件实例、Face

浙公网安备 33010602011771号