Topology Shapes of OpenCascade BRep

eryar@163.com

摘要Abstract:通过对OpenCascade中的BRep数据的读写,理解边界表示法的概念及实现。理解了拓朴形状的数据结构,就对ModelingData模块有了清晰认识,方便OpenCascade其他模块如ModelingAlgorithms和Visiualization模块的理解。

关键字Key Words:OpenCascade, BRep, Topology, BRep Format

一、引言 Introduction

边界表示(Boundary Representation)也称为BRep表示,它是几何造型中最成熟、无二义的表示法。实体的边界通常是由面的并集表示,而每个面又由它所在曲面的定义加上其边界来表示,面的边界是边的并集,而边又是由点来表示。如下图1.1所示,曲面的汇合处形成曲线,而曲线的汇合处形成点。所以点、线、面是描述一个形状所需要的基本组成单元。

Figure 1.1 BRep Shape demo

边界表示的一个重要特点是描述形状的信息包括几何信息(geometry)和拓朴(topology)信息两个方面。拓朴信息描述形状上的顶点、边、面的连接关系,它形成物体边界表示的“骨架”。形状的几何信息犹如附着在“骨架”上的肌肉。在OpenCascade中,形状的几何信息包含曲线和曲面的参数解析表示Geom_Curve/Geom_Surface。

这样我们就可以用平面方程和柱面方程来描述曲面,用直线或圆弧方程来描述曲线。这时会出现一个问题,即代数表达式只能定义无边界的几何体。除了单个点、圆以及球体,经典的解析几何仅能表示无限延伸的曲线和曲面。为了解决这个问题,边界表示法按下述方法明确地定义曲线或曲面的边界:

l 曲线的边界由位于曲线上的一对点来确定;

l 曲面的边界由位于曲面上的一组曲线来确定;

通过这个方法,就可以定义一段曲线或一片曲面。这时,不同几何元素之间的关系的组织问题就出现了,为此我们将记录如下信息:

l 哪些点界定哪些曲线;

l 哪些曲线界定哪些曲面;

这些关于谁关联谁的信息,就是几何造型系统经常提到的拓朴。在边界表示法中,理论上表示一个物理模型只需要三个拓朴体(顶点TopoDS_Vertex、边TopoDS_Edge和面TopoDS_Face),但在实际应用中,为了提高计算机处理的速度或提供高级的操作功能,还要引入其他一些概念,如环TopoDS_Wire、壳TopoDS_Shell、复合体TopoDS_Compound等。

二、边界表示形状中的几何数据 Geometry of BRep shapes

对形状数据的读写主要是由类BRepTools_ShapeSet来完成的,其中在类的函数AddGeometry中对拓朴形状中的几何数据进行了处理,代码如下所示:

//=================================================================
//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());
}
}

根据上述代码可知,OpenCascade在保存和读写BRep表示的形状时,只保存了顶点、边和面的信息,因为只有这三个拓朴结构中包含了几何信息及显示用的离散点和三角网格数据。有了这些信息,就可以生成一个边界表示的形状了。

几何之间的联系也保存起来了,这也是拓朴数据的一种形式,在下节详细说明。

三、边界表示形状中的拓朴数据 Topology of BRep shapes

关于拓朴顶点TopoDS_Vertex、边TopoDS_Edge、面TopoDS_Face更详细的信息,请参考博客:

l Topology and Geometry in OpenCascade-Vertex;

l Topology and Geometry in OpenCascade-Edge;

l Topology and Geometry in OpenCascade-Face;

l Topology and Geometry in OpenCascade-Topology;

本文只对OpenCascade拓朴结构中的几何数据的关联信息进行分析。

3.1 顶点 TopoDS_Vertex

结合《BRep Format Description White Paper》中对<vertex data>的描述,及程序代码中对顶点数据的读取,分析OpenCascade的BRep表示中的顶点。

Figure 3.1.1 NBF-like definition of Vertex

