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. oracle高阶知识点

    ------------------------------------------------- varchar2(4000)字符型,最大长度不能超过4000,与char的区别是不用空格补足 num ...

  2. 使用github与jekyll搭建个人博客(一)

    虽然使用博客园还没有多久,但是最近看到一些大神的博客觉得很是炫酷.于是突发奇想,想要搭建自己的博客站点儿.编程菜鸟一枚,还是想要记录下最近的搭建博客经历. 使用github搭建个人博客的方式有很多,百 ...

  3. js二级导航下拉菜单

    <!DOCTYPE html> <html> <head> <title>导航列表</title> <meta http-equiv= ...

  4. [MySQL][Spider][VP]Spider-3.1 VP-1.0 发布

    我很高兴的宣布 Spider 存储引擎 3.1 Beta 版本和垂直分区存储引擎 1.0 Beta 版本发布了. Spider 是数据库拆分的存储引擎: http://spiderformysql.c ...

  5. HTML5之Canvas时钟(网页效果--每日一更)

    今天,带来的是使用HTML5中Canvas标签实现的动态时钟效果. 话不多说,先看效果:亲,请点击这里 众所周知,Canvas标签是HTML5中的灵魂,HTML5 Canvas是屏幕上的一个由Java ...

  6. MySQL数据丢失讨论

    原文地址:http://hatemysql.com/tag/sync_binlog/ 1.  概述 很多企业选择MySQL都会担心它的数据丢失问题,从而选择Oracle,但是其实并不十分清楚什么情况下 ...

  7. 用DirectX实现魔方(三)视角变换及缩放(附源码)

    在本系列第一篇介绍过鼠标按键的功能,如下. 左键拖拽 - 旋转魔方 右键拖拽 - 变换视角 滚轮 - 缩放魔方 今天研究一下如何实现后面两个功能,用到的技术主要是Arcball,Arcball是实现M ...

  8. 230行实现一个简单的MVVM

    作者:mirone链接:https://zhuanlan.zhihu.com/p/24451202来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. MVVM这两年在前端届 ...

  9. iOS给图片添加滤镜&使用openGLES动态渲染图片

    给图片增加滤镜有这两种方式: CoreImage / openGLES 下面先说明如何使用CoreImage给图片添加滤镜, 主要为以下步骤: #1.导入CIImage格式的原始图片 #2.创建CIF ...

  10. MySQL 5.7新特性之Generated Column(函数索引)

    MySQL 5.7引入了Generated Column,这篇文章简单地介绍了Generated Column的使用方法和注意事项,为读者了解MySQL 5.7提供一个快速的.完整的教程.这篇文章围绕 ...