本文主要是介绍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 的比较都相同。
这篇关于OCC中如何识别装配体中多次引用的同一零件体的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!