详细说明:

<vertex data representation u parameter>u的使用方法说明如下:

<vertex data representation data 1> 和参数u定义了三维曲线C上的点V的位置。参数u是曲线C上点V对应的参数:C(u)=V。对应的类是:BRep_PointOnCurve;

<vertex data representation data 2>和参数u定义了曲面上的二维曲线C上点V的位置。参数u是曲线C上点V对应的参数:C(u)=V。对应的类是:BRep_PointOnCurveOnSurface;

<vertex data representation data 3>和参数u及<vertex data representation v parameter>v定义了曲面S上的点V:S(u,v)=V。对应的类是:BRep_PointOnSurface;

在这些类中都将顶点对应的曲线、曲面及其上点的参数都保存起来了。有了这些信息就可以判断与顶点有联系的边或面,因为曲线、曲面属于边和面。

<vertex data tolerance>t定义如下所示:

下面结合程序示例片段,创建一个顶点并将其输出为BRep文件,并在OpenCascade中进行显示。

void TestVertex(void)
{
ofstream dumpFile("vertex.brep"); TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(gp_Pnt(1.0, 2.0, 3.0)); BRepTools::Dump(aVertex, std::cout);
BRepTools::Write(aVertex, dumpFile);
}

当使用BRepTools::Dump时,显示更易读的信息。可将数据dump到屏幕,也可将数据dump到文件;当使用Write时,生成的信息即是BRep文件格式的数据。可以通过Read生成形状,也可直接读入到OpenCascade中显示,如下图3.1.2所示:

Figure 3.1.2 Import a Vertex from brep file

3.2 边 TopoDS_Edge

详细说明:

标志位<edge data same parameter flag>,<edge data same range flag>,<edge data degenerated flag>有特别的用途。

<edge data representation data 1>表示一个三维曲线,对应类:Geom_Curve;

<edge data representation data 2>表示曲面上的一个二维曲线,

对应类Geom_Curve/Geom_Surface;

<curve values for parameter minimal and maximal values>只在2版本中使用;

<edge data representation data 3>表示闭合曲面上的一个二维曲线;

对应类Geom_Curve/Geom_Surface;

<curve values for parameter minimal and maximal values>只在2版本中使用;

<edge data representation data 4>表示Regularity的边,使用到的类有:

Geom_Curve/Geom_Surface;

<edge data representation data 5>表示一个三维的多段线(3D polyline);

对应的类:Poly_Polygon3D,是边的近似表示,主要用来显示;

<edge data representation data 6>表示三角剖分上一条多段线;

对应的类:Poly_PolygonOnTriangulation,也是边在三角剖分上的近似表示;

<edge data tolerance> t的定义如下所示:

下面的示例程序片段将圆的边导出为BRep文件,并在OpenCascade中显示。程序代码如下所示:

void TestEdge(bool bSubdivision = false)
{
ofstream dumpFile("edge.brep"); TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(gp_Circ(gp::XOY(), 6.0)); if (bSubdivision)
{
BRepMesh::Mesh(anEdge, 1.0);
} BRepTools::Dump(anEdge, std::cout);
BRepTools::Write(anEdge, dumpFile);
}

其中参数bSubdivision用来生成显示用的离散多段线数据,这里会生成<edge data representation data 5>的Poly_Polygon3D,将生成的BRep文件导入进行显示如下图所示:

Figure 3.2.1 Import a Face from brep file

3.3 面 TopoDS_Face

详细说明:

<face data>描述了面F的曲面S和三角剖分T。曲面S可能为空:<surface number>=0.

<face data tolerance> t的定义如下所示:

标志位<face data natural restriction flag>有特别的用途。

面中的数据比较简单,有参数表示的曲面的索引号。若曲面已经被三角剖分,将会把剖分后的网格数据也保存起来。下面的示例程序片段将一个球面导出为brep文件:

