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. css样式重置,不建议用通配符

    由于各个浏览器对css样式的默认样式不一致,所以有必要进行样式重置.在网上看到很多建议使用 *{margin:0;padding:0} 重置margin和padding.建议不这样子使用,原因主要是性 ...

  2. PHP程序员如何突破技术瓶颈

    身边有几个做PHP开发的朋友,也接触到不少的PHP工程师,他们常疑虑自己将来在技术上的成长与发展,我常给他们一些建议,希望他们能破突自己,有更好的发展. 先明确我所指的PHP工程题,是指毕业工作后,主 ...

  3. maven里的modelVersion

    modelVersion 描述这个POM文件是遵从哪个版本的项目描述符

  4. 设置UIButton或者UILabel显示文字的行数

    需要在UIButton的titleLabel或者UILabel的text 字符串里面添加换行符号 “\n”,并且设置 UILabel的numberOfLines属性 栗子:行数要和“\n”的个数对应, ...

  5. JS实现雪花效果

    演示效果 http://www.9696e.com/demo/snow/ 春节之前新一博客也会一直挂着的. 加载链接 <script src="http://www.9696e.com ...

  6. 关于Android的背景色配色小结

    三基色原理:三基色是指红,绿,蓝三色,人眼对红.绿.蓝最为敏感,大多数的颜色可以通过红.绿.蓝三色按照不同的比例合成产生.同样绝大多数单色光也可以分解成红绿蓝三种色光.这是色度学的最基本原理,即三基色 ...

  7. java jdb命令详解

    jdb - Java debugger 功能描述: 通过简单的命令行程序,对本地或远程jvm进程进行调试. 开启jdb会话: 有多种方式可以开启jdb会话. (1)常见的方式是采用Jdb命令打开一个新 ...

  8. ORACLE 自定义分页存储过程

    一.创建包 CREATE OR REPLACE PACKAGE PKG_JK_LAB_BASIC IS TYPE CURSOR_TYPE IS REF CURSOR; PROCEDURE SP_GET ...

  9. python Scrapy

    由于项目要使用新闻,大量的数据所以想到了python的scrapy 下面大致讲一讲如何安装使用,直到整个新闻采集模块完成,网址什么的自己找 这里只是示范这里的项目环境是python 2.66 cent ...

  10. Python--过滤Mysql慢日志

    ##================================================================## 先来个笑话: 刚交的女朋友让我去他家玩,我觉得空手不好,于是告 ...