Topology and Geometry in OpenCascade-Edge

eryar@163.com

摘要Abstract:本文简要介绍了几何造型中的边界表示法(BRep),并结合程序说明OpenCascade中的边界表示的具体实现,即拓朴与几何的联系。对具有几何信息的拓朴结构顶点(vertex)、边(edge)、面(face)进行了详细说明。本文只对拓朴边数据进行说明,着重介绍了OpenCascade中两个种特别的边缝合边(seam edge)和退化边(degenerated edge)。

关键字Key Words:OpenCascade、BRep、Topology、Edge、Geometry

一、引言 Introduction

边(Edge)是两个邻面(对正则形体而言)或多个邻面(对非正则形体而言)的交集。边有方向,它由起始顶点和终止顶点来界定;边的形状由边的几何信息来表示,可以是直线,也可以是曲线,曲线边可用一系列控制点或型值点来描述,也可以用显示、隐式或参数方程来描述。

边(Edge)是边界表示法中的重要结构,因为边界表示法(BRep)是用形体的边界来描述形体的一种方法。BRep认为形体是由有限数量的边界表面(平面或曲面)构成,而每个表面又由若干边界边与顶点构成,所有的单元面构成了形体的边界,形体的边界将形体和周围的环境分隔开来。

边界表示法不仅详细记录了构成形体的面、边方程的系数和顶点坐标值的几何信息,而且描述了这些几何元素之间的拓朴信息,即体、面、边、顶点的组成关系等。在保证对形体面的定义确定并且无二义性的前提下,它允许根据形体的拓朴结构、面表示的方便性等因素确定一个面是以一个整体表示,还是以几个部分之和进行表示。

在OpenCascade中边包含了一系列的曲线,其结构如下图所示:

Figure 1.1 BRep_TEdge members

其中,包含一系列的曲线由下面几种:

Figure 1.2 BRep_CurveRepresentation class diagram

二、边 Edge

边(edge)是对应于一维对象-曲线的拓朴实体。边可以是面的边界(如长方体的12条边之一);也可以只是一条不属于任何面的“悬空”边(floating edge),想像一下在构建锥形体或扫掠体之前的轮廓线;面的边可以被两个或更多面共享,或者只属于一个面。如下图所示:

Figure 2.1 Model used to illustrate Edge

在上图中用不同的颜色将不同类型的边区别开来:

l 红色:不属于任何面的悬空边(floating edge);

l 绿色:只属于一个面的自由边(free edge);

l 黄色:属于两个或多个面的共享边(shared edge);

边Edge包含几种几何表示:

n 三维空间中的曲线C(t),由Geom_Curve实现。这是边的基本表示方式;

n 曲线P(t)为二维空间的参数曲线,用来表示属于面的边,通常被称为pcurves,由类Geom2d_Curve实现;

n 多段线(Polygonal)由一组三维点表示,且由类Poly_Polygon3D实现。

n 多段线(Polygonal)也可由一组三角剖分面上点的索引来表示,且由类Poly_PolygonOnTriangulation实现。

他们的表示都可以使用前面提到的类BRep_Tool来获取。例如:

Standard_Real aFirst, aLast, aPFirst, aPLast;
Handle(Geom_Curve) aCurve3d = BRep_Tool::Curve (anEdge, aFirst, aLast);
Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface (anEdge, aFace, aPFirst, aPLast);

边必须有曲面上的参数曲线(pcurves),除了平面以外。边中所有曲线必须一致,即朝向相同。这样边上的点可以使用任意表示方式计算得到,如曲线C(t),可以用[first, last]区间上的t来计算;也可根据u在区间[first1, last1]上取得曲面S1(P1x(u), P1y(u))上的点Pi,这里Pi是曲面Si上的参数曲线pcurve上的一点。

1. 边的标志位 Edge Flags 

边中的标志位有三种:

static const Standard_Integer ParameterMask       = ;
static const Standard_Integer RangeMask = ;
static const Standard_Integer DegeneratedMask = ;

这里对前两种标志位进行说明:

l RangeMask “same range”:(BRep_Tool::SameRange())取值区间相同,即几何表示的曲线参数取值区间相同;

l ParameterMask “same parameter”:(BRep_Tool::SameParameter())参数相同,即当C(t)=S1(P1x(t), P1y(t))时,对于同样的参数t,C(t)和曲面S1上的点P1(t)相同。即任何边上的点都对应参数曲线上相同的参数值。