void TestFace(bool bSubdivision = false)
{
ofstream dumpFile("face.brep"); TopoDS_Face aFace = BRepBuilderAPI_MakeFace(gp_Sphere(gp::XOY(), 6.0)); if (bSubdivision)
{
BRepMesh::Mesh(aFace, 1.0);
} BRepTools::Dump(aFace, std::cout);
BRepTools::Write(aFace, dumpFile);
}

其中参数bSubdivision用来生成显示用的网格数据,这里会生成Poly_Triangulation,将生成的BRep文件导入进行显示如下图所示:

Figure 3.3.1 Import a Face from brep

四、示例程序 Example Code

将上述代码放在一起,完整的程序代码如下所示:

/*
* Copyright (c) 2013 eryar All Rights Reserved.
*
* File : Main.cpp
* Author : eryar@163.com
* Date : 2013-12-21 21:18
* Version : 1.0v
*
* Description : Use BRepTools to dump and write BRep files.
*
* Key Words : OpenCascade, BRep, Vertex, Edge, Face
*
*/ // OpenCascade library.
#define WNT
#include <gp_Pnt.hxx>
#include <gp_Circ.hxx>
#include <gp_Sphere.hxx> #include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx> #include <BRepMesh.hxx>
#include <BRepTools.hxx> #include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx> #pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKBRep.lib")
#pragma comment(lib, "TKMesh.lib")
#pragma comment(lib, "TKTopAlgo.lib") void TestVertex(void)
{
ofstream dumpFile("vertex.brep"); TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(gp_Pnt(1.0, 2.0, 3.0)); BRepTools::Dump(aVertex, std::cout);
BRepTools::Write(aVertex, dumpFile);
} void TestEdge(bool bSubdivision = false)
{
ofstream dumpFile("edge.brep"); TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(gp_Circ(gp::XOY(), 6.0)); if (bSubdivision)
{
BRepMesh::Mesh(anEdge, 1.0);
} BRepTools::Dump(anEdge, std::cout);
BRepTools::Write(anEdge, dumpFile);
} void TestFace(bool bSubdivision = false)
{
ofstream dumpFile("face.brep"); TopoDS_Face aFace = BRepBuilderAPI_MakeFace(gp_Sphere(gp::XOY(), 6.0)); if (bSubdivision)
{
BRepMesh::Mesh(aFace, 1.0);
} BRepTools::Dump(aFace, std::cout);
BRepTools::Write(aFace, dumpFile);
} int main(void)
{
TestVertex(); TestEdge(true); TestFace(true); return ;
}

也可以把更易懂的信息dump出来,这样可以更好地理解brep文件的格式。当将球面导出为brep文件时,会生成很多信息,如下所示:

Shape : , FORWARD

Dump of  TShapes

-----------------

Flags : Free, Modified, Checked, Orientable, Closed, Infinite, Convex

TShape #  : FACE
+
NaturalRestriction
Tolerance : 1e-
- Surface : TShape # : WIRE 01807CE8
- + + - TShape # : EDGE 01808C10
+ -
Tolerance : 1e-
same parametrisation of curves
same range on curves
degenerated
- PCurve : on surface , range : 6.28319
UV Points : , 1.5708 6.28319, 1.5708 TShape # : EDGE 01807AA0
+ -
Tolerance : 1e-
same parametrisation of curves
same range on curves
degenerated
- PCurve : on surface , range : 6.28319
UV Points : , -1.5708 6.28319, -1.5708 TShape # : EDGE 018078C8
+ -
Tolerance : 1e-
same parametrisation of curves
same range on curves
- Curve 3D : , range : -1.5708 1.5708
- PCurve : , (C0) on surface , range : -1.5708 1.5708
UV Points : 6.28319, -1.5708 6.28319, 1.5708
UV Points : , -1.5708 , 1.5708 TShape # : VERTEX 018076F0 Tolerance : 1e-
- Point 3D : 3.67394e-016, , TShape # : VERTEX Tolerance : 1e-
- Point 3D : 3.67394e-016, , - -------
Dump of Curve2ds
------- : Line
Origin :6.28319,
Axis :, : Line
Origin :,
Axis :, : Line
Origin :, -1.5708
Axis :, : Line
Origin :, 1.5708
Axis :, -------
Dump of Curves
------- : Trimmed curve
Parameters : 4.71239 7.85398
Basis curve :
Circle
Center :, ,
Axis :, -,
XAxis :, ,
YAxis :-, ,
Radius : -------
Dump of Polygon3Ds
-------
-------
Dump of PolygonOnTriangulations
------- -------
Dump of surfaces
------- : SphericalSurface
Center :, ,
Axis :, ,
XAxis :, , -
YAxis :-, ,
Radius : -------
Dump of Triangulations
------- -------
Dump of Locations
-------

