Mesh Algorithm in OpenCascade

eryar@163.com

Abstract. Rendering a generic surface is a two steps process: first, computing the points that will form the mesh of the surface and then, send this mesh to 3D API. Use the Triangle to triangulate the parametric space and then lifting map to the model 3D space. This is the main method to visualize the generic shaded surface. This paper show the OpenCascade triangulation of the parametric space and  the map result: mesh in 3D model space. Use the method can visualize a generic surface.

Key words. Delaunay Triangulation, Tessellation, Mesh, OpenCascade, Shaded Surface

1. Introduction

与曲线的可视化算法相比,曲面的可视化要稍微复杂点。总的思路还是很好理解的,那就是把参数空间三角剖分,再将剖分结果映射到三维空间,就得到曲面的网格数据了。

因为B样条曲面的强凸包性,所以可以对其参数空间进行三角剖分,再映射到三维空间。这样可以实现曲面的可视化,但是还有些问题需要处理,如曲面上开孔、曲面离散精度控制等。

因为OpenCascade使用了边界表示法(BRep),所以通过Face,Wire,Edge可以得到曲面的参数范围,若曲面上有开孔,也可通过Edge的PCurve得到开孔在曲面上的参数表示。将得到的参数空间进行三角剖分,再映射到三维空间中,即可对边界表示的形状进行可视化。

用三角网格来逼近实际的形状的精度可以通过增加或减少参数空间中的点来实现。当把参数空间剖分得密,映射到三维空间中的曲面更逼近真实的曲面;当把参数空间剖分得疏,映射到三维空间中的曲面就比较粗糙了。

本文主要将OpenCascade中曲面的参数空间的三角剖分结果显示出来,来分析和理解上述算法。

2. OpenCascade BRep Shape

在OpenCascade中实体的边界表示法(BRep)为:

u COMPSOLID由面共享的SOLID组成;

u SOLID(Cylinder, Cone, Sphere, Torus, etc.)由SHELLS分隔出来的体(Volume);

u SHELL由边Edges相连的FACES组成;

u FACE是一个映射(MAP),从矩形的参数UV空间映射到3D空间。(Cylinder: [0, 2*PI] x[0, H] -> R3,Cone, Sphere, Torus, Bezier Surface, NURBS Surface, etc.)

u FACE的边界由WIRE组成;

u WIRE由相连的EDGES组成;

u EDGE也是一个映射,从一维参数空间U映射到3D空间。(Bezier’s Curve: [0,1] -> R3, NURBS Curve, etc.)

u VERTEX是用来限制EDGE的;

边界表示法(BRep)形成了不同SHAPES(CompSolid, Solid, Shell, Face, Wire, Edge, Vertex)之间的一个图结构(a structure of GRAPH),如下图所示:

Figure 2.1 Shape BRep in OpenCascade

表示上图的的边界表示法形成的树形结构如下图所示。由图可知,有些结构被共享几次。在OpenCascade中使用类TopoDS_Shape来保存这个结构。

Figure 2.2 Graph structure of the BRep Shape

3. How the Mesh is Generated

OpenCascade中可以遍历COMPSOLID不同的子形状。首先,将EDGE离散化,实现的伪代码如下所示:

for (TopExp_Explorer edgeExp(theCompSolid, TopAbs_EDGE);
edgeExp.More();
edgeExp.Next())
{
// The U-interval of the EDGE is subdivided into
// segments with respect to the edge length and
// deflection in 3D-space. By the map, the segments
// of the U-interval give the segments in 3D-Space.
const TopoDS_Edge& theEdge = TopoDS::Edge(edgeExp.Current());
BRepAdaptor_Curve BAC(theEdge); GCPnts_TangentialDeflection thePointsOnCurve;
thePointsOnCurve.Initialize(BAC, aDeflection, cDeflection);
Standard_Real u = 0.0;
gp_Pnt aPoint;
for (Standard_Integer i = ; i <= thePointsOnCurve.NbPoints(); ++i)
{
u = thePointsOnCurve.Parameter(i);
aPoint = thePointsOnCurve.Value(i);
}
}

使用上述算法将每条EDGE离散化,如下图所示:

Figure 3.1 Creation of U-Mesh and 3D-Mesh for each EDGE

当曲面上有开孔时,开孔的信息可以通过WIRE来获得。对于组成开孔的WIRE的每条EDGE,可以通过曲面上的曲线PCurve来将开孔的参数统一到曲面的UV参数空间。实现的伪代码如下所示:

for (TopExp_Explorer faceExp(theCompSolid, TopAbs_FACE);
faceExp.More();
faceExp.Next())
{
for (TopExp_Explorer wireExp(faceExp.Current(), TopAbs_WIRE);
wireExp.More();
wireExp.Next())
{
for (TopExp_Explorer edgeExp(wireExp.Current(), TopAbs_EDGE);
edgeExp.More();
edgeExp.Next())
{
// The U-Mesh of the EDGE is assembled after scaling in the
// UV-domain to constitute the WIRE.
Standard_Real theFirst = 0.0;
Standard_Real theLast = 0.0;
gp_Pnt2d theUV; Handle_Geom2d_Curve thePCurve =
BRep_Tool::CurveOnSurface(theEdge, theFace, theFirst, theLast); theUV = thePCurve.Value(theFirst);
}
}
}

