OpenCASCADE BRepTools

eryar@163.com

Abstract. OpenCASCADE BRepTools provides utilities for BRep data structure. OuterWire method to find the outer wire of a face. Dump method to dump a BRep object. It also can be used as the data exchange for OpenCASCADE native shapes.

Key Words. OpenCASCADE, BRepTools, BRep, Topology

1. Introduction

OpenCASCADE 提供了一个类BRepTools,其中有许多static函数,主要用来对BRep表示的拓朴形状的数据进行读写,也提供了查找一个面中外环(Outer Wire)的函数。因为OpenCASCADE中的边界表示法BRep的数据结构如下图1.1所示:

Figure 1.1 BRep Data Structure of OpenCASCADE

因为OpenCASCADE中拓朴结构采用了包含关系,当需要将TopoDS_Shape数据保存到文件时,如何保持TopoDS_Shape中的关系,以便于从文件读取这些数据时,可以重构出TopoDS_Shape中的各种关系?

参 考opennurbs中的BRep表示时数据的存储方式,可知直接在BRep中保存拓朴及几何数据的索引,这样对数据的存储及读取时重构拓朴结构还是很方 便的。而在OpenCASCADE中拓朴数据是以Handle来保存的,且为组合关系,即一个父结构中有一个列表 (TopoDS_ListOfShape)给包含了子结构数据。对于没有索引的OpenCASCADE的拓朴结构,如何进行读写操作呢?

本文结合类BRepTools中的函数,对OpenCASCADE中TopoDS_Shape数据的保存和读取功能的代码进行分析,从而对ModelingData中的BRep数据做进一步的理解。

2.Topology Shape Serialization

OpenCASCADE的类BRepTools中提供了如下函数,可以TopoDS_Shape中的数据进行导入导出:

v BRepTools::Dump();

v BRepTools::Read();

v BRepTools::Write();

这 几个函数比较常用,因为可以方便地将TopoDS_Shape导出,或导入到OpenCASCADE的Draw Test Harness中,来对程序一些算法进行验证。对于使用了组合关系的TopoDS_Shape如何确保数据的保存及读取后,能够维持这些关系?带着这个问 题去看BRep文件读写的功能,应该更为清晰。

还是看看代码,如下所示为输出TopoDS_Shape的函数,在程序Debug时比较常用:

  1. //=======================================================================
  2. //function : Dump
  3. //purpose :
  4. //=======================================================================
  5. void BRepTools::Dump(const TopoDS_Shape& Sh, Standard_OStream& S)
  6. {
  7. BRepTools_ShapeSet SS;
  8. SS.Add(Sh);
  9. SS.Dump(Sh,S);
  10. SS.Dump(S);
  11. }

其中使用了类BRepTools_ShapeSet,这里的Set的意思我理解为集合的意思,其Add函数如下:

  1. //=======================================================================
  2. //function : Add
  3. //purpose :
  4. //=======================================================================
  5. Standard_Integer TopTools_ShapeSet::Add(const TopoDS_Shape& S)
  6. {
  7. if (S.IsNull()) return ;
  8. myLocations.Add(S.Location());
  9. TopoDS_Shape S2 = S;
  10. S2.Location(TopLoc_Location());
  11. Standard_Integer index = myShapes.FindIndex(S2);
  12. if (index == ) {
  13. AddGeometry(S2);
  14.  
  15. for (TopoDS_Iterator its(S2,Standard_False,Standard_False);
  16. its.More(); its.Next())
  17. Add(its.Value());
  18. index = myShapes.Add(S2);
  19. }
  20. return index;
  21. }