根据上面的数据,可以很好地理解BRep中拓朴形状的相关数据。大部分数据还是很直观,便于理解的。其中有个数据可能需要解释即PCurve(Parametric Curve),它是在参数(u,v)空间的曲面上的参数曲线。可能有些不好理解,结合程序代码看下PCurve的使用,就会Aha!恍然大悟的:

//=================================================================//function : D0
//purpose :
//=================================================================
void BRep_CurveOnSurface::D0(const Standard_Real U, gp_Pnt& P) const
{
// shoud be D0 NYI
gp_Pnt2d P2d = myPCurve->Value(U);
P = mySurface->Value(P2d.X(),P2d.Y());
P.Transform(myLocation.Transformation());
}

此函数的作用是求PCurve上对应参数u的曲面上的点,即0次微分D0。根据PCurve上的一个参数u,可以求出对应参数u的PCurve上的点,把这个点的x,y分别作为参数曲面的参数u,v,即求出了曲面上的点。

五、结论 Conclusion

通过程序代码将《BRep Format Description White Paper》中数据进行读写,深入理解OpenCascade的边界表示法的数据结构模块ModelingData,为理解其他模块打下基础。

在边界表示法中,理论上表示一个物理模型只需要三个拓朴体(顶点TopoDS_Vertex、边TopoDS_Edge和面TopoDS_Face),所以在对brep文件输出时,只处理了这三种拓朴体的信息。在生成形状时,主要也是处理这三种拓朴体,再根据他们生成其他拓朴体。

顶点、边和面的几何之间的联系在brep中也保存起来了,有了这些信息,就可以判断一个顶点是不是边上的点等。通过示例程序,来理解参数曲线PCurve。

理解了brep表示的结构后,下一步准备来研究下造型算法模块ModelingAlgorithms。

六、参考资料 References

1. BRepTools_ShapeSet.cpp of OpenCascade

2. TopTools_ShapeSet.cpp of OpenCascade

3. BRepTools.cpp Of OpenCascade

4. BRep Format Description White Paper of OpenCascade

5. 孙家广等. 计算机图形学. 清华大学出版社, 2000

6. 詹海生等, 基于ACIS的几何造型技术与系统开发, 清华大学出版社, 2002