Figure 3.2 Hole in Parametric UV space

将WIRE限制的曲面的参数空间UV进行三角剖分,若其中有开孔的信息,则将形成孔的WIRE内部的三角形去掉。将参数空间的三角剖分映射到三维空间,即可得到曲面的三角剖分网格。如下图所示:

Figure 3.3 Hole in Surface

对组成COMPSOLID的每个FACE进行剖分,最后就得到COMPSOLID的网格。实现的伪代码如下所示:

for (TopExp_Explorer faceExp(theCompSolid, TopAbs_FACE);
faceExp.More();
faceExp.Next())
{
// The 3d-mesh of the FACE is assembled to form the
// boundary of the SOLID.
}

Figure 3.4 Mesh of the Shape

4. Deflection Control

形状通过三角网格来逼近显示,所以当离散精度越高时,显示越逼真,但是产生的数据量大;离散精度越低时,显示越失真,但是产生的数据量小。正如莎翁所说:To be or not to be: that is the question。面对选择时,不走极端,中庸之道也是个不错的解决方法。在显示逼真程度与数据量的大小之间做个平衡,实体三角剖分的算法需要考虑的地方。

在OpenCascade中曲面的三角剖分的网格数据都保存在类Poly_Triangulation中,也包括曲面的参数空间的剖分,参数结点数据是UVNodes。如下代码所示为将曲面的参数空间三角剖分结果可视化:

osg::Geode* BuildUVMesh(const Handle_Poly_Triangulation& theMesh)
{
osg::ref_ptr<osg::Geode> theGeode = new osg::Geode();
osg::ref_ptr<osg::Geometry> theTriangles = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> theVertices = new osg::Vec3Array(); for (Standard_Integer t = ; t <= theMesh->NbTriangles(); ++t)
{
const Poly_Triangle& theTriangle = theMesh->Triangles().Value(t); gp_Pnt2d theUV1 = theMesh->UVNodes().Value(theTriangle());
gp_Pnt2d theUV2 = theMesh->UVNodes().Value(theTriangle());
gp_Pnt2d theUV3 = theMesh->UVNodes().Value(theTriangle()); theVertices->push_back(osg::Vec3(theUV1.X(), 0.0, theUV1.Y()));
theVertices->push_back(osg::Vec3(theUV2.X(), 0.0, theUV2.Y()));
theVertices->push_back(osg::Vec3(theUV3.X(), 0.0, theUV3.Y()));
} theTriangles->setVertexArray(theVertices.get());
  theTriangles->addPrimitiveSet(
   new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, , theVertices->size())); osgUtil::SmoothingVisitor smv;
smv.smooth(*theTriangles); theGeode->addDrawable(theTriangles); return theGeode.release();
}

如下图所示,将球面参数空间的三角剖分显示出来。由球面的参数方程可知其参数空间的范围,U从0到2PI,V从-PI/2到PI/2。

从图中还可以看出,对球面的参数空间进行剖分时,只在V方向加入了一些点,而在U方向没有增加。

Figure 4.1 Triangulation of the Sphere parametric space

当增加离散精度后,显示得更逼真,但产生了更多的网格数据,如下图所示:

Figure 4.2 Triangulation of the Sphere

从上图可知,将参数空间剖分的越细密,显示的效果越逼真。由上图还可知,OpenCascade对球面的参数空间剖分也不是很均匀,有很密集的区域,也是相对稀疏的区域。如果将参数空间均匀剖分,映射到三维空间曲面上时,显示效果也不是很均匀。如下图所示为较理想的球面的剖分网格:

Figure 4.3 Triangulation of the Sphere Generated by Netgen

Figure 4.4 Triangulation of the Sphere

从图中可以看出,将参数空间均匀剖分后,映射到三维空间后,在球面的两个极点处,显示出来有些密集,在轨道线附近,比较稀疏。

同一个曲面,当剖分得密集时,显示得细腻,如下图所示:

Figure 4.5 Triangulation of a Shape by Netgen

在OpenCascade中得到的剖分结果如下图所示:

Figure 4.6 Triangulation of a Shape by OpenCascade

在OpenCascade中只是把边的离散点组成了三角形,没有优化,但是用于显示也还不错,且数据量也很小。当程序要处理的模型很多时,减少三角网格的数量,将会明显提高显示速度。所以在对实体进行网格剖分时,需要根据实际需要,选择折中的,和谐的算法。即若对网格剖分质量要求较高(如用于有限元分析),模型量少,可以将实体剖分得精细;若模型量很大,又对显示速度要求较高,在网格剖分算法中可以选择产生数据量小的算法。

上述形状的渲染模式如下图所示。虽然剖分中也有很多细长的三角形,但当把网格的顶点法向设置正确后,用于显示已经足够。三角形的数量明显要少很多。

Figure 4.7 Shaded mode of the Shape

Figure 4.8 Shaded Mode in OpenCascade

5. Conclusions