这是一个递归函数,通过AddGeometry函数,将TopoDS_Shape中的几何信息都保存到相应的集合Set中,Set中使用了Map,即给每个几何信息一个唯一的编号与之对应。

  1. //=======================================================================
  2. //function : AddGeometry
  3. //purpose :
  4. //=======================================================================
  5.  
  6. void BRepTools_ShapeSet::AddGeometry(const TopoDS_Shape& S)
  7. {
  8. // Add the geometry
  9.  
  10. if (S.ShapeType() == TopAbs_VERTEX) {
  11.  
  12. Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(S.TShape());
  13. BRep_ListIteratorOfListOfPointRepresentation itrp(TV->Points());
  14.  
  15. while (itrp.More()) {
  16. const Handle(BRep_PointRepresentation)& PR = itrp.Value();
  17.  
  18. if (PR->IsPointOnCurve()) {
  19. myCurves.Add(PR->Curve());
  20. }
  21.  
  22. else if (PR->IsPointOnCurveOnSurface()) {
  23. myCurves2d.Add(PR->PCurve());
  24. mySurfaces.Add(PR->Surface());
  25. }
  26.  
  27. else if (PR->IsPointOnSurface()) {
  28. mySurfaces.Add(PR->Surface());
  29. }
  30.  
  31. ChangeLocations().Add(PR->Location());
  32. itrp.Next();
  33. }
  34.  
  35. }
  36. else if (S.ShapeType() == TopAbs_EDGE) {
  37.  
  38. // Add the curve geometry
  39. Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(S.TShape());
  40. BRep_ListIteratorOfListOfCurveRepresentation itrc(TE->Curves());
  41.  
  42. while (itrc.More()) {
  43. const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
  44. if (CR->IsCurve3D()) {
  45. if (!CR->Curve3D().IsNull()) {
  46. myCurves.Add(CR->Curve3D());
  47. ChangeLocations().Add(CR->Location());
  48. }
  49. }
  50. else if (CR->IsCurveOnSurface()) {
  51. mySurfaces.Add(CR->Surface());
  52. myCurves2d.Add(CR->PCurve());
  53. ChangeLocations().Add(CR->Location());
  54. if (CR->IsCurveOnClosedSurface())
  55. myCurves2d.Add(CR->PCurve2());
  56. }
  57. else if (CR->IsRegularity()) {
  58. mySurfaces.Add(CR->Surface());
  59. ChangeLocations().Add(CR->Location());
  60. mySurfaces.Add(CR->Surface2());
  61. ChangeLocations().Add(CR->Location2());
  62. }
  63. else if (myWithTriangles) { // for XML Persistence
  64. if (CR->IsPolygon3D()) {
  65. if (!CR->Polygon3D().IsNull()) {
  66. myPolygons3D.Add(CR->Polygon3D());
  67. ChangeLocations().Add(CR->Location());
  68. }
  69. }
  70. else if (CR->IsPolygonOnTriangulation()) {
  71. myTriangulations.Add(CR->Triangulation());
  72. myNodes.Add(CR->PolygonOnTriangulation());
  73. ChangeLocations().Add(CR->Location());
  74. if (CR->IsPolygonOnClosedTriangulation())
  75. myNodes.Add(CR->PolygonOnTriangulation2());
  76. }
  77. else if (CR->IsPolygonOnSurface()) {
  78. mySurfaces.Add(CR->Surface());
  79. myPolygons2D.Add(CR->Polygon());
  80. ChangeLocations().Add(CR->Location());
  81. if (CR->IsPolygonOnClosedSurface())
  82. myPolygons2D.Add(CR->Polygon2());
  83. }
  84. }
  85. itrc.Next();
  86. }
  87. }
  88.  
  89. else if (S.ShapeType() == TopAbs_FACE) {
  90.  
  91. // Add the surface geometry
  92. Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(S.TShape());
  93. if (!TF->Surface().IsNull()) mySurfaces.Add(TF->Surface());
  94.  
  95. if (myWithTriangles) { // for XML Persistence
  96. Handle(Poly_Triangulation) Tr = TF->Triangulation();
  97. if (!Tr.IsNull()) myTriangulations.Add(Tr);
  98. }
  99.  
  100. ChangeLocations().Add(TF->Location());
  101. }
  102. }