Topology Shapes of OpenCascade BRep的更多相关文章

  1. Geometry Surface of OpenCascade BRep

    Geometry Surface of OpenCascade BRep eryar@163.com 摘要Abstract:几何曲面是参数表示的曲面 ,在边界表示中其数据存在于BRep_TFace中, ...

  2. Geometry Curve of OpenCascade BRep

    Geometry Curve of OpenCascade BRep eryar@163.com 摘要Abstract:几何曲线是参数表示的曲线 ,在边界表示中其数据存在于BRep_TEdge中,BR ...

  3. OpenCascade BRep Format Description (2)

    OpenCascade BRep Format Description eryar@163.com 摘要Abstract:本文结合OpenCascade的BRep格式描述文档和源程序,对BRep格式进 ...

  4. OpenCascade BRep Format Description

    OpenCascade BRep Format Description eryar@163.com 摘要Abstract:本文结合OpenCascade的BRep格式描述文档和源程序,对BRep格式进 ...

  5. OpenCASCADE BRep Projection

    OpenCASCADE BRep Projection eryar@163.com 一网友发邮件问我下图所示的效果如何在OpenCASCADE中实现,我的想法是先构造出螺旋线,再将螺旋线投影到面上. ...

  6. OpenCASCADE BRep vs. OpenNURBS BRep

    OpenCASCADE BRep vs. OpenNURBS BRep eryar@163.com Abstract. BRep short for Boundary Representation. ...

  7. Representation Data in OpenCascade BRep

    Representation Data in OpenCascade BRep eryar@163.com 摘要Abstract:现在的显示器大多数是光栅显示器,即可以看做一个像素的矩阵.在光栅显示器 ...

  8. Locations Section of OpenCascade BRep

    Locations Section of OpenCascade BRep eryar@163.com 摘要Abstract:本文结合OpenCascade的BRep格式描述文档和源程序,对BRep格 ...

  9. OpenCascade Primitives BRep - Box

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

随机推荐

  1. c++ STL中的vector与list为什么没有提供find操作?

    map里有,set里也有,vector,list没有,太不公平了吧. 其实应该考虑为什么map,set里有find操作. include<algorithm>里有通用的find操作,通用的 ...

  2. 『TCP/IP详解——卷一:协议』读书笔记——18

    2013-08-27 15:44:52 第7章 Ping程序 7.1 引言 “ping”这个名字来源于声纳定为操作.Ping程序由Mike Muuss编写,目的是为了测试另一台主机是否可达.该程序发送 ...

  3. MATLAB不运行也不报错

    今天本来挺激动找到能运行的好几个程序 MATLAB忙到busy也是停不下来 本来不以为然 结果呢 吃了个水果 一杯水都喝下去了 还没结果(⊙o⊙) 这时候解决办法只有一个 Ctrl+c

  4. Tomcat settings should be set in Tomcat Preference Page解决

    选择tomcat version,然户找到该tomcat的主目录,输入在tomcat home,下面的参数会自动配置,点击apply. 然后在左边选择advanced,同样把tomcat的主目录复制在 ...

  5. LinqToEntity模糊查询的方法选择

    LinqToEntity针对oracle模糊查询 方法:Contains() 转换出来的sql是  like  关键字 方法:IndexOf()  转换出来的sql是  instr()  函数 lik ...

  6. make基础(转)

    1. 基本规则 请点评 除了Hello World这种极简单的程序之外,一般的程序都是由多个源文件编译链接而成的,这些源文件的处理步骤通常用Makefile来管理.Makefile起什么作用呢?我们先 ...

  7. 萝卜白菜,给有所爱——C#和JAVA都会终将被时代淘汰

    看到园子里又有一波试图掀起C#和JAVA的谁更好的争论,对于这些一直不断的争论,我觉得实在没有必要,黑格尔的存在即合理,中国的老古语说的萝卜白菜各有所爱,大家争论的再多其实卵用也没用,还不如趁着闲暇时 ...

  8. SAP HANA企业级培训系列课程<第一部分>

    No. 课程 备注 1 HANA概述 HANA 特点 2 HANA Server & Studio & Client 认识HANA Server \Client\ Studio, 熟悉 ...

  9. [poi2010]Hamsters

    题意:Tz养了一群仓鼠,他们都有英文小写的名字,现在Tz想用一个字母序列来表示他们的名字,只要他们的名字是字母序列中的一个子串就算,出现多次可以重复计算.现在Tz想好了要出现多少个名字,请你求出最短的 ...

  10. 超链接标签a样式生效,取消下划线,文字垂直(上下)居中

    直接设置超链接标签a的属性时并不会生效, 需要将display属性改为inline-block, 即style="display:inline-block" 添加标签a时,默认是有 ...