Topology Shapes of OpenCascade BRep
Topology Shapes of OpenCascade BRep
摘要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
PDF Version: Topology Shapes of OpenCascade BRep
Topology Shapes of OpenCascade BRep的更多相关文章
- Geometry Surface of OpenCascade BRep
Geometry Surface of OpenCascade BRep eryar@163.com 摘要Abstract:几何曲面是参数表示的曲面 ,在边界表示中其数据存在于BRep_TFace中, ...
- Geometry Curve of OpenCascade BRep
Geometry Curve of OpenCascade BRep eryar@163.com 摘要Abstract:几何曲线是参数表示的曲线 ,在边界表示中其数据存在于BRep_TEdge中,BR ...
- OpenCascade BRep Format Description (2)
OpenCascade BRep Format Description eryar@163.com 摘要Abstract:本文结合OpenCascade的BRep格式描述文档和源程序,对BRep格式进 ...
- OpenCascade BRep Format Description
OpenCascade BRep Format Description eryar@163.com 摘要Abstract:本文结合OpenCascade的BRep格式描述文档和源程序,对BRep格式进 ...
- OpenCASCADE BRep Projection
OpenCASCADE BRep Projection eryar@163.com 一网友发邮件问我下图所示的效果如何在OpenCASCADE中实现,我的想法是先构造出螺旋线,再将螺旋线投影到面上. ...
- OpenCASCADE BRep vs. OpenNURBS BRep
OpenCASCADE BRep vs. OpenNURBS BRep eryar@163.com Abstract. BRep short for Boundary Representation. ...
- Representation Data in OpenCascade BRep
Representation Data in OpenCascade BRep eryar@163.com 摘要Abstract:现在的显示器大多数是光栅显示器,即可以看做一个像素的矩阵.在光栅显示器 ...
- Locations Section of OpenCascade BRep
Locations Section of OpenCascade BRep eryar@163.com 摘要Abstract:本文结合OpenCascade的BRep格式描述文档和源程序,对BRep格 ...
- OpenCascade Primitives BRep - Box
OpenCascade Primitives BRep - Box eryar@163.com Abstract. BRep is short for Boundary Representation. ...
随机推荐
- response.sendRedirect的细节
今天敲书上的例子的时候无意间发现,response中的sendRedirect()重定向到另一个servlet时,调用的是doget方法,不明所以,百度得知,原来还牵扯到http协议的细节问题,原文如 ...
- 高德地图API编译警告
版本: V2.1.1 警告内容: (null): warning: (i386) /Users/xiaominghan/Desktop/autonavi/MAMapKit_3D_r923_201310 ...
- 使用HtmlAgilityPack解析Html(非常好用)
/// <summary> /// 设计成一个exe,解决WebBrowser控件内存泄漏的问题. /// </summary> public partial class Ma ...
- Android中的PopupWindow
1.功能 PopupWindow这个类用来实现一个弹出框,可以使用任意布局的View作为其内容,这个弹出框是悬浮在当前activity之上的,可以设置显示位置. 2.需求 弹出软键盘,实现键盘功能从而 ...
- mySQL中删除unique key的语法
CREATE TABLE `good_booked` ( `auto_id` int(10) NOT NULL auto_increment, `good_id` int(11) default ...
- C#中Directory.GetFiles() 函数的使用
C#中Directory.GetFiles(string path , string searchPattern, SearchOption searchOption ) 获取path目录中所有文件 ...
- Main()
P25 “每一个c#可执行文件都必须有一个入口——Main()方法” 我一直对这个Main()方法有一些疑问. 那就是这里头的参数. 在JAVA里,main(String args[])中的参数是绝对 ...
- poj1083
The famous ACM (Advanced Computer Maker) Company has rented a floor of a building whose shape is in ...
- node(websocket)
websocket原本是html5下实现长链接的一个特性,当前已被众多浏览器支持. 在websocket协议中,首先通过http交换一次握手,明确将协议升级至websocket.同时建立一个TCP通道 ...
- Aoite 系列(04) - 强劲的 CommandModel 开发模式(上篇)
Aoite 是一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案.Aoite.CommandModel 是一种开发模式,我把它成为"命令模型",这是一 ...