• OpenCASCADE BRepTools


    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所示:

    wps_clip_image-4070

    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时比较常用:

    //=======================================================================
    //function : Dump
    //purpose  : 
    //=======================================================================
    void  BRepTools::Dump(const TopoDS_Shape& Sh, Standard_OStream& S)
    {
      BRepTools_ShapeSet SS;
      SS.Add(Sh);
      SS.Dump(Sh,S);
      SS.Dump(S);
    }

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

    //=======================================================================
    //function : Add
    //purpose  : 
    //=======================================================================
    Standard_Integer  TopTools_ShapeSet::Add(const TopoDS_Shape& S)
    {
      if (S.IsNull()) return 0;
      myLocations.Add(S.Location());
      TopoDS_Shape S2 = S;
      S2.Location(TopLoc_Location());
      Standard_Integer index = myShapes.FindIndex(S2);
      if (index == 0) {
        AddGeometry(S2);
    
        for (TopoDS_Iterator its(S2,Standard_False,Standard_False);
             its.More(); its.Next())
          Add(its.Value());
        index = myShapes.Add(S2);
      }
      return index;
    }

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

    //=======================================================================
    //function : AddGeometry
    //purpose  : 
    //=======================================================================
    
    void BRepTools_ShapeSet::AddGeometry(const TopoDS_Shape& S)
    {
      // Add the geometry
      
      if (S.ShapeType() == TopAbs_VERTEX) {
        
        Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(S.TShape());
        BRep_ListIteratorOfListOfPointRepresentation itrp(TV->Points());
        
        while (itrp.More()) {
          const Handle(BRep_PointRepresentation)& PR = itrp.Value();
    
          if (PR->IsPointOnCurve()) {
            myCurves.Add(PR->Curve());
          }
    
          else if (PR->IsPointOnCurveOnSurface()) {
            myCurves2d.Add(PR->PCurve());
            mySurfaces.Add(PR->Surface());
          }
    
          else if (PR->IsPointOnSurface()) {
            mySurfaces.Add(PR->Surface());
          }
    
          ChangeLocations().Add(PR->Location());
          itrp.Next();
        }
    
      }
      else if (S.ShapeType() == TopAbs_EDGE) {
    
        // Add the curve geometry
        Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(S.TShape());
        BRep_ListIteratorOfListOfCurveRepresentation itrc(TE->Curves());
    
        while (itrc.More()) {
          const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
          if (CR->IsCurve3D()) {
            if (!CR->Curve3D().IsNull()) {
              myCurves.Add(CR->Curve3D());
              ChangeLocations().Add(CR->Location());
            }
          }
          else if (CR->IsCurveOnSurface()) {
            mySurfaces.Add(CR->Surface());
            myCurves2d.Add(CR->PCurve());
            ChangeLocations().Add(CR->Location());
            if (CR->IsCurveOnClosedSurface())
              myCurves2d.Add(CR->PCurve2());
          }
          else if (CR->IsRegularity()) {
            mySurfaces.Add(CR->Surface());
            ChangeLocations().Add(CR->Location());
            mySurfaces.Add(CR->Surface2());
            ChangeLocations().Add(CR->Location2());
          }
          else if (myWithTriangles) { // for XML Persistence
            if (CR->IsPolygon3D()) {
              if (!CR->Polygon3D().IsNull()) {
                myPolygons3D.Add(CR->Polygon3D());
                ChangeLocations().Add(CR->Location());
              }
            }
            else if (CR->IsPolygonOnTriangulation()) {
              myTriangulations.Add(CR->Triangulation());
              myNodes.Add(CR->PolygonOnTriangulation());
              ChangeLocations().Add(CR->Location());
              if (CR->IsPolygonOnClosedTriangulation())
                myNodes.Add(CR->PolygonOnTriangulation2());
            }
            else if (CR->IsPolygonOnSurface()) {
              mySurfaces.Add(CR->Surface());
              myPolygons2D.Add(CR->Polygon());
              ChangeLocations().Add(CR->Location());
              if (CR->IsPolygonOnClosedSurface())
              myPolygons2D.Add(CR->Polygon2());
            }
          }
          itrc.Next();
        }
      }
    
      else if (S.ShapeType() == TopAbs_FACE) {
    
        // Add the surface geometry
        Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(S.TShape());
        if (!TF->Surface().IsNull())  mySurfaces.Add(TF->Surface());
    
        if (myWithTriangles) { // for XML Persistence
          Handle(Poly_Triangulation) Tr = TF->Triangulation();
          if (!Tr.IsNull()) myTriangulations.Add(Tr);
        }
    
        ChangeLocations().Add(TF->Location());
      }
    }
    由上述代码可知,Edge中的几何信息较多,Face中的几何信息最少,只是几何曲面或其用于显示的网格数据。在将拓朴数据输出时,拓朴面、边及顶点中包含的几何信息都是前面几何数据的编号,即相当于索引号的形式输出,代码如下所示:
    //=======================================================================
    //function : WriteGeometry
    //purpose  : 
    //=======================================================================
    
    void  BRepTools_ShapeSet::WriteGeometry(const TopoDS_Shape& S, 
                                            Standard_OStream&   OS)const 
    {
      // Write the geometry
      
      if (S.ShapeType() == TopAbs_VERTEX) {
    
        // Write the point geometry
        TopoDS_Vertex V = TopoDS::Vertex(S);
        OS << BRep_Tool::Tolerance(V) << "
    ";
        gp_Pnt p = BRep_Tool::Pnt(V);
        OS<<p.X()<<" "<<p.Y()<<" "<<p.Z()<<"
    ";
    
        Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(S.TShape());
        BRep_ListIteratorOfListOfPointRepresentation itrp(TV->Points());
        
        while (itrp.More()) {
          const Handle(BRep_PointRepresentation)& PR = itrp.Value();
    
          OS << PR->Parameter();
          if (PR->IsPointOnCurve()) {
            OS << " 1 " << myCurves.Index(PR->Curve());
          }
    
          else if (PR->IsPointOnCurveOnSurface()) {
            OS << " 2 " <<  myCurves2d.Index(PR->PCurve());
            OS << " " << mySurfaces.Index(PR->Surface());
          }
    
          else if (PR->IsPointOnSurface()) {
            OS << " 3 " << PR->Parameter2() << " ";
            OS << mySurfaces.Index(PR->Surface());
          }
    
          OS << " " << Locations().Index(PR->Location());
          OS << "
    ";
          
          itrp.Next();
        }
        
        OS << "0 0
    "; // end representations
    
      }
    
      else if (S.ShapeType() == TopAbs_EDGE) {
    
        // Write the curve geometry 
    
        Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(S.TShape());
    
        OS << " " << TE->Tolerance() << " ";
        OS << ((TE->SameParameter()) ? 1 : 0) << " ";
        OS << ((TE->SameRange())     ? 1 : 0) << " ";
        OS << ((TE->Degenerated())   ? 1 : 0) << "
    ";
        
        Standard_Real first, last;
        BRep_ListIteratorOfListOfCurveRepresentation itrc = TE->Curves();
        while (itrc.More()) {
          const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
          if (CR->IsCurve3D()) {
            if (!CR->Curve3D().IsNull()) {
              Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itrc.Value());
              GC->Range(first, last);
              OS << "1 ";                               // -1- Curve 3D
              OS << " "<<myCurves.Index(CR->Curve3D());
              OS << " "<<Locations().Index(CR->Location());
              OS << " "<<first<<" "<<last;
              OS << "
    ";
            }
          }
          else if (CR->IsCurveOnSurface()) {
            Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itrc.Value());
            GC->Range(first, last);
            if (!CR->IsCurveOnClosedSurface())
              OS << "2 ";                             // -2- Curve on surf
            else
              OS << "3 ";                             // -3- Curve on closed surf
            OS <<" "<<myCurves2d.Index(CR->PCurve());
            if (CR->IsCurveOnClosedSurface()) {
              OS <<" " << myCurves2d.Index(CR->PCurve2());
              PrintRegularity(CR->Continuity(),OS);
            }
            OS << " " << mySurfaces.Index(CR->Surface());
            OS << " " << Locations().Index(CR->Location());
            OS << " "<<first<<" "<<last;
            OS << "
    ";
    
            // Write UV Points // for XML Persistence higher performance
            if (FormatNb() == 2)
            {
              gp_Pnt2d Pf,Pl;
              if (CR->IsCurveOnClosedSurface()) {
                Handle(BRep_CurveOnClosedSurface) COCS = 
                  Handle(BRep_CurveOnClosedSurface)::DownCast(CR);
                COCS->UVPoints2(Pf,Pl);
              }
              else {
                Handle(BRep_CurveOnSurface) COS = 
                  Handle(BRep_CurveOnSurface)::DownCast(CR);
                COS->UVPoints(Pf,Pl);
              }
              OS << Pf.X() << " " << Pf.Y() << " " << Pl.X() << " " << Pl.Y() << "
    ";
            }
          }
          else if (CR->IsRegularity()) {
            OS << "4 ";                              // -4- Regularity
            PrintRegularity(CR->Continuity(),OS);
            OS << " "<<mySurfaces.Index(CR->Surface());
            OS << " "<<Locations().Index(CR->Location());
            OS << " "<<mySurfaces.Index(CR->Surface2());
            OS << " "<<Locations().Index(CR->Location2());
            OS << "
    ";
          }
    
          else if (myWithTriangles) { // for XML Persistence
            if (CR->IsPolygon3D()) {
              Handle(BRep_Polygon3D) GC = Handle(BRep_Polygon3D)::DownCast(itrc.Value());
              if (!GC->Polygon3D().IsNull()) {
                OS << "5 ";                            // -5- Polygon3D
                OS << " "<<myPolygons3D.FindIndex(CR->Polygon3D());
                OS << " "<<Locations().Index(CR->Location());
                OS << "
    ";
              }
            }
            else if (CR->IsPolygonOnTriangulation()) {
              Handle(BRep_PolygonOnTriangulation) PT = 
                Handle(BRep_PolygonOnTriangulation)::DownCast(itrc.Value());
              if (!CR->IsPolygonOnClosedTriangulation())
                OS << "6 ";                            // -6- Polygon on triangulation
              else
                OS << "7 ";                            // -7- Polygon on closed triangulation
              OS << " " <<  myNodes.FindIndex(PT->PolygonOnTriangulation());
              if (CR->IsPolygonOnClosedTriangulation()) {
                OS << " " << myNodes.FindIndex(PT->PolygonOnTriangulation2());
              }
              OS << " " << myTriangulations.FindIndex(PT->Triangulation());
              OS << " "<<Locations().Index(CR->Location());
              OS << "
    ";
            }
          }
          
          itrc.Next();
        }
        OS << "0
    "; // end of the list of representations
      }
      
      else if (S.ShapeType() == TopAbs_FACE) {
    
        Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(S.TShape());
        const TopoDS_Face& F = TopoDS::Face(S);
    
        if (!(TF->Surface()).IsNull()) {
          OS << ((BRep_Tool::NaturalRestriction(F)) ? 1 : 0);
          OS << " ";
          // Write the surface geometry
          OS << " " <<TF->Tolerance();
          OS << " " <<mySurfaces.Index(TF->Surface());
          OS << " " <<Locations().Index(TF->Location());
          OS << "
    ";
        }
        else //For correct reading of null face
          {
        OS << 0;
        OS << " ";
        OS << " " <<TF->Tolerance();
        OS << " " << 0;
        OS << " " << 0;
        OS << "
    ";
          }
        if (myWithTriangles) { // for XML Persistence
          if (!(TF->Triangulation()).IsNull()) {
            OS << 2;
            OS << " ";
            // Write the triangulation
            OS << " " <<myTriangulations.FindIndex(TF->Triangulation());
          }
        }
      }
      
    }

    通过先将几何数据收集到相应的集合(映射)中,再在拓朴结构对应的地方以索引号的方式输出,这样就便于从文件读取数据时,以类似的方式来重构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

  • 相关阅读:
    MasterPage里使用TreeView保存状态功能
    JavaScript 如何将字符串转换为数值
    asp.net 样式GridView CSS的完整样式表
    CSS Frames LayoutsCSS框架
    Fix: .Net 2.0 or 3.5 Setup Project Requires .Net Framework version 4.0
    Design Pattern Resources
    Agile Method
    The Art of Debugging
    WPF Control Layout
    Getting Started With Setup Projects
  • 原文地址:https://www.cnblogs.com/opencascade/p/4338194.html
Copyright © 2020-2023  润新知