由上述代码可知,Edge中的几何信息较多,Face中的几何信息最少,只是几何曲面或其用于显示的网格数据。在将拓朴数据输出时,拓朴面、边及顶点中包含的几何信息都是前面几何数据的编号,即相当于索引号的形式输出,代码如下所示:

  1. //=======================================================================
  2. //function : WriteGeometry
  3. //purpose :
  4. //=======================================================================
  5.  
  6. void BRepTools_ShapeSet::WriteGeometry(const TopoDS_Shape& S,
  7. Standard_OStream& OS)const
  8. {
  9. // Write the geometry
  10.  
  11. if (S.ShapeType() == TopAbs_VERTEX) {
  12.  
  13. // Write the point geometry
  14. TopoDS_Vertex V = TopoDS::Vertex(S);
  15. OS << BRep_Tool::Tolerance(V) << "\n";
  16. gp_Pnt p = BRep_Tool::Pnt(V);
  17. OS<<p.X()<<" "<<p.Y()<<" "<<p.Z()<<"\n";
  18.  
  19. Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(S.TShape());
  20. BRep_ListIteratorOfListOfPointRepresentation itrp(TV->Points());
  21.  
  22. while (itrp.More()) {
  23. const Handle(BRep_PointRepresentation)& PR = itrp.Value();
  24.  
  25. OS << PR->Parameter();
  26. if (PR->IsPointOnCurve()) {
  27. OS << " 1 " << myCurves.Index(PR->Curve());
  28. }
  29.  
  30. else if (PR->IsPointOnCurveOnSurface()) {
  31. OS << " 2 " << myCurves2d.Index(PR->PCurve());
  32. OS << " " << mySurfaces.Index(PR->Surface());
  33. }
  34.  
  35. else if (PR->IsPointOnSurface()) {
  36. OS << " 3 " << PR->Parameter2() << " ";
  37. OS << mySurfaces.Index(PR->Surface());
  38. }
  39.  
  40. OS << " " << Locations().Index(PR->Location());
  41. OS << "\n";
  42.  
  43. itrp.Next();
  44. }
  45.  
  46. OS << "0 0\n"; // end representations
  47.  
  48. }
  49.  
  50. else if (S.ShapeType() == TopAbs_EDGE) {
  51.  
  52. // Write the curve geometry
  53.  
  54. Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(S.TShape());
  55.  
  56. OS << " " << TE->Tolerance() << " ";
  57. OS << ((TE->SameParameter()) ? : ) << " ";
  58. OS << ((TE->SameRange()) ? : ) << " ";
  59. OS << ((TE->Degenerated()) ? : ) << "\n";
  60.  
  61. Standard_Real first, last;
  62. BRep_ListIteratorOfListOfCurveRepresentation itrc = TE->Curves();
  63. while (itrc.More()) {
  64. const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
  65. if (CR->IsCurve3D()) {
  66. if (!CR->Curve3D().IsNull()) {
  67. Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itrc.Value());
  68. GC->Range(first, last);
  69. OS << "1 "; // -1- Curve 3D
  70. OS << " "<<myCurves.Index(CR->Curve3D());
  71. OS << " "<<Locations().Index(CR->Location());
  72. OS << " "<<first<<" "<<last;
  73. OS << "\n";
  74. }
  75. }
  76. else if (CR->IsCurveOnSurface()) {
  77. Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itrc.Value());
  78. GC->Range(first, last);
  79. if (!CR->IsCurveOnClosedSurface())
  80. OS << "2 "; // -2- Curve on surf
  81. else
  82. OS << "3 "; // -3- Curve on closed surf
  83. OS <<" "<<myCurves2d.Index(CR->PCurve());
  84. if (CR->IsCurveOnClosedSurface()) {
  85. OS <<" " << myCurves2d.Index(CR->PCurve2());
  86. PrintRegularity(CR->Continuity(),OS);
  87. }
  88. OS << " " << mySurfaces.Index(CR->Surface());
  89. OS << " " << Locations().Index(CR->Location());
  90. OS << " "<<first<<" "<<last;
  91. OS << "\n";
  92.  
  93. // Write UV Points // for XML Persistence higher performance
  94. if (FormatNb() == )
  95. {
  96. gp_Pnt2d Pf,Pl;
  97. if (CR->IsCurveOnClosedSurface()) {
  98. Handle(BRep_CurveOnClosedSurface) COCS =
  99. Handle(BRep_CurveOnClosedSurface)::DownCast(CR);
  100. COCS->UVPoints2(Pf,Pl);
  101. }
  102. else {
  103. Handle(BRep_CurveOnSurface) COS =
  104. Handle(BRep_CurveOnSurface)::DownCast(CR);
  105. COS->UVPoints(Pf,Pl);
  106. }
  107. OS << Pf.X() << " " << Pf.Y() << " " << Pl.X() << " " << Pl.Y() << "\n";
  108. }
  109. }
  110. else if (CR->IsRegularity()) {
  111. OS << "4 "; // -4- Regularity
  112. PrintRegularity(CR->Continuity(),OS);
  113. OS << " "<<mySurfaces.Index(CR->Surface());
  114. OS << " "<<Locations().Index(CR->Location());
  115. OS << " "<<mySurfaces.Index(CR->Surface2());
  116. OS << " "<<Locations().Index(CR->Location2());
  117. OS << "\n";
  118. }
  119.  
  120. else if (myWithTriangles) { // for XML Persistence
  121. if (CR->IsPolygon3D()) {
  122. Handle(BRep_Polygon3D) GC = Handle(BRep_Polygon3D)::DownCast(itrc.Value());
  123. if (!GC->Polygon3D().IsNull()) {
  124. OS << "5 "; // -5- Polygon3D
  125. OS << " "<<myPolygons3D.FindIndex(CR->Polygon3D());
  126. OS << " "<<Locations().Index(CR->Location());
  127. OS << "\n";
  128. }
  129. }
  130. else if (CR->IsPolygonOnTriangulation()) {
  131. Handle(BRep_PolygonOnTriangulation) PT =
  132. Handle(BRep_PolygonOnTriangulation)::DownCast(itrc.Value());
  133. if (!CR->IsPolygonOnClosedTriangulation())
  134. OS << "6 "; // -6- Polygon on triangulation
  135. else
  136. OS << "7 "; // -7- Polygon on closed triangulation
  137. OS << " " << myNodes.FindIndex(PT->PolygonOnTriangulation());
  138. if (CR->IsPolygonOnClosedTriangulation()) {
  139. OS << " " << myNodes.FindIndex(PT->PolygonOnTriangulation2());
  140. }
  141. OS << " " << myTriangulations.FindIndex(PT->Triangulation());
  142. OS << " "<<Locations().Index(CR->Location());
  143. OS << "\n";
  144. }
  145. }
  146.  
  147. itrc.Next();
  148. }
  149. OS << "0\n"; // end of the list of representations
  150. }
  151.  
  152. else if (S.ShapeType() == TopAbs_FACE) {
  153.  
  154. Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(S.TShape());
  155. const TopoDS_Face& F = TopoDS::Face(S);
  156.  
  157. if (!(TF->Surface()).IsNull()) {
  158. OS << ((BRep_Tool::NaturalRestriction(F)) ? : );
  159. OS << " ";
  160. // Write the surface geometry
  161. OS << " " <<TF->Tolerance();
  162. OS << " " <<mySurfaces.Index(TF->Surface());
  163. OS << " " <<Locations().Index(TF->Location());
  164. OS << "\n";
  165. }
  166. else //For correct reading of null face
  167. {
  168. OS << ;
  169. OS << " ";
  170. OS << " " <<TF->Tolerance();
  171. OS << " " << ;
  172. OS << " " << ;
  173. OS << "\n";
  174. }
  175. if (myWithTriangles) { // for XML Persistence
  176. if (!(TF->Triangulation()).IsNull()) {
  177. OS << ;
  178. OS << " ";
  179. // Write the triangulation
  180. OS << " " <<myTriangulations.FindIndex(TF->Triangulation());
  181. }
  182. }
  183. }
  184.  
  185. }

