OCC中如何识别装配体中多次引用的同一零件体

1. 问题背景

在CAD(计算机辅助设计)系统中,装配体通常由多个零件(或称为组件)组成,这些零件可能在不同的装配体中多次引用或共享。例如,一个标准的螺栓或轴承可能在多个装配体中被使用,而在这些装配体的设计中,这些标准零件可能被多次引用。

在采用CAD二次开发或者基于开源平台Open cascade进行开发时,如何准确地识别这些重复的零件体,是一个重要的问题,本文以Open cascade为例,说明识别同一零件体的方法。

2. 识别思路

在前置的开发工作中,已经获得了装配体中所有的零件体,放在了m_vecChildPartNode变量中,可以通过m_vecChildPartNode[i]->getOCCShape()方法,获得每个零件体的TopoDS_Shape对象,如何判断两个同一引用的零件体的TopoDS_Shape对象“相同”呢?

在此需要明确TopoDS_Shape的构成,在OCC中,TopoDS_Shape是描述一个拓扑对象的基本变量,这个类记录了拓扑对象的三个主要数据:位置、方向和共享对象,具体由如下三个数据成员表示:

① Handle(TopoDS_TShape) myTShape;
② TopLoc_Location myLocation;
③ TopAbs_Orientation myOrient;

每个TopoDS_Shape都引用了一份TopoDS_TShape,并为TopoDS_TShape增加了orientation和locaion信息。结合共享数据结构部分就可以看出,TopoDS TShape包含了真正的几何、拓扑数据。
myOrient 记录了拓扑对象的方向, myLocation记录了一个对象的位置信息。

在一个装配体中,如果引用了某个零件n次,这个零件在内存中会有一个唯一的TopoDS_TShape数据,对应n个TopoDS_Shape数据,n个TopoDS_Shape共享一份共同的几何、拓扑数据,但是其各自都有自己的位置信息和方向信息。这样,OCC通过共享TopoDS_TShape,减少了模型数据占用内存的大小,一些后续的操作(例如查找所有的共边)也得以可行,或者得到简化。

因此,识别装配体中多次引用的同一零件体的基本思路就是,获得零件对应的TopoDS_TShape对象,检查TopoDS_TShape是否相同,如果相同,则可以认为两个零件是同一个零件。

3. 代码实现及注意点

在OCC中,获取TopoDS_Shape引用的TopoDS_TShape的接口如下:

//Returns a handle to the actual shape implementation.
const Handle< TopoDS_TShape >& TopoDS_Shape::TShape()const

据此写了如下代码

for (int i = 0; i < m_vecChildPartNode.size(); i++)
 {
    TopoDS_Shape partShape = m_vecChildPartNode[i]->getOCCShape();
    const Handle(TopoDS_TShape)& shape1 = m_vecChildPartNode[i]->getOCCShape().TShape();
    
    for (int j = i + 1; j < m_vecChildPartNode.size(); j++) 
    {
        const Handle(TopoDS_TShape)& shape2 = m_vecChildPartNode[j]->getOCCShape().TShape();

        // 检查 shape1 和 shape2 是否相同
        if (shape1 == shape2)
         {
        	std::cout << "第" << i << "个PartNode和第" << j << "个PartNode的TopoDS_TShape完全相同。" << std::endl;
        }
    }
}

但是运行发现,上述代码运行不正确,检测到所有的零件的TopoDS_TShape都是相同的,输出shape1、shape2的地址,都是000000,这是什么原因造成的?该如何解决呢?

先看最终的解决办法如下:

for (int i = 0; i < m_vecChildPartNode.size(); i++)
 {
    TopoDS_Shape partShape = m_vecChildPartNode[i]->getOCCShape();
    Handle(TopoDS_TShape) shape1 = m_vecChildPartNode[i]->getOCCShape().TShape();
    
    for (int j = i + 1; j < m_vecChildPartNode.size(); j++) 
    {
        Handle(TopoDS_TShape) shape2 = m_vecChildPartNode[j]->getOCCShape().TShape();

        // 检查 shape1 和 shape2 是否相同
        if (shape1 == shape2)
         {
        	std::cout << "第" << i << "个PartNode和第" << j << "个PartNode的TopoDS_TShape完全相同。" << std::endl;
        }
    }
}

只需要把原代码中的 const Handle(TopoDS_TShape) &shape1 和 const Handle(TopoDS_TShape) &shape2 改为Handle(TopoDS_TShape) shape1 和 Handle(TopoDS_TShape) shape2 即可。

下面解释原因:

在c++中,Handle(TopoDS_TShape) shape1 和 Handle(TopoDS_TShape) shape2 是值拷贝的形式,意味着 shape1 和 shape2 是独立的智能指针对象,它们分别指向不同的内存区域或相同的对象。而const Handle(TopoDS_TShape) &shape1 和 const Handle(TopoDS_TShape) &shape2 中,shape1 和 shape2 成为对原智能指针对象的引用。因为它们是引用,因此它们指向相同的智能指针对象。

那么为什么引用和拷贝的结果完全不同呢?

Handle(TopoDS_TShape)是 Open CASCADE 的智能指针类,类似于 C++ 的标准智能指针,如 std::shared_ptr。当使用 Handle(TopoDS_TShape) shape1 和 Handle(TopoDS_TShape) shape2 时,你在函数调用时创建了 shape1 和 shape2 的拷贝。这意味着每个 Handle 都有自己的内部指针,可能指向相同的对象,也可能指向不同的对象。每个 Handle 对象都管理着自己的引用计数和资源。

const Handle(TopoDS_TShape) &是 Handle 类的引用,const 关键字表示引用的是常量,不能修改引用的对象。当使用 const Handle(TopoDS_TShape) &shape1 和 const Handle(TopoDS_TShape) &shape2 时,shape1 和 shape2 是对函数传入的 Handle 对象的引用,而不是拷贝。引用不会创建新的 Handle 对象,它们只是指向原来的 Handle 对象。因此,上面第一段代码输出的shape1 和 shape2的地址均为0000000,指向同一个 未创建的Handle 对象,任何 shape1 和 shape2 的比较都相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值