许多算法假定设置了这两个标志位,因此建议你注意这种情况,一定要设置这些标志位。

2. 边的容差 Tolerance 

边的容差(Tolerance)是其三维曲线和其他任何表示方式之间的最大偏差。其几何意义就是以容差为半径沿边的一个包含边的三维曲线及其他任何形式表示的管子。如下图所示:

Figure 2.2 Edge Tolerance

3. 特殊类型的边 Special edge types 

在OpenCascade有两种特别类型的边,他们是:

l 缝合边(seam edge):即在同一个面上出现两次的边(如:在同一个面上具有2个参数曲线);

l 退化边(degenerated edge):这种边位于曲面的奇异点处,在三维空间中退化为一个点;

球面中这两种类型的边都有。缝合边位于经线(U iso-lines),参数为0和2*PI。退化边位于南北极点,对应于纬线(V iso-lines),参数为-PI/2和PI/2。因为球面的参数方程为:

当参数u取0和2*PI时,球面的参数方程计算如下:

从计算结果可以看出,缝合边是位于Dx和Dz所在平面上的半圆弧。

当参数v取-PI/2和PI/2时,球面的参数方程计算如下:

从计算结果可以看出,曲面上的两个边分别退化为两个点。即v取-PI/2和PI/2时球面的两个退化边分别位于南北极点上。如下图所示:

Figure 2.3 seam edge and degenerated edge of sphere

另外例子:环形体(torus)、圆柱体(cylinder)、圆锥体(cone)。环形体torus有两条缝合边(seam edge),对应于它的参数空间的边界;圆柱体(cylinder)有一条缝合边(seam edge)。圆锥(cone)顶点处为退化边(degenerated edge)。

检查边是否是缝化边或退化边,可以使用函数BRep_Tool::IsClosed()和BRep_Tool::Degenerated()。

4. 边的朝向 

边的朝向为正向(forward edge orientation)意味着边的逻辑方向与曲线的方向相同。反向(reversed)意味着逻辑方向与曲线方向相反。所以,缝合边(seam-edge)在一个面中总是有两个朝向:一个反向(reversed),一个正向(forward)。

三、示例程序 Example Code 

以边界表示BRep表示的球面为例,说明其边的类型。程序代码如下所示:

/*
* Copyright (c) 2013 eryar All Rights Reserved.
*
* File : Main.cpp
* Author : eryar@163.com
* Date : 2013-08-24 16:11
* Version : 1.0v
*
* Description : Demonstrate seam edge and degenerated edge of sphere.
*
*/ #include <iostream> // OpenCascade Library.
#define WNT
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepPrimAPI_MakeSphere.hxx> #pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKBRep.lib")
#pragma comment(lib, "TKPrim.lib")
#pragma comment(lib, "TKTopAlgo.lib") /**
* @breif Dump orientation types.
* Orientation definitaion:
* enum TopAbs_Orientation { * TopAbs_FORWARD, * TopAbs_REVERSED, * TopAbs_INTERNAL, * TopAbs_EXTERNAL * };
*/
std::string dumpOrientation(const TopAbs_Orientation& orient)
{
std::string strType; switch (orient)
{
case TopAbs_FORWARD:
strType = "TopAbs_FORWARD";
break; case TopAbs_REVERSED:
strType = "TopAbs_REVERSED";
break; case TopAbs_INTERNAL:
strType = "TopAbs_INTERNAL";
break; case TopAbs_EXTERNAL:
strType = "TopAbs_EXTERNAL";
break;
} return strType;
} /**
* @breif Dump edge information.
*/
void processEdge(const TopoDS_Edge& edge, const TopoDS_Face& face)
{
Standard_Real dTolerance = BRep_Tool::Tolerance(edge); Standard_Boolean bIsGeometric = BRep_Tool::IsGeometric(edge);
Standard_Boolean bIsSameParameter = BRep_Tool::SameParameter(edge);
Standard_Boolean bIsSameRange = BRep_Tool::SameRange(edge);
Standard_Boolean bIsDegenerated = BRep_Tool::Degenerated(edge);
Standard_Boolean bIsClosed = BRep_Tool::IsClosed(edge, face); TopAbs_Orientation nOrientation = edge.Orientation(); // Dump edge info.
std::cout<<"====== Edge Info ======="<<std::endl;
std::cout<<"Tolerance: "<<dTolerance<<std::endl;
std::cout<<"Orientation: "<<dumpOrientation(nOrientation)<<std::endl;
std::cout<<"Geometric: "<<(bIsGeometric?"True":"False")<<std::endl;
std::cout<<"Same Parameter: "<<(bIsSameParameter?"True":"False")<<std::endl;
std::cout<<"Same Range: "<<(bIsSameRange? "True":"False")<<std::endl;
std::cout<<"Degenerated edge: "<<(bIsDegenerated?"True":"False")<<std::endl;
std::cout<<"Seam edge: "<<(bIsClosed? "True":"False")<<std::endl; // Dump vertex of the edge.
for (TopExp_Explorer vertexItr(edge, TopAbs_VERTEX);
vertexItr.More();
vertexItr.Next())
{
const TopoDS_Vertex& aVertex = TopoDS::Vertex(vertexItr.Current());
gp_Pnt pnt = BRep_Tool::Pnt(aVertex); std::cout<<"Vertex: ("<<pnt.X()<<", "<<pnt.Y()<<", "<<pnt.Z()<<")"<<std::endl;
}
} int main(void)
{
Standard_Integer nSphereFaceCount = ;
Standard_Integer nSphereEdgeCount = ; TopoDS_Shape sphere = BRepPrimAPI_MakeSphere(1.0); for (TopExp_Explorer faceItr(sphere, TopAbs_FACE);
faceItr.More();
faceItr.Next())
{
const TopoDS_Face& aFace = TopoDS::Face(faceItr.Current()); ++nSphereFaceCount; for (TopExp_Explorer edgeItr(aFace, TopAbs_EDGE);
edgeItr.More();
edgeItr.Next())
{
const TopoDS_Edge& aEdge = TopoDS::Edge(edgeItr.Current()); processEdge(aEdge, aFace); ++nSphereEdgeCount;
}
} std::cout<<"Sphere face count: "<<nSphereFaceCount<<std::endl;
std::cout<<"Sphere edge count: "<<nSphereEdgeCount<<std::endl; return ;
}