通过先将几何数据收集到相应的集合(映射)中,再在拓朴结构对应的地方以索引号的方式输出,这样就便于从文件读取数据时,以类似的方式来重构BRep边界表示的拓朴Shape的结构。即读取文件重构拓朴结构数据是输出的逆过程。

在实现从文件读取BRep表示的数据时,先将几何信息读取到对应的集合中,再读取拓朴结构数据时,若拓朴结构中包含几何信息,则以索引的方式,找到对应的几何数据即可。详细实现可参考源程序。

3. For Debugging

由 于BRepTools为Toolkit TKBRep中的类,所以依赖的动态库较少,所以在编程时,若要验证一些算法的正确性时,经常需要将TopoDS_Shape的数据导出,甚至可以直接先 在Draw Test Harness中使用相关命令来将导出的数据导入来查看结果。

4. Conclusion

通 过BRepTools中对TopoDS_Shape数据的输出及导入的代码分析可知,对于只有组合关系的数据,若想维持这种关系,就需要引入集合映射的类 来产生索引,进而在读取数据时,可以根据索引来重构拓朴关系。由于opennurbs中的BRep在内存中本来就是索引的方式,所以在数据存取时,实现要 简单很多。

5. References

1. OpenCASCADE Team. BRep Format. 2014.12

2. Shing Liu. Topology and Geometry in OpenCascade-Topology.