将形状中曲面的参数空间三角剖分后,再映射到三维空间即可得到形状的剖分网格。当形状上有开孔时,通过边界表示法,可以得到孔的数据。通过曲面上的曲线PCurve,可将孔与面统一到参数空间进行剖分。

网格的质量与离散精度的控制是个问题。根据需要来对形状进行网格化。当把参数空间均匀剖分时,产生的曲面不一定均匀。所以,也应该存在与曲线离散化类似的算法,即在曲率较大的地方,剖分的密集;在很平的地方,剖分粗。这样来对显示与速度之间做个平衡。

6. References

1. Alain PERRONNET. NEF: A Mesher based on OpenCascade C.A.D software

https://www.ljll.math.upmc.fr/~perronnet/mit/mit.html

2. Kelly Dempski. Focus on Curves and Surfaces. Premier Press 2003

Mesh Algorithm in OpenCascade的更多相关文章

  1. OpenCASCADE PCurve of Topological Face

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

  2. Visualize Surface by Delaunay Triangulator

    Visualize Surface by Delaunay Triangulator eryar@163.com Abstract. Delaunay Triangulation is the cor ...

  3. OpenCASCADE Incremental Mesh

    OpenCASCADE Incremental Mesh eryar@163.com Abstract. OpenCASCADE IncrementalMesh is used to build th ...

  4. Delaunay Triangulation in OpenCascade

    Delaunay Triangulation in OpenCascade eryar@163.com 摘要:本文简要介绍了Delaunay三角剖分的基础理论,并使用OpenCascade的三角剖分算 ...

  5. Surface Normal Averaging

    Surface Normal Averaging eryar@163.com 摘要Abstract:正确设置网格面上点的法向,对几何体在光照等情况下显示得更真实,这样就可以减少顶点数量,提高渲染速度. ...

  6. Open CASCADE Technology(OCCT)概述

    OCCT模块结构图 基础类: Foundation Classes module underlies all other OCCT classes; 模型数据: Modeling Data modul ...

  7. OpenCASCADE Root-Finding Algorithm

    OpenCASCADE Root-Finding Algorithm eryar@163.com Abstract. A root-finding algorithm is a numerical m ...

  8. Mesh Data Structure in OpenCascade

    Mesh Data Structure in OpenCascade eryar@163.com 摘要Abstract:本文对网格数据结构作简要介绍,并结合使用OpenCascade中的数据结构,将网 ...

  9. OpenCascade Sweep Algorithm

    OpenCascade Sweep Algorithm eryar@163.com Abstract. Sweeps are the objects you obtain by sweeping a ...

随机推荐

  1. T-SQL Recipes之Database Backups

    The Problem 在DBA和T-SQL码奴日常工作中,比如常规检查,服务管理,数据库管理, 是其中最具挑战性的一个领域. 在相似任务中,比如索引碎片管理,统计管理,数据库备份是异常重要的,对任何 ...

  2. Lession1 写在机器学习之前

    机器学习从学习方式上来讲,可以分为两类: 监督学习(Supervised Learning),简而言之就是“有标签”学习 无监督学习(Unsupervised Learning),简而言之就是“无标签 ...

  3. 有关iOS系统中调用相机设备实现二维码扫描功能的注意点(3/3)

    今天我们接着聊聊iOS系统实现二维码扫描的其他注意点. 大家还记得前面我们用到的输出数据的类对象吗?AVCaptureMetadataOutput,就是它!如果我们需要实现目前主流APP扫描二维码的功 ...

  4. python小程序

    使用python实现在crt中捕捉出现的异常信息,并统计出现的次数: #$language = "Python" #$interface = "1.0" def ...

  5. Oracle解锁与加锁(HR用户为例)

    SQL*Plus: Release 9.2.0.4.0 - Production on Tue Jul 14 18:12:38 2009   Copyright (c) 1982, 2002, Ora ...

  6. Windows下ADT环境搭建

    1.JDK安装 下载JDK(点我下载),安装成功后在我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量: JAVA_HOME值为C:\Program Files ...

  7. Convert PLY to VTK Using PCL 1.6.0 使用PCL库将PLY格式转为VTK格式

    PLY格式是比较流行的保存点云Point Cloud的格式,可以用MeshLab等软件打开,而VTK是医学图像处理中比较常用的格式,可以使用VTK库和ITK库进行更加复杂的运算处理.我们可以使用Par ...

  8. 纯CSS3制作超级漂亮又实用的加载小图标

    先来一张各种效果的预览图,其实代码并不复杂,关键看自己如何运用. <!doctype html> <head> <meta charset="utf-8&quo ...

  9. java并发编程(十八)阻塞队列和阻塞栈

    阻塞队列 阻塞队列是Java 5并发新特性中的内容,阻塞队列的接口是java.util.concurrent.BlockingQueue,它有多个实现类:ArrayBlockingQueue.Dela ...

  10. Python join()函数

    今天写python 100例时,有个题目是大致是这样的:已知输入形式是1+3+2+1,要求输出形式为1+1+2+3 一开始思路是将输入的字符串用split()函数划分成数组,在对数组进行排序,再用fo ...