程序运行结果如下所示:

  ====== Edge Info =======
  Tolerance: 1e-
  Orientation: TopAbs_REVERSED
  Geometric: True
  Same Parameter: True
  Same Range: True
  Degenerated edge: True
  Seam edge: False
  Vertex: (6.12323e-017, -1.49976e-032, )
  Vertex: (6.12323e-017, -1.49976e-032, )
  ====== Edge Info =======
  Tolerance: 1e-
  Orientation: TopAbs_FORWARD
  Geometric: True
  Same Parameter: True
  Same Range: True
  Degenerated edge: False
  Seam edge: True
  Vertex: (6.12323e-017, -1.49976e-032, )
  Vertex: (6.12323e-017, -1.49976e-032, -)
  ====== Edge Info =======
  Tolerance: 1e-
  Orientation: TopAbs_FORWARD
  Geometric: True
  Same Parameter: True
  Same Range: True
  Degenerated edge: True
  Seam edge: False
  Vertex: (6.12323e-017, -1.49976e-032, -)
  Vertex: (6.12323e-017, -1.49976e-032, -)
  ====== Edge Info =======
  Tolerance: 1e-
  Orientation: TopAbs_REVERSED
  Geometric: True
  Same Parameter: True
  Same Range: True
  Degenerated edge: False
  Seam edge: True
  Vertex: (6.12323e-017, -1.49976e-032, )
  Vertex: (6.12323e-017, -1.49976e-032, -)
  Sphere face count:
  Sphere edge count:
  Press any key to continue . . .

从运行结果可以看,当球的边为退化边时,边的两个顶点的坐标值相同。退化边位于球的南北极点上。缝合边为连接两个退化边的曲线。

根据遍历顺序,

第一条边为退化边(degenerated edge),其朝向为反向(reversed);

第二条边为缝合边(seam-edge),其朝向为正向(forward);

第三条边为退化边,其朝向为正向(forward);

第四条边为缝合边,其朝向为反向(reversed)。

由上可见,缝合边有两个朝向,一个正向一个反向。

四、结论 Conclusion 

对与几何相关的拓朴边(edge)的类的属性数据进行详细说明。并结合程序代码详细说明边的标志位(myFlags)属性的意义,从参数方程出发,理解缝合边(seam-edge)和退化边(degenerated edge),即标志位中DegeneratedMask的意义。