http://www.cppblog.com/eryar/archive/2013/09/21/203338.html

3. Shing Liu. Topology and Geometry in OpenCascade-Vertex

http://www.cppblog.com/eryar/archive/2013/08/20/202678.html

4. Shing Liu. Topology and Geometry in OpenCascade-Edge

http://www.cppblog.com/eryar/archive/2013/08/24/202739.html

5. Shing Liu. Topology and Geometry in OpenCascade-Face

http://www.cppblog.com/eryar/archive/2013/09/12/203199.html

OpenCASCADE BRepTools的更多相关文章

  1. Make Helix Curve in OpenCASCADE

    Make Helix Curve in OpenCASCADE eryar@163.com Abstract. OpenCASCADE does not provide helix curve dir ...

  2. OpenCASCADE Hidden Line Removal

    OpenCASCADE Hidden Line Removal eryar@163.com Abstract. To provide the precision required in industr ...

  3. OpenCASCADE Make Primitives-Sphere

    OpenCASCADE Make Primitives-Sphere eryar@163.com Abstract. The sphere is the simplest topology shape ...

  4. OpenCASCADE Make Primitives-Box

    OpenCASCADE Make Primitives-Box eryar@163.com Abstract. By making a simple box to demonstrate the BR ...

  5. OpenNURBS to OpenCASCADE

    OpenNURBS to OpenCASCADE eryar@163.com Abstract. The OpenNURBS initiative provides CAD/CAM/CAE and c ...

  6. OpenCascade Primitives BRep - Box

    OpenCascade Primitives BRep - Box eryar@163.com Abstract. BRep is short for Boundary Representation. ...

  7. Topology Shapes of OpenCascade BRep

    Topology Shapes of OpenCascade BRep eryar@163.com 摘要Abstract:通过对OpenCascade中的BRep数据的读写,理解边界表示法的概念及实现 ...

  8. OpenCASCADE 基础

    OpenCASCADE 基础 转载▼ 一直在用OCC作项目,但这方面的中文资料很少,看来OCC在中国还不是十分普及: 后来,项目中使用OCC和DirectX结合使用,取得了很好的效果: 随着OCC6. ...

  9. FreeType in OpenCASCADE

    FreeType in OpenCASCADE eryar@163.com Abstract. FreeType is required for text display in the 3D view ...

随机推荐

  1. linux安装oracle11g

    准备oracle安装文件 Oracle11gR2包含两个文件linux_11gR2_database_1of2.zip和linux_11gR2_database_2of2.zip,将这两个文件通过SS ...

  2. PHP中关于PDO的使用

    执行没有结果集的查询 执行INSERT,UPDATE,DELETE的时候,不返回结果集.这个时候可以是有exec(),exec()将返回查询所影响的行数 int PDO::exec ( string ...

  3. bzoj1051Tarjan裸题

    tarjan缩点+判断出度为0的点 所以不需要新建边 #include <cstdio> ,time=,T=,sum=,ans=; ],to[],nex[],fir[],dfn[],low ...

  4. RESTFUL Architecture

    Just review some articles about RESTFUL stuff, my understanding is RESTFUL is another more general v ...

  5. 转载:Chrome调试折腾记_(1)调试控制中心快捷键详解!!!

    转载:http://blog.csdn.net/crper/article/details/48098625 大多浏览器的调试功能的启用快捷键都一致…按下F12;还是熟悉的味道;  或者直接 Ctrl ...

  6. java分享第十七天-02(封装操作excel类)

     java解析EXCEL用的是POI的JAR包,兼容EXCEL2003及2007+版本的EXCEL所需要的JAR包:poi-3.8.jarpoi-ooxml.jarpoi-ooxml-schemas. ...

  7. Java 清除数组相同元素

    定义一个函数清除该数组的重复元素,返回一个不能浪费长度的数组.代码如下: import java.util.*; public class demo1 { public static void mai ...

  8. *HDU 1028 母函数

    Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  9. navicat 结合快捷键

    ctrl+q 打开查询窗口ctrl+/ 注释sql语句ctrl+shift +/ 解除注释ctrl+r 运行查询窗口的sql语句ctrl+shift+r 只运行选中的sql语句F6 打开一个mysql ...

  10. MYSQL删除重复数据

     delete from co_jobinformation cwhere c.name in (select cc.name from co_jobinformation cc group by   ...