五、参考资料 

1. Roman Lygin, OpenCascade notes, opencascade.blogspot.com

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

3. OpenCascade source code.

Topology and Geometry in OpenCascade-Edge的更多相关文章

  1. Topology and Geometry in OpenCascade-Adapters

    Topology and Geometry in OpenCascade-Adapters eryar@163.com 摘要Abstract:本文简要介绍了适配器模式(adapter pattern) ...

  2. Topology and Geometry in OpenCascade-Face

    Topology and Geometry in OpenCascade-Face eryar@163.com 摘要Abstract:本文简要介绍了几何造型中的边界表示法(BRep),并结合程序说明O ...

  3. Topology and Geometry in OpenCascade-Topology

    Topology and Geometry in OpenCascade-Topology eryar@163.com 摘要Abstract:本文简要介绍了几何造型中的边界表示法(BRep),并结合程 ...

  4. Topology and Geometry in OpenCascade-Vertex

    Topology and Geometry in OpenCascade-Vertex eryar@163.com 摘要Abstract:本文简要介绍了几何造型中的边界表示法(BRep),并结合程序说 ...

  5. Topology Shapes of OpenCascade BRep

    Topology Shapes of OpenCascade BRep eryar@163.com 摘要Abstract:通过对OpenCascade中的BRep数据的读写,理解边界表示法的概念及实现 ...

  6. Geometry Surface of OpenCascade BRep

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

  7. Geometry Curve of OpenCascade BRep

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

  8. OpenCASCADE PCurve of Topological Face

    OpenCASCADE PCurve of Topological Face eryar@163.com Abstract. OpenCASCADE provides a class BRepBuil ...

  9. OpenCASCADE BRepTools

    OpenCASCADE BRepTools eryar@163.com Abstract. OpenCASCADE BRepTools provides utilities for BRep data ...

随机推荐

  1. 游戏Loading中的小提示和Loading动画实现

    学习unity1年多了,工作也1年了,因为工作需要,有几个月没接触unity Ngui啦. 学的还是不踏实.继续努力吧.由于下周就要进行新游戏的开发,这几天熟悉熟悉NGUI,今天按照现在公司以前的项目 ...

  2. MYSQL删除表的记录后如何使ID从1开始

    MYSQL删除表的记录后如何使ID从1开始 MYSQL删除表的记录后如何使ID从1开始 http://hi.baidu.com/289766516/blog/item/a3f85500556e2c09 ...

  3. leetcode sort List

    Sort a linked list in O(n log n) time using constant space complexity. /** * Definition for singly-l ...

  4. 重拾java之路之webservice

         Web service平台是一套标准,它定义了应用程序如何在Web上实现互操作性.你可以用任何你喜欢的语言,在任何你喜欢的平台上写Web service ,只要我们可以通过Web servi ...

  5. Visual Studio2013(Update4)无法生成依赖项关系图解决方案

    今天为了看别人写的一套框架,就琢磨着有没视图的方式去看别人每个类和方法之间的调用和继承关系.这个时候发现了一个VS2013自带的功能: 带着兴奋的心情小手一抖一点... 我等呀等,等呀等.... 尼玛 ...

  6. go json null字段的转换

    最近试了试go中对json null字段进行转换,代码如下: struct 转 json: package main import ( "encoding/json" " ...

  7. ASP.NET MVC 学习笔记(一)

    很久很久没有在博客园写过东西了,很多大虾也说过展示自己最好的地方就是有一个博客作为笔记,展示一下自己的学习和研究成果. 最近决心将公司的一款产品改用MVC的方式实现,于是乎就开始在园子里面疯狂的寻找各 ...

  8. 开始VS 2012 中LightSwitch系列的第1部分:表中有什么?描述你的数据

    [原文发表地址]  Beginning LightSwitch in VS 2012 Part 1: What’s in a Table? Describing Your Data [原文发表时间]  ...

  9. mongodb(map-reduce)

    下例中给出mongoose的一个mapreduce例子,参考mongoose官网. 基本概念: Map函数 接受一个键值对(key-value pair),产生一组中间键值对.MapReduce框架会 ...

  10. 图解集合2:LinkedList

    初识LinkedList 上一篇中讲解了ArrayList,本篇文章讲解一下LinkedList的实现. LinkedList是基于链表实现的,所以先讲解一下什么是链表.链表原先是C/C++的概念,是 ...