tetgen手册

更新时间:2024-04-04 18:54:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Tetgen 可以用来产生四面体网并且遵守格德洛内规则,四面体网格对有限元和有限体积法是非常有用的。这个算法在当前研究领域具有领先水平。文档简洁的介绍了一些可以被tetgen解决的问题,是一个非常详细用户指南。读者从中不仅可以了解到怎样直接使用来自命令行的输入文件去产生四面体网格,而且还可以了解其他程序怎样调用tetgen

关键词:四面体网格,Delaunay四面体化,有约束的Delaunay四面体化,网格质量,网格产生

内容 1、 介绍

1.1 Delaunay三角形与空间多面体 1.2 有约束的Delaunay四面体化 1.2.1 分段线性复杂 1.3 四面体网格质量

1.3.1 半径边缘比质量衡量标准

2、 入门指南 2.1 编译

2.1.1 unix/linux

2.1.2 windows 9x/NT/2000/xp

2.2 测试 2.3 可视化 2.3.1 tetview 2.3.2 其他的网格可视化工具 3、 Tetgen使用 3.1 命令行语法 3.2 命令行开关

3.2.1 –p 对一个PLC进行四面体化 3.2.2 -q 网格生成质量 3.2.3 -a 规定有限元 3.2.2 -A 分配区域属性 3.2.2 -r 重构或优化网格 3.2.2 -i 插入一个点 3.2.2 -T 设置公差

3.2.2 -Y 边界禁止steiner点 3.2.2 其他开关命令

3.3 命令行举例 3.3.1 产生Delaunay四面体 3.3.2 产生带约束的Delaunay四面体 3.3.3 网格质量、网格大小控制 4、 文件格式

4.1 tetgen文件格式 4.1.1 .nodes文件

4.1.2 .poly文件 4.1.3 .smeshs文件 4.1.4 .ele文件 4.1.5 .face文件 4.1.6 .edges文件 4.1.7 .vol文件 4.1.8 .var文

4.1.9 .neigh文件

4.2 支持文件格式

4.2.1 .off 4.2.2 .ply 4.2.3 .stl 4.2.4 .mesh

4.3 文件格式举例 4.3.1 带两个边界标识的空间多面体 4.3.2 带两个区域的空间多面体 5、 其他程序调用tetgen

5.1 头文件

5.2 调用方法

5.3 tetgenio数据类型 5.4 数据描述 5.4.1 内存管理 5.4.2 facet数据结构 5.5 举例

一些相关的扩展 引用

1、 介绍

Tetgen 程序可以对三维物体进行四面体剖分。Tetgen的目的是为数值模拟产生合适的四面体网格,其中数值模拟有用到有限元和有限体积法。不仅如此,tetgen作为一个四面体网格生成器,它在许多科学与工程应用中也常被用来作为一个网格化组件。

对于一个三维区域 ,它是由它的边界定义的(如表面网格文件)。Tetgen可以对这样一个有边界约束的区域进行四面体剖分,并且符合delaunay规则和网格质量标准。后者是恰好是线变,并且对产生的所有四面体的外接球半径与其最小边的比率是有限制的。对于一个三维域点集,tetgen可以对其进行delaunay四面体剖分,并且产生凸壳。

Tetgen是的代码是用C++写的, 这些代码可以被编译成直接执行的程序或者是集成到其他应用程序的库。Tetgen支持所有主流的操作系统,比如unix/linux,macos,windows系列等。

tetgen

使用的算法符合delaunay准则。这一章节的其他内容对用tetgen解决的网格问题作了一些简单

描述,对Tetgen的算法实现也作了一些描述,有兴趣的读者参考文档给出的引用。然而,这些信息并不是对所有用户都真正有用,除了章节1.2.1和1.3.1,其他的部分浏览一下就可以了,章节1.2.1和1.3.1包含了一些解决问题的要点。

点集的三角网划分(区别对待概念simplicial complex与simplex)

三角形是基本的几何图形结构。点集V的一个三角形划分就是一个simplicial complex ,这里称之为S,S包含

的点可能只是点集V的一部分点,也可能是V的全部点,并且这里S的底部空间就是V的convex hull。对于一个点集,在它上面有许多不同的三角形划分,但毫无疑问,德洛内三角形划分是最好的一种。它的dual是点集的Voronoi图。德洛内三角形划分与Voronoi图有许多非常好的数学特性。它们在许多应用中被广泛使用。

1.1 Delaunay三角剖分法(点集的三角剖分)和凸壳

点集的Delaunay三角形剖分法由Delaunay在1934年提出,它的许多有利的特性使得它成为一个非常有用的几何结构,它已经在高效的算法设计与实际的工程应用中被广泛应用。

附录部分用来描述Delaunay三角剖分法,用户理解一些基本概念是非常有必要的,像凸壳,单形,

单复形等。附录A提供了对这些基本概念简单的介绍

假设V是 ?d 中的一个点集, σ是点集V中的一个k -simplex (0 ≤ k ≤ d)。这个σ的外接球包含了σ上所有点。如果 K=d,σ有一个唯一的外接球,否则的话,σ就有无限的外接球。如果σ存在一个外接球,并且这个外接球没有包含点集V的其他顶点,这个simplex就是一个Delaunay。图1a展现了一个二维空间点集的delaunay simplices。

如果所有的simplices都是德洛内型,那么点集V的一个德洛内三角形划分(称之为D)就是一个simplicial complex ,并且D的底部空间为点集V的convex hull。三维的德洛内三角形划分也叫德洛内四面体剖分。

1.2 约束Delaunay四面体剖分法

约束德洛内四面体剖分就是把一个三维区域Ω划分成一个四面体网格,正如在表面网格呈现出来的边界? Ω,总体来说,Ω可能在形状上是反复无常的变化,而且还很复杂,可能包含内边界(分割成不同的区域)和洞。这个问题也被称为边界网格生成或者边界整合。

顶点集Ω的德洛内四面体剖分法没有必要符合这个? Ω,由于? Ω的面是非德洛内simplices(面片)。而约束德洛内四面体剖分法是一种变异的德洛内四面体剖分法,它需要遵守? Ω规则。约束德洛内四面体剖分法(CDT)保持着德洛内四面体剖分法的许多特性。对于解决这类问题它们是再合适不过的结构了。

为了简化一个算法的设计,我们可以假定认为? Ω是一个三维空间多面体,也就是? Ω是一个二维底层空间的单纯复形simplical complex。更具体的说,? Ω是一个三维空间顶点集和是一个多边形集。每一个多边形是一个带段边界约束的小平面。Tetgen使用了一个更通用的方法来表示? Ω,它将在章节1.2.1分开介绍。 下面关于CDT的定义是来源于shewchuk。

点集V中的两个顶点p和q是可见的,但如果有一个约束的平面f,并且点p和q位于这个平面f的相反两边,pq之间的线段交叉与平面f(见图5),那么顶点p与q将变得不可见。由点集V的顶点形成的四面体t就是一个约束德洛内四面体,当然前提是它的外接球没有包含V的其他顶点,四面体t内的任何顶点都是可见的。

像这样一个Ω空间的四面体T剖分被称作是约束四面体剖分 ,如果四面体T和空间Ω恰好有相同的顶点

集,空间Ω的每一个多边形完全被四面体T的三角形面的集合所代替。

T是? Ω的四面体剖分,如果T是一个约束的四面体剖分并且T的每一个四面体都是约束德洛内四面体。 直观地,对于约束德洛内四面体来说,德洛内四面体剖分和约束德洛内四面体剖分的定义是一样的,当球

穿过一个约束的多边形时我们忽略了这个球队体积。注意在一个约束德洛内四面体剖分中,那些单形(四面体、三角形、边)并不总是德洛内型的

构造一个德洛内四面体剖分是一种微妙的方式。一些多面体根本不能四面体剖分。图6中展示了两个例子。

此外,ruppert和serdel展示了它是一个非完全多项式去决定一个简单的多面体是否能够被四面体剖分。尽管如此,每一个多面体是否能够被四面体剖分的条件是只要有额外的点被插入。德洛内四面体剖分算法是插入另外的顶点。当这些额外顶点是必须存在的时候,一个关键的问题是怎么样决定额外插入点的最佳数目。另一个要考虑的是,网格优化算法是怎么样去避免短边,这些短边将给非常小的四面体带来危险,因此,这些额外插入点的数目不应该太大。对于约束四面体网格剖分法来说,基于不同点插入方案的29,32,36,37,41方法是被提倡的。

Shewchuk给出了一个条件确保四面体网格剖分的存在性,它对设计一个算法去构造四面体网格剖分法是

非常有用。因为每一个空间多面体的多边形都是有分割边界的。一个要考虑的就是空间多面体所有的片段集。如果存在一个段s的外接球S,且没有多面体顶点集的其他顶点位于外接球S中,这个段s就是德洛内型。此外,如果没有空间中的其他顶点位于外接球内或位于外接球上,段s就是一个强德洛内型,并且这个空间多面体的德洛内四面体剖分就存在。这个条件是非常有用的,因为它表明额外的点唯一被插入到片段中。

Tetgen算法的实现是被si和gartner给出的。这个算法扩展了在41中提出的片段恢复算法。这个算法和其

他的约束德洛内四面体剖分[29,30,41]的主要区别是它实际的可利用性,一个强德洛内四面体剖分法的存在条件是它要求一个空间多面体顶点集没有局部的德洛内型。一个新的局部德洛内移除算法把顶点扰动和顶点插

入结合起来构造一个新的顶点集,这个顶点集合空间多面体是一致的。在这个条件满足之后,一个实际的快速面片恢复算法用来构造这个德洛内四面体剖分。图7展示了二维模型中这个算法的主要思想。

1.2.1分段线性复杂

三维几何体对象一般是比多面体更复杂的。Tetgen库用一个非常广泛的输入叫做piecewise linear complex

(PLC),PLC是由miller,talmor,teng,walkington和wang定义的。一个PLC X是一个顶点,段,和小平面的的集合。每一个小平面都是多边形区域,在它里面它可能有许多面,也可能是非凸壳,可能还有洞,段,和顶点。一个小平面能够代表任何二维的笔直线性图形,这是一个非常流行的输入模型,许多二维网格算法使用都是这种模型。一个小平面实际上是一个二维的笔直线性图嵌入到三维中。图8给出了一个例子,阴影区域高亮了这个面。

PLCs像其他复合体一样是有限制的。对于像X PLC,X的元素在内部区域里必须的闭合的。例如,两个分

段只有在一个共同的顶点集并且这些点也是在X中才能交叉。X的两个面片只有在共享一个片段或者是一个顶点集或者是两个的集合时才可以相交。(因为小平面是非凸的)。图9展示了非闭合的配置的例子。

PLCs的小平面的另一个限制是这些被用来定义小平面的顶点集必须是共面的。

任何多面体都可以认为是一个PLC。此外,PLCs在表示三维集合体对象时比空间多面体更灵活。例如,图

8 的阴影面不能用任何的多边形来表示。对于一些有弯曲面的区域来说,这个表面三角形化在先前就是要求的,因此,PLCs差不多能够表示任何三维区域。

1.3 四面体网格质量

Tetgen产生了一个四面体网格对于解决由有限元法和有限元体积法定义的偏微分方程 不等式是非常有用的。

问题是怎么样去产生一个四面体网格,这个产生四面体网格要遵守给出的域(空间多面体或者是PLC),而

且这个域包含大小和网格元素形状的确切约束。它是验证产生的网格质量的一个典型问题。这个网格生成质量检验技术提供了形状与大小来保证这个网格:

所有的元素都一个确切的质量衡量标准,并且这个元素的数目是在最小数目的常量因子之内。

解决网格生成质量的方法包括octree,advancing front,和德洛内方法。德洛内优化,一个德洛内四面体

化是被迭代增加的顶点改善了。这些顶点的布置是被选中去迫使边界整合,并且提高网格的质量。德洛内优化已经成功应用到相应的二维问题。这些算法能够在chew和ruppert的作品中被找到。然而,在三维区域中这些算法不能移除这些裂片(非常扁平,几乎退化了四面体)。

Tetgen处理这个问题实现的算法是来自shewchuk的德洛内优化算法。对于三维来说它是一个泛化的ruppert算法。在三维空间中给出一系列的顶点,约束段和小平面,以及不少于90度的输入角,这个算法能够产生一个半径边缘比列不大于2.0的德洛内四面体网格质量。在短距离上四面体从小到大是分等级的。这个算法产生的网格普遍胜过这理论界,并且在消除有最小或最大二面角的四面体时是非常有效的。

除了四面体临近的最小输入角,这个裂片是最坏形状四面体在进行德洛内优化后唯一还存在的类型。现

在已经有几种技术能够从网格中删除裂片。Tetgen做了一个简单的裂片消除步骤。裂片能够通过一些局部的翻转操作消除,或者从边界剥离。这个策略在删除大部分的裂片是非常有效的,单不能保证把所有的都消除。在将来上面提到的一些方法是值得去实现。

1.3.1 半径边缘比质量衡量标准

在著作中有一些质量衡量标准是可以利用的。这一部分从它的算法实现介绍了tetgen使用的质量衡量方法。 一般来说,对于一些精确的有限元建模,元素的形状有边界纵横比是有必要的。一个元素的纵横比是最大边长度和最小高度的比列。对于判断这个网格划分的质量来说,值当然是越小越好。例如“瘦与扁平”的四面体趋向有一个大的纵横比。

一个类似的但是较弱的网格划分质量评价依据是半径边缘比,它是miller,talmor,teng,walkington和wang提出的。一个四面体t有一个唯一的外接球。我们令R=R(t)为半径,L=L(t)为最短边的长度。这个四面体的半径边缘比Q=Q(t)是:

半径边缘比用来衡量这个四面体的质量。对于所有质量好的四面体来说,这个值是小的(见图10),但对于大部分形状不好的四面体来说,这个值比较大(见图11)。因此,在一衡量一个网格划分的质量时,这个值应该是越小越好。然而,这个比例是被这个规则的四面体最小化了,也就算说:

一种划分形状比较糟糕的四面体特殊情况是这个裂片(见图12),它是非常扁平并且差不多快退化了。裂片的半径边缘比能够小至到0.707.此时这个半径边缘比作为衡量裂片的依据已经不合适了。然而,miller,talmor,teng,walkington,和wang 已经指出对于分析这个德洛内优化算法来说它仍然是最自然和优雅的依据。

Q=R/L

Q >=

2、 入门指南

Tetgen的最新版本是可以从 ——————————————下载。Tetgen的发布版本在它的源代码中已有说明(用C++写的),它在使用时需要先被编译。这个代码具有高度可移植性,只需要支持标准的C++库即可。编译环境为主流的32为或64位系统。章节2.1会介绍怎么在unix/linux和windows系统中把tetgen编译成一个可执行程序。

当你获取这个可执行文件时,你可以用它包含的例子测试一下tetgen,下面是这个教程。

Tetgen没有图形用户接口。Tetview程序可以显示tetgen的输入输出文件。当然,还有一些其他比较流行

的网格显示器,详细可以看章节2.3。

2.1 编译

下载的内容应该包含下列文件

Readme License

说明

版权说明

tetgen库头文件

Tengen.h Tetgen.cxx

tetgen库C++源代码 几何谓词C++源代码

Predicates.cxx

Makefile 编译tetgenmakefile文件 Example.poly 一个实例数据文件

文件predicates.cxx是一个shewchuk型的精确几何谓词文件(c++版本)。

要编译tetgen,系统应该用C++编译器,在unix/linux上可以用G++,在windows系统上可以用microsoftC++或者是BorlandC++。Tetgen可以编译成一个可执行程序或者是一个可以嵌入到其他程序的库。

2.1.2 unix/linux

编译tetgen最容易的方法是编辑和使用它包含的makefile文件。在编译之前,把所有的源文件和makefile放到一个目录下。可以读一下这个makefile,它描述了一些用户选项,然后你可以根据这些选项编辑它。你应该设置你的C++编译器和优化层次。当你做完这些之后,输入make命令把tetgen编译成一个可执行程序或者输入make tetlib命令把tetgen编译成一个库。编译后会在同一个目录下产生可执行文件tetgen和库文件libtet.a

二者你可以选择其中一个方式,这些文件在没有makefile的情况下通常也很容易编译。只要你会用G++,

首先你可以先编译这个predicates.cxx文件生成一个对象文件:

g++ -c predicates.cxx

把tetgen编译成一个可执行文件的命令如下:

g++ -O -o tetgen tetgen.cxx predicates.o –lm 把tetgen编译成库文件的命令如下:

g++ -O -DTETLIBRARY -c tetgen.cxx ar r libtet.a tetgen.o predicates.o

2.1.2 windows9x/NT/2000/xp

在win32系统,tetgen可以编译成控制台程序tetgen.exe或者编译成一个库tetgen.lib。这个已经用microsoft visual C++6.0做过测试。编译tetgen最容易的方法就是用VC++的集成开发环境。 建立tetgen.exe的步骤:

建立一个名为tetgen的win32控制台程序 把所有源文件添加到工程中

编译工程

建立tetgen库的步骤:

建立一个名为library的win32 static library 把所有源文件添加到工程中 添加tetlibrary符号到编译开关中 编译工程

2.2 测试

如果没有参数的话,Tetgen会给出一个简短的命令行选项列表。-h选项表示打印出使用方法。 Tetgen –h

这个封装的示例文件,example.poly,是一个简单的三维分段线性复合体。用tetgen实验一下: Tetgen –p example

Tetgen将会读入这个复合体,然后把它的约束德洛内四面体剖分结果写入到文件example.1.node,example.1.ele,和example.1.face,文件内容分别是网格顶点列表,四面体列表和边界面列表。Tetgen典型的输出文件如下:

Opening example.poly.

Constructing Delaunay tetrahedralization. Delaunay seconds: 0.02 Creating surface mesh. Perturbing vertices. Delaunizing segments. Constraining facets.

Segment and facet seconds: 0.02 Removing unwanted tetrahedra. Hole seconds: 0

Repairing degenerate tets. Steiner seconds: 0

Writing example.1.node. Writing example.1.ele. Writing example.1.face. Output seconds: 0

Total running seconds: 0.04 Statistics:

Input points: 54 Input facets: 29 Input holes: 0 Input regions: 0 Mesh points: 79

Mesh tetrahedra: 188 Mesh faces: 453 Mesh subfaces: 154 Mesh subsegments: 106

如果需要获取这个复合体四面体网格质量,可以输入以下命令: Tetgen -pq example

这个结果正如之前一样结果输出在上面提到的三个文件中。但是这一次,它有四面体网格质量限制,这些四

面体有外接圆半径与最短边比,比列限制为2.0。现在开始运行: Tetgen -pq1.414V example

Tetgen将再一次产生网格质量,此时将比之前包含更多的点,并且所有有半径边缘比的四面体其比例限定为1.414。另外,tetgen打印出了一个大概的网格质量报告(由于使用了-V开关)。它看出来如下:

Mesh quality statistics:

Smallest volume: 0.0085019 | Largest volume: 115.27 Shortest edge: 0.30902 | Longest edge: 15.287

Smallest dihedral: 5.0167 | Largest dihedral: 169.2909 Radius-edge ratio histogram: < 0.707 : 6 | 1.6 - 1.8 : 130 0.707 - 1 : 238 | 1.8 - 2 : 64 1 - 1.1 : 85 | 2 - 2.5 : 0 1.1 - 1.2 : 94 | 2.5 - 3 : 0 1.2 - 1.4 : 222 | 3 - 10 : 0 1.4 - 1.6 : 145 | 10 - : 0

(A tetrahedron’s radius-edge ratio is its radius of circumsphere divided by its shortest edge length) Aspect ratio histogram:

1.1547 - 1.5 : 0 | 15 - 25 : 13 1.5-2 : 0 | 25-50 : 3 2 - 2.5 : 0 | 50 - 100 : 0 2.5 - 3 : 10 | 100 - 300 : 0 3 - 4 : 209 | 300 - 1000 : 0 4 - 6 : 607 | 1000 - 10000 : 0 6 - 10 : 115 | 10000 - 100000 : 0 10 - 15 : 27 | 100000 - : 0

(A tetrahedron’s aspect ratio is its longest edge length divided by the diameter of its inscribed sphere) Dihedral angle histogram:

0 - 5 degrees: 0 | 90 - 100 degrees: 310 5 - 10 degrees: 25 | 100 - 110 degrees: 206 10 - 30 degrees: 340 | 110 - 120 degrees: 173 30 - 40 degrees: 263 | 120 - 130 degrees: 100 40 - 50 degrees: 251 | 130 - 140 degrees: 46 50 - 60 degrees: 100 | 140 - 150 degrees: 23 60 - 70 degrees: 5 | 150 - 170 degrees: 43 70 - 80 degrees: 4 | 170 - 175 degrees: 0 19

80 - 90 degrees: 79 | 175 - 180 degrees: 0

如果要计算这个PLC点集的德洛内四面体剖分和凸壳,输入一下命令: cp example.poly example.node tetgen example

德洛内四面体保存在example.1.node 和 example.1.ele文件中。凸壳是被文件example.1.face中三角形列表代表。所有的网格和德洛内四面体都能够在下一节介绍中的程序中显示出来。 章节3和4 是关于命令行的开关和文件格式的详细描述

2.3 可视化 2.3.1 tetview

Tetview是用来显示复合体和简单化网格的图形接口。它是特意为tetgen创造的,它能够读入tetgen的输入和

输出文件并且显示这个对象。它也显示了一些其他的信息,像边界类型和材质。这个交互式图形用户接口允许用户通过鼠标或键盘轻易地操作这个显示对象。Tetview也可以将当前窗口的内容保存到高质量格式的文件。 Tetview是一款免费软件,你可以找到不同平台上的编译可执行的版本。在你的系统上下载一个相适应的即可。 如果要显示example.poly PLC,首先把tetview的可执行文件复制到到你的文件目录中,输入如下命令,它将自动载入:

tetview example.poly

下面的命令将显示文件example.1.node,example.1.ele, and example.1.face中网格。 tetview example.1

tetview的使用说明可以在以上网站中找到

2.3.2 其他的网格显示器

其他两个程序可以被选择用来显示由tetgen生成的网格,并且都是免费可用和运行在主流 操作系统上。他们是:

Medit,一个界面非常友好的网格显示器 Gid

在用medit显示网格时,在命令行添加 –g开关。Tetgen将另外输出一个网格文件,它只能直接被medit读入和渲染。命令如下:

Tetgen -pg example.poly medit example.1

通过在命令行开启-g开关,tetgen将会产生另外两个额外的文件。它们分别是四面体网格文件和表面网格文件。这些文件能够被Gid显示。

3.使用tetgen

这个章节描述了tetgen作为一个标准独立程序的使用方法。它被命令行的开关选项集和输入文件调用。开关用来设置控制tetgen的行为,并且设置输出文件格式。依据不同的的开关选项,tetgen将会产生德洛内四面体剖分,或者是边界约束的德洛内四面体剖分,或者是是网格质量。

3.1 命令行语法

运行tetgen的命令行语法如下:

tetgen [-pq__a__AriYMS__T__dzjo_fe ngG OJBN EFIC QVvh ] input_file

下划线表明选项后面可以跟数值,也可以不跟。在选项和数字参数之间不要留空格。章节3.2将介绍这些开关选项。

输入文件可以是不同的文件,这取决你用的参数选项。如果没有使用命令行参数的话,那么输入文件必

须要用后缀名为.node的文件格式,这类文件包含一个三维的顶点列表。结果是将产生这个点集的德洛内四面体剖分。

如果使用了命令函参数p,输入文件的后缀名必须为.poly, .smesh, .off, .stl, 或者是.mesh。这些文件描述的

是一个复合体(或者表面网格),运行后将会产生这类对象的边界约束德洛内四面体剖分。如果同时使用了pq参数,那么运行后会生成符合用户质量要求的四面体网格。

如果使用了参数r,那么程序会读入一个已经存在的四面体网格。这里你必须同时提供.node 和 .ele 文

件,它们共同描述了一个四面体网格,当然 .node与 .face 或者.node与 .vol 的文件组合都可以,此时的输入文件参数可以不带后缀名。

如果使用命令行参数q,这个网格将会依据这个新的网格质量和变量限制进行优化。 章节4描述了文件格式。

3.2 命令行选项

下面对每一个选项作了简单的描述。直接输入命令tetgen时将会显示这些信息。 -p Tetrahedralizes a piecewise linear complex (.poly or .smesh file). 四面体剖分一个PLC网格文件,文件后缀名须为.poly or .smesh

-q Quality mesh generation. A minimum radius-edge ratio may be specified (default 2.0). 网格质量控制参数,主要设置最小半径边缘比(默认为2) -a Applies a maximum tetrahedron volume constraint. 控制产生四面体的最大体积

-A Assigns attributes to identify tetrahedra in certain regions. 为产生的四面体分配属性用来辨别其所在区域

-r Reconstructs and Refines a previously generated mesh. 重构和优化之前产生的网格文件

-Y Suppresses boundary facet s/segments splitting. 控制边界面/段分割

-i Inserts a list of additional points into mesh. 插入一系列额外的点到网格中 -M Does not merge coplanar facets. 不用合并共面的facets

-T Set a tolerance for coplanar test (default 1e-8). 为共面测试设置极限值

-d Detect intersections of PLC facets. 检测PLC facets的交集

-z Numbers all output items starting from zero. 所有输出项的数字都是从0开始

-o2 Generates second-order subparametric elements. -f Outputs faces (including non-boundary faces) to .face file. 输出面(包含非边界面)到.face文件 -e Outputs subsegments to .edge file. 输出子段到.edge文件

-n Outputs tetrahedra neighbors to .neigh file. -g Outputs mesh to .mesh file for viewing by Medit. -G Outputs mesh to .msh file for viewing by Gid. -O Outputs mesh to .off file for viewing by Geomview. -J No jettison of unused vertices from output .node file. -B Suppresses output of boundary information. 控制边界信息的输出

-N Suppresses output of .node file. 控制.node文件的输出

-E Suppresses output of .ele file. 控制.ele文件的输出

-F Suppresses output of .face file. 控制.face文件的输出

-I Suppresses mesh iteration numbers. 控制网格迭代数目

-C Checks the consistency of the final mesh. 检查最终网格的一致性

-Q Quiet: No terminal output except errors.

-V Verbose: Detailed information, more terminal output. -v Prints the version information.

-h Help: A brief instruction for using TetGen.

Table 1: Overview of TetGen’s command line switches

3.2.1 –p 四面体剖分一个PLC

-p 选项表示读入文件中的PLC,文件后缀名可以为.poly or .smesh,并且产生这个PLC的约束德洛内四面

体剖分。

约束德洛内四面体剖分可能有一些特别的点被添加到这个PLC的输入边界。如果你不想有顶点被添加到

这个边界上,你可以使用选项-Y。

如果没有设置文件扩展名,tetgen将自动寻找扩展名为.poly or .smesh的文件,并且选择其中一个可以使

用的文件。例如,“tetgen -p xxx” 是打开名为xxx.poly的文件,如果这个文件不存在的话,就会打开名xxx.smesh的文件,也有可能打开xxx.node;在整个PLC中读数据,产生一个约束的德洛内四面体剖分并且把结果保存到xxx.1.node, xxx.1.ele, and xxx.1.face.三个文件中。

其他格式的的多边形文件也可以用来作为输入文件。Tetgen根据扩展名来辨认文件格式。Tetgen支持下

面的文件格式:.off, .ply, .stl, and .mesh.

Tetgen调用时如果同时使用了-q和-a,将会产生这个PLC的四面体网格质量。-p和-r不能同时使用。

3.2.2 -q 网格质量生成

选项-q是用shewchuk的德洛内优化算法来控制生成网格的质量。它添加顶点到约束的德洛内四面体剖分(和-p一起使用)或者是先前产生的四面体网格(和-r一起使用),以确保每个四面体的半径边缘比小于2.0。用户可以在-q后加上数值来设置最小半径边缘比。对于太小的比列,比如比1.0还小的话,tetgen可能不会终止。

如果PLC的输入角度或者是输入的二面角没有小于60度的,这个算法将保证终止,并且没有四面体的半径边缘会大于2.0。实际上,用户是能够观察到半径边缘比降至1.414或者更小时的成功终止。 下面是一些使用-q的例子。可以测试一下,然后和包含的例子文件比较一下: Tetgen -pq example tetgen tetgen

3.2.3 -a 强加有限元体积

-a 可以对所有的四面体强加一个最大的体积约束。在a后面跟一个数值,表示产生的四面体的体积都应

-rq1.414 example.1 -ra0.5

example.2

该小于这个数值。

如果没有设置最大体积,也没有使用选项r,tetgen将读入后缀名为.poly or .smesh的区域部分。.poly file

or .smesh file能够有选择地为每个有小平面限制的区域包含一个有限约束,从而用更多的设置方式来从控制PLC在四面体剖分时产生的四面体密度。

用户可以通过调用-a 两次来为一些区域强加一个固定的体积约束和一个变化的体积约束,一次带数值,

一次不带数值。每一个体积设置的数值可以包含小数点。

如果没有设置数值,也没有使用r选项,那么.vol 文件中可以为每一个四面体包含不同的体积约束。它对

基于后验误差估计的优化有限元和有限元网格是非常有用的。

3.2.4 –A 分配区域属性

-A 选项表示为每一个四面体分配额外的属性(一个整数),表明每一个四面体属于哪一个方面有界区域。分配给区域的属性是保存在.poly or .smesh 文件中,如果一个区域在两个文件中没有被明确地标识,那么这个区域中的四面体将被自动是分配为0属性。

如果你想tetgen自动给一个区域中的每个四面体分配属性,即使这个区域没有在.poly和.smesh文件中分

配属性,那么你可以使用选项 –A两次(比如-AA)。在你的网格输出中,同一个区域的所有四面体将获得非0值。默认值是一些1,2,3等数字。如果当前属性被使用,它将跳过并将使用下一个可以使用的属性。

3.2.5 -r 重构/优化网格

选项 –r 用来重构先前生成的网格。网格可以从.node and .ele file, .face file读入。如果.face文件存在,它将被读入并且使用网格中的约束表面,否则的话tetgen将会自动标识这些表面,内部表面也通过比较两个相邻的四面体属性来标识。字段将从其存在的表面自动标识。 重构的网格和原来的网格是通过不同的迭代数值来区别。

例如,“tetgen -r xxx.1”表示可能是从xxx.1.node,xxx.1.ele或者是xxx.1.face, xxx.1.edge文件中读入网格,当然前提是这些文件已存在;然后重构这个网格;然后再把结果输出到

xxx.2.node,xxx.2.ele,xxx.2.face文件中。现在xxx.2就能够作为上面命令的输入文件,其输出结果是另一个网格,并且保存在xxx.3.node 等文件中。网格迭代数量允许用户创建一系列质量越来越好的网格。

用户可以通过把使用 –r 和-q ,-a, -i选项结合起来来优化网格。下面是几种可能的方法: -A选项只有在-p使用并且-r不使用时才有效。

用户可以使用-q选项并且带一个较小的数值来实施更严格的质量约束,也可以使用-a选项并在其后面加上一个比之前优化网格时更小的有限元。

用户可以创建一个.vol文件,为每一个四面体设置最大有限元,并使用-a选项(后面不带数值)。每一个四面体的有限元约束都被应用到对应的四面体上。

用户可以创建一个.node文件。文件包含一个插入到网格中的额外顶点列表。可以使用-i去通知tetgen有一些额外的顶点需要插入。

-r 不能同 –p 和 –I 同时使用。

3.2.6 -i插入另外顶点

-i 选项表示插入一些另外的顶点到德洛内四面体剖分中(使用-p),或者是先前产生的网格中(使用-r)。这些

插入的顶点是从来源于xxx-a.node文件,xxx代表输入文件的文件名,当然其后缀名可以为.poly or .smesh, or .ele。这个选项在用用户定义的顶点优化有限元或者是有限元网格时是非常有用的。下面是几个你需要注意的要点:

位于网格域外面的顶点将被tetgen忽略

网格在插入一些点后可能不是约束德洛内型或不再遵守德洛内型。然而,通过与-q选项一起使用,tetgen将自动添加一些额外的点以确保网格的符合德洛内型的特性。

3.2.7 –T 设置公差

选项 –T 用来设置用户定义的公差,这个公差在tetgen多次计算都将用到,默认值是1e——8.

原则上,用来定义一个PLC的小平面的顶点集应该是恰好是共面的,但实际上由于在计算机用的中浮点

数格式不一致的原因导致它是非常困难的。

Tetgen可以接受顶点不是太确切但近于共面的小平面。只有这个v/l3的比列是小于给出的公差就可以认为

a,b,c,d是共面的。这里v和l分别四面体abcd的体积和平均边的长度。

3.2.8 -Y 边界上禁止施耐泰点

选项 –Y表示禁止在外部边界产生施耐泰点。内部施耐泰点仍然可以产生。

当要求网格边界必须保持一致能够与一些相邻的网格相符合时,这个选项就非常有用。 用户可以使用-YY以保护所有边界分裂,当然也包括内部边界。

为了提高网格质量,用户可以同时使用-Y和-q,tetgen可以这样使用,不过可能使产生的网格包含的四面体质量较差。然而,如果先前所有的边界划分很合理并且有非常紧凑的间隔补丁的话,它还是会产生较好想效果 3.2.9 其他选项

-I -I选项没有用到内部的迭代次数,它禁止输出.node文件,所有你的输入文件不会被覆盖。-r选项也不能用,因为那样会覆盖你的输入文件.ele。如果用户使用.node文件作为输入的话,像-q,-a,-s,or –t这些选项就不能使用,因为没有.node文件可以写,所有没有添加的施耐泰顶点的任何记录。

-z -z选项表示所有输出项目的数值都是从0开始。在从其他程序调用tetgen的情况下这个选项是非常有用。

-o2 如果使用了-o2这个选项的话,tetgen将使用二次元产生网格。二次元每个元素有10个节点,而不是4根据这些输入的顶点集选择一个合适的公差经常有助于减少这个插入点的数目和提高网格质量。

.

这个可选的第四个部分列出了区域的属性(分配给一个区域中的所有四面体)和关于最大四面体体积的区域约束。在调用tetgen时如果使用了参数-A后者-a并且没有带数值,那么Tetgen将读入这个区域。对于洞来说,区域属性和体积约束以同样的方式传播。

如果在x,y,z坐标所在行后面写了两个值,这个形式tetgen会将它们前者当作一个区域属性(只有选

项-A开启才能使用),并且后者会被认为是一个区域体积约束(只有在-a被使用的时候才有用)。读入在坐标后面只使用一个值也是可能的,此时它既被当作区域属性也被当作体积约束,最终是哪个还得看调用了哪个参数。一个负的最大体积约束允许使用-A和-a而不用在这个特殊的区域内强加一个体积约束。

下面是.poly文件中的格式,它描述了一个立方体。

# Part 1 - node list

# node count, 3 dim, no attribute, no boundary marker 8300

# Node index, node coordinates 1 0.0 0.0 0.0 2 1.0 0.0 0.0 3 1.0 1.0 0.0 4 0.0 1.0 0.0 5 0.0 0.0 1.0 6 1.0 0.0 1.0 7 1.0 1.0 1.0 8 0.0 1.0 1.0

# Part 2 - facet list

# facet count, no boundary marker 60

# facets

1 # 1 polygon, no hole, no boundary marker 4 1234 # front 1

4 5678 # back 1

4 1265 # bottom 1

4 2376 # right 1

4 3487 #top 1

4 4158 # left # Part 3 - hole list 0 # no hole

# Part 4 - region list 0 # no region

4.1.3 .smesh files

.smesh文件代表一个PLC的特殊类型——网格表面。.smesh文件格式是.poly文件格式的简化版。每一面只有一个确切的多边形,没有洞,没有段和内部点。它没有.poly文件的格式灵活,但是当网格表面是由其他程序调用创建时更简单、更有用。

和.poly文件格式一样,.smesh文件格式也是由四部分组成,分别是点,面,洞,和区域。其中只有关于

面部分的描述和.poly文件是不一样的。它的描述如下:

Part 2 面列表

One line: <# of facets> Following lines list # of facets:

<# of corners> ... [boundary marker]

...

每一个面只由一个确切的多边形组成。每一个多边形的角列表位于同一行。每一个面的可选边界标识符

在是角列表的结尾给出来的。

下面的例子示例了单位立方体面部分的布局。(图17)

# Part 2 - facet list

# facet count, no boundary marker 60

# facets

4 1234 # front 4 5678 # back 4 1265 # bottom 4 2376 # right 4 3487 #top 4 4158 # left

4.1.4 ele文件格式如下:

第一行三个数字分别对应变量:

Numberoftetrahedra numberofcorners numberoftetrahedronattributes 四面体个数 每个四面体顶点个数

四面体属性个数

接下来是四面体列表:

四面体编号 节点1 节点2 节点3 节点4 [可选项四面体属性]

ele文件包含一个四面体列表。每一个四面体有四个角(如果-o2选项开启的话可能是10个角)。节点是对应于的.node文件中。第一次四个节点是角点。如果使用了选项-o2,剩下的六个节点为位于四面体六条边上的中点。图18展示了节点的数目。

如果第一行的区域属性为1,每一个四面弹在最后一列会另外有一个区域属性。四面体的区域属性主要是

用来做为识别哪些四面体和PLC的面约束区域相关的标记。它是位于.poly或者是.smesh文件的第四部分。区域属性没有分散面,同一个区域的所有四面体仍然是有相同的区域属性。区域属性最广泛的用途是决定四面体是哪一个材质。

如果tetgen产生一个网格或者是四面体剖分,.ele文件是默认的输出文件。然而,使用-E选项可以忽略。

如果使用了-r选项,tetgen会读入.ele文件,并且会依据它重构一个四面体网格。下面的例子说明了ele文件的布局。

154 4 0 1 4 107 3 50 2 4 108 3 107 3 9 97 95 94 4 4 107 50 93 5 56 1 50 47 6 94989795 7 97 9 95 55 85255551 ...

4.1.5 face文件格式

第一行两个数字分别标识face(三角形面)的个数与三角形标识符列表(1为非空0为空) 接下来是三角形列表:

face 文件包含一系列的三角形面列表,这些面可能是边界面(使用了选项-P或者是-r),可能是凸壳面。每一个面有三个角,可能还有边界标识符。节点索与.node 文件里一致。

三角形编号

顶点1 顶点2 顶点3 face标识符

在产生一个网格或者是德洛内四面体剖分后,tetgen默认是把边界面或者是凸壳输出到 .face文件。然而,

这个文件可以通过-F来忽略。如果使用了-r选项,tetgen也可以读入.face文件来识别在重构网格中的边界面。-B选项可以用来禁止边界标识符的可选列。

如果在第一行的边界标识符为1,每一个面在最后一列有一个另外的边界标识符。面的边界标识符是

由.poly 和.smesh文件定义的。它们主要是用来识别哪些四面体剖分面和哪一个PLC面相关的标记。其最广泛的使用是决定哪儿为不同的边界条件。

4.1.6 .edge文件

First line: <# of edges>

Remaining lines list # of edges: ...

.edge file包含边的列表,这些边是PLC的段或者是字段。每一条边有两条终端节点,索引对应于.node文件中相应的点。 它是tetgen的输出部分(使用-e选项)。

4.1.7 .vol files

First line: <# of tetrahedra>

Remaining lines list # of maximum volumes: ...

.vol文件与每一个四面体的最大体积相关,最大体积是用于优化网格的。在使用-r选项时,tetgen将会读入此文件。

和其他的文件格式一样,每一个四面体必须有编号,并且是连续编号的。如果给一个四面体分配一个符的

最大体积,四面体可能是没有约束的。

4.1.8 .var files

One line: <# of facet constraints>

Remaining lines list # of facet constraints:

...

One line: <# of segment constraints>

Remaining lines list # of segment constraints:

...

Var 文件允许你对面和段设置可变的约束。像对一个区域设置最大体积一样,每一面都可以有最大面积限制。在输出中,子表面的面积都小于之前的对应平面面积限制。同样地,每一个段都有最大长度限制,因此,这个段的字段将不会比它长。

设定面的面约束是通过设置边界标识符,面边界标识符是一个整数,分布在面对应的.poly或.smesh文件

中。设定一个段的段约束是通过设置段的两个终点索引。

下面的例子说明了.var文件的布局。它可以和包含的example.poly文件一起使用。

# Facet constraints 1 # 1 constraint

1 2 0.5 # Set maximum area constraint (0.5) on all facets # having boundary marker 2. # Segment constraints 10 # 10 constraints

1 32 33 0.05 # Set maximum edge length constraint (0.05) on # segment with endpoints 32 and 33. 2 33 34 0.05 3 34 35 0.05 4 35 36 0.05 5 36 37 0.05 6 37 38 0.05 7 38 39 0.05 8 39 40 0.05 9 40 41 0.05 10 41 42 0.05

4.1.9 .neigh files

First line: <# of tetrahedra> <# of nei. per tet. (always 4)> Following lines list # of neighbors:

...

.neigh文件和每一个四面体相邻的四面体有关,索引对应的四面体在.ele 文件中。 索引为-1时标识四面体没有相邻的四面体(此时四面体位于网格域的外界)。四面体i的第一个邻居与四面体i的第一个角是相反的。当使用-n选项时,tetgen会输出这个文件。

4.2 支持的文件格式

Tetgen也支持一些多面体文件格式。表3列出了支持的文件格式。Tetgen通过文件扩展名来识别这些文件。 4.2.1 .off files

Off文件一种综述文件格式,它是一个为unix/linux系统开发的交互式三维图形显示器。它包含可能共顶点的共面多边形集,它是一种描述多面体非常方便的方式。多面体可能是凹形的但没有规定多面体一定包含洞。

对于off文件格式在描述可以在网上查到。下面是对这种文件格式的一个简单描述。

provisionOFF numVertices numFaces numEdges xyz xyz

... numVertices like above NVertices v1 v2 v3 ... vN MVertices v1 v2 v3 ... vM ... numFaces like above

注意这个顶点编号是从0开始的,边也是从0开始编号的。

4.2.2 .ply files

Ply文件格式是一个简单的对象描述,为了方便那些与多边形模型打交道的研究人员,它被设计为一种简单格式。这种文件格式的早期版本是用于斯坦福大学和北卡教堂。

和例子中描述一样,PLY文件格式的代码可以从http://astronomy.swin.e du.a u/~p bour ke/ geom form ats/ ply

下载。

4.2.3 stl文件

Stl或stereolithography格式是一个用于制造业的ASCII或者是二进制文件。它包含了一个三角形表面的列表,并且描述了计算机产生的固体模型。对于大多数快速原型机来说这是一个非常标准的输入文件。

Stl文件格式描述能够在网上许多地方找到,可以参考http://www.sdsc.edu/tmf/ Stl- spe cs/stl.html 。下面

是一个例子。

solid ...

facet normal 0.00 0.00 1.00 outer loop

vertex 2.00 2.00 0.00 vertex -1.00 1.00 0.00 vertex 0.00 -1.00 0.00 endloop endfacet ...

Endsolid

4.2.4 .mesh文件

.mesh是编辑一个交互式三维网格显示程序的的文件格式,可以参考http://www.ann.jussieu.fr/~ fre y/lo gici els/ medi t.h tml。在medit文档中有关于这个文件格式的描述。

用户可以http://www- rocq1.inria.fr/ gamm a .免费下载这种文件格式的3D模型。

4.3 文件格式例子

这一节提供了两个例子。他们是用来支持交互式学习。关于PLCs的焦点是通过命令行来使用tetgen.poly文件格式和构造不同的网格质量标准。

4.3.1 有两个边界标识符的PLC

图19展示了一个矩形条的几何图形。这个bar由八个顶点和六个面组成(面都是矩形)。另外,三是两个边界标识符(-1和-2)分别于最左边和最右边的面相关。这个简单的物理模型有它简单物理意义。它可以被看作为一个简单的热量转移问题。这个任务是计算bar的温度扩散,热量从bar热的一边传到冷的一边。两个边界标识符代表不要的边界条件,一个是高温一个是低温。下面这个bar.poly输入文件描述了这个bar:

# Part 1 - the node list.

# A bar with 8 nodes in 3D, no attributes, no boundary marker. 8300

# The 4 leftmost nodes:

1000 2200 3220 4020

# The 4 rightmost nodes: 50012 62012 72212 80212

# Part 2 - the facet list.

# Six facets with boundary markers. 61

# The leftmost facet.

1 0 -1 # 1 polygon, no hole, boundary marker (-1) 4 1234

# The rightmost facet.

1 0 -2 # 1 polygon, no hole, boundary marker (-2) 4 5678

# Other facets. 1

4 1562 # bottom side 1

4 2673 # back side 1

4 3784 #top side 1

4 4851 # front side # Part 3 - the hole list. # There is no hole in bar. 0

# Part 4 - the region list. # There is no region defined. 0

命令行可以如下选择:PLC的第一个网格(-p),然后强加质量约束(-q)。这样将会在三个文件中生成一个网格质量。分别为bar.1.node, bar.1.ele, and bar.1.face

tetgen –pq bar

下面是输出文件bar.1.node。它包含47个点。为了满足质量标准,tetgen会自动添加一些额外的点。

47300 1 000 2 200 3 220 4 020 5 0012 6 2012 7 2212 8 0212

9 1.0000469999999999 0 0 10 0 0.999668 0

11 0 0.99944500000000003 12

12 1.000594 0 12 ...

# Generated by tetgen -pq bar

Here is the output file “bar.1.ele”, which contains 83 tetrahedra. 83 4 0

1 18332034 292325 3 17182034 4 43321837 5 19203033 6 14411342 7 122676 8 102819 9 28331834 10 35 41 38 45 11 10 9 25 28 12 3251930 ...

# Generated by tetgen -pq bar

下面是输出文件bar.1.face。它包含了90个边界面。面1和面2是最左边的面,因此有标识符-1;面3与面4有标识符-2表明它们是最右边的面。其他的面都有默认的标识符0.

90 1 13410-1 21093-1 3 7 12 11 -2 47118-2 5 1837 430 6 2446 390 726670 8 3522 240 929780 10 39 7 29 0 11 29 11 27 0 12 23 45 38 0 ...

# Generated by tetgen -pq bar

然而,对用有限元法或者是有限体积法来进行数值模拟的话,上面的网格可能太粗糙。Tetgen运行时可以

用-q 或者 –a选项,或者两个选项同时使用,此时将产生更密的网格质量。

tetgen -pq1.414a0.1 bar

Tetgen产生了一个包含330个顶点和1092个四面体的网格。这些多出来的点是由于我调用了-q和-a选项。

要想看到关于网格的质量报告,可以输入下面命令: > tetgen -rNEFV bar.1

4.3.2 有两个区域的PLC区域

下面的例子中,我们在bar的里面添加了一个内部边界面,以致于在bar上创建了两个区域(区域由这个新添加的面分割开来)。图20 展示了这个改变的几何图形。这个bar由12个节点和七个面组成(注意这些面当中有些已经不再是单一的多边形)。另外,此时已经定义了两个区域,它们分别带有区域属性-10和-20.物理上,我们可以两个区域赋予不同的材质。上一个例子中的两个边界标识符仍然存在。下面是bar2.poly文件,它描述了这个修改后的bar:

# Part 1 - the node list.

# The model has 12 nodes in 3D, no attributes, no boundary marker. 12300

# The 4 leftmost nodes: 1000 2200 3220 4020

# The 4 rightmost nodes: 50012 62012 72212 80212

# The 4 added nodes: 9003 10 2 0 3 11 2 2 3 12 0 2 3

# Part 2 - the facet list.

# Seven facets with boundary markers. 71

# The leftmost facet.

1 0 -1 # 1 polygon, no hole, boundary marker (-1) 4 1234

# The rightmost facet.

1 0 -2 # 1 polygon, no hole, boundary marker (-2) 4 5678

# Each of following facets has two polygons, which are # one rectangle (6 corners) and one segment. 2

6 1956102# bottom side 2910 2

6 21067113# back side 21011 2

6 31178124#top side 21112 2

6 4128591# front side 2129

# The internal facet separates two regions. 1

4 9 10 11 12

# Part 3 - the hole list.

# There is no hole in bar. 0

# Part 4 - the region list.

# There are two regions (-10 and -20) defined. 46 2

1 1.0 1.0 1.5 -10 0.1 2 1.0 1.0 5.0 -20 -1

这个“tetgen -pqaA bar2”命令产生了bar2.1.ele文件。下面列出了这个文件的前八行。它和bar.1.ele是不同的,每一行记录都增加了一个区域属性。

431 4 1

1 32575060-20 2 51235049-20

3 88 138 116 149 -10 4 76969536-20 5 29555652-20

6 132 138 88 139 -10 7 65 138 132 139 -10 8 16545315-20 ...

# Generated by tetgen -pqaA bar2

生成的网格的可视化之后,我们可以看到这个经过优化后的区域-10,它是比其他的地方要密。这是因为

bar2.poly文件中定义了体积约束,并且使用了-aA选项。

5 其他程序调用tetgen

除了被用作一个独立的程序之外,tetgen也可以被其他程序调用。Tetgen库提供了函数与数据结构。使用tetgen库的一个好处是它能够被其他程序重复调用而不会覆盖输入或者输出的文件。这个特征对一些应用程序非常有用,像合适的有限元法和有限体积法。

这个章节给出了使用tetgen库一些必要的说明。包含的例子有助于更好的理解。用户要想能够使用tetgen的话,需要知道他的命令选项和输入输出文件格式。第二节包含了怎么把tetgen编译成一个库的介绍。

5.1 头文件

所有调用tetgen的程序必须包含头文件tetgen.h #include \

Tetgen库包含了所有的数据类型和函数声明。更特别的是,它定义了函数tetrahedralize()和数据类型tetgenio,这个两个是提供给用户调用tetgen的接口。在5.2节和5.3节将有介绍。

5.2 调用规则

函数tetrahedralize()声明如下:

void tetrahedralize(char *switches, tetgenio *in, tetgenio *out)

参数switch是一个命令行参数字符串。在这个字符串中,不要求有初始化破折号。Q选项建议在最终的代码中,选项I(没有迭代数值),g(.mesh文件输出),G(.msh文件输出)是没有效果的。 参数in,out是两个指向tetgenio对象的指针,描述输入和输出。In和out可能是空指针。

5.3 tetgenio数据类型

Tetgenio结构是用来传入数据和四面体的输出。它可以用一个数组集代替tetgen的输入和输出文件,这些数组用来保存点,四面体,标识符等。它被声明作为一个C++类,包括一些数据域和函数,tetgenio的数据域如下:

int firstnumber; // 0 or 1, default 0. int mesh_dim; // must be 3. REAL *pointlist;

REAL *pointattributelist; REAL *addpointlist; int *pointmarkerlist; int numberofpoints;

int numberofpointattributes; int numberofaddpoints; int *tetrahedronlist;

REAL *tetrahedronattributelist; REAL *tetrahedronvolumelist; int *neighborlist;

int numberoftetrahedra; int numberofcorners;

int numberoftetrahedronattributes; facet *facetlist; int *facetmarkerlist; int numberoffacets; REAL *holelist; int numberofholes; REAL *regionlist; int numberofregions;

REAL *facetconstraintlist; int numberoffacetconstraints; REAL *segmentconstraintlist; int numberofsegmentconstraints; int *trifacelist;

int *trifacemarkerlist; int numberoftrifaces; int *edgelist;

int *edgemarkerlist; 49

int numberofedges;

5.4 数组描述

就一般情况而言,数组中的第一项的索引是0.然而,如果使用了选项z的话,这个项的项索引从firstnumber开始,在这种情况下它的项号是0.下面是对于这些数组的描述。

Poinlist 顶点左边数组。第一个顶点的x坐标是index[0],y坐标是index[1],z坐标是index[3]。接下来是其他顶点的坐标。每一个顶点占三个REALs。

Pointattributelist 顶点属性数组。

每一个顶点的属性占用“numberofpointattributes” REALs.

Pointmarkerlist 顶点标识符数组,每一个点的标识符为一个整数。

Addpointlist 额外顶点坐标数组,当使用-i选项时,这些点将被读入然后插入到网格中。结构跟pointlist一样,每一个点占三个REALs

Tetrahedronlist 四面体角数组。第一个四面体的第一个角为index[0],接下来是其他的三个角,如果使用了-o2选项的话,接下来便是其他的节点。每一个四面体占用numberofcorners整型。

Tetrahedronattributelist 四面体属性数组。每一个四面体属性占用“numberoftetrahedronattributes” REALs。

Tetrahedronvolumelist 四面体体积列表,四面体体积约束数组;每一个四面体占一个REAL,只用在输入。

Neighborlist 四面体邻居数组。每一个四面体占四个整数。只输出。

Facetlist PLC面数组。每一个面都是一个面类型的对象(见章节5.4.2)。

Facetmarkerlist 面标识符数组。每一个面一个占一个整数。

Holelist 洞数组。第一个洞的x,y,z坐标分别在index[0],index[1],index[2],接下来是其他洞的坐标。每一个洞占三个REALs。

Regionlist 区域属性和体积约束数组。第一个约束的x,y,z坐标在inde[0],index[1],index[2],区域属性在index[3],接着是最大体积在index[4],再接下来就是其他区域的约束。每一个体积约束占5个REALs。每一个区域属性只有在A选项使用时才有效,每一个体积约束只有在a选项时才有效,但省略其中一个选项不会改变内存布局。

Facetconstraintlist面的最大面积约束数组。每一个约束占两个REALs。第一个为面的标识符,第二个是它的最大面积限制。注意facetconstraintlist只有在开启选项q时才能够用。

Segmentconstraintlist 段长度约束数组。每一个约束占两个REALs。第一个是节点的索引(指向pointlist),第二个是最大长度限制。注意segmentcon-straintlist只有在q选项开启使用。

Trifacelist 三角形面数组。第一个面的角是在index[0],index[1],index[2],接下来是其他的面。每一个面占三个整数。

Trifacemarkerlist 面标识符数组。每一个面一个整数。

Edgelist 段终端店数组。第一个段的终端点位于index[0],index[1],接下来是其他的段。每段占两个整数。

Edgemarkerlist 段标识符数组。每一段一个整数。

5.4.1 内存管理

Tetgenio定义两个柜子用于内存的初始化和释放。他们是:

void initialize(); void deinitialize();

initialize()初始化所有内容。也就是说,所有指向数组的指针都为空。除了变量numberofcorners(它的值为4),其他的变量初始化为0.初始化工作由tetgenio的构造函数完成。例如,下面一行创建了一个名为io的tetgenio对象,io所有的域都被初始化了: tetgenio io;

下一步是为每一个将要使用的数组分配内存。C++的内存分配与释放可以通过new和delete关键字。另一对函数是malloc()与free()。无论你用什么,你必须使用两个函数中的一个。New/delete和malloc/free不能混淆。例如,下面一行为io.pointlist分配了内存。 io.pointlist = new REAL[io.numberofpoints * 3];

deinitialize通过用delete为已经分配的tetgenio对象释放内存。它是自动调用tetgenio对象的delete。如果内存是通过malloc函数分配的,用户应该手动去释放它。在释放所有内存之后,initialize()函数的一个调用将没有自动内存释放的功能。

重新使用一个对象是可能的:首先调用d einitialize(),然后在下一次用之前调用initialize();

5.4.2 facet数据结构

在tetgenio里面定义了面的数据结构,facet可以用来表示一个PLC的任意面。然而,为了保持灵活性,不用直接用它。

下面展示的Facet结构由一个多边形列表和一个洞点列表组成。

typedef struct { polygon *polygonlist; int numberofpolygons; REAL *holelist; int numberofholes; } facet;

A polygon也是一个polygon类型的对象。它由一列角点组成。结构如下:

typedef struct { int *vertexlist; int numberofvertices; } polygon;

实际上,facet的结构是poly文件格式的直接翻译,章节3.2.2描述了。图20前面的面作为设定一个PLC面作为facet对象的例子。它有两个多边形。一个有六个顶点,另外一个是一个segment,没有洞,ACSII码数据如下: 2

6 412859 1# front side 2129

下面的C++代码做了介绍。这里假定已经创建了一个tetgenio对象io。

tetgenio::facet *f; // Define a pointer of facet. tetgenio::polygon *p; // Define a pointer of polygon. // All indices start from 1. io.firstnumber = 1;

...

// Use ’f’ to point to a facet of ’facetlist’. f = &io.facetlist[i];

// Initialize the fields of this facet. // There are two polygons, no holes. f->numberofpolygons = 2;

// Allocate memory for polygons.

f->polygonlist = new tetgenio::polygon[2]; f->numberofholes = 0; f->holelist = NULL;

// Set the data of the first polygon into facet. p = &f->polygonlist[0]; p->numberofvertices = 6;

// Allocate memory for vertices. p->vertexlist = new int[6]; p->vertexlist[0] = 4; p->vertexlist[1] = 12; p->vertexlist[2] = 8; p->vertexlist[3] = 5; p->vertexlist[4] = 9; p->vertexlist[5] = 1;

// Set the data of the second polygon into facet. 53

p = &f->polygonlist[1]; p->numberofvertices = 2;

p->vertexlist = new int[2]; // Alloc. memory for vertices. p->vertexlist[0] = 12; p->vertexlist[1] = 9;

5.5 一个例子

这一节给出了一个其他程序怎么样通过使用tetgeio数据结构和函数“tetrahedralize()”来调用tetgen的例子。章节4.3.1的例子再一次被用到。

下面给出了完整的C++代码。用户可以从链接http://tetgen.ber lios .de /fil es/t etca ll. Cxx下载。这个代码说明了下面的基本步骤:

第一步创建一个tetgenio的输入对象in,其中包含bar的数据。

然后调用函数“tetrahedralize()”创建一个四面体网格,结果输出到对象out中。

另外,它把对象in中的PLC输出到barin.node and barin.poly文件中,并且把对象out中的网格输出到barout.node, barout.ele, and barout.face。这些文件可以通过tetview显示出来。

这个例子可以编译成一个可执行程序。 把tetgen编译成一个名为libtet.a的库

把文件“tetcall.cxx”保存到文件“tetgen.h” and “libtet.a”相同的目录。 使用下面的命令编译它

g++ -o test tetcall.cxx -L./ -ltet 此时将会产生一个可执行文件test

完整源代码如下:

#include \int main(int argc, char *argv[]) {

tetgenio in, out; tetgenio::facet *f; tetgenio::polygon *p; int i;

// All indices start from 1. in.firstnumber = 1; in.numberofpoints = 8;

in.pointlist = new REAL[in.numberofpoints * 3]; in.pointlist[0] = 0; // node 1. in.pointlist[1] = 0; in.pointlist[2] = 0;

in.pointlist[3] = 2; // node 2. in.pointlist[4] = 0; in.pointlist[5] = 0;

in.pointlist[6] = 2; // node 3. in.pointlist[7] = 2; in.pointlist[8] = 0;

in.pointlist[9] = 0; // node 4. in.pointlist[10] = 2; in.pointlist[11] = 0; // Set node 5, 6, 7, 8. for (i = 4; i < 8; i++) {

in.pointlist[i * 3] = in.pointlist[(i - 4) * 3];

in.pointlist[i * 3 + 1] = in.pointlist[(i - 4 )*3+1]; in.pointlist[i * 3 + 2] = 12; }

in.numberoffacets = 6;

in.facetlist = new tetgenio::facet[in.numberoffacets]; in.facetmarkerlist = new int[in.numberoffacets]; // Facet 1. The leftmost facet. f = &in.facetlist[0]; f->numberofpolygons = 1;

f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; f->numberofholes = 0; f->holelist = NULL; p = &f->polygonlist[0]; p->numberofvertices = 4;

p->vertexlist = new int[p->numberofvertices]; p->vertexlist[0] = 1; p->vertexlist[1] = 2; p->vertexlist[2] = 3; 55

p->vertexlist[3] = 4;

// Facet 2. The rightmost facet. f = &in.facetlist[1]; f->numberofpolygons = 1;

f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; f->numberofholes = 0; f->holelist = NULL; p = &f->polygonlist[0]; p->numberofvertices = 4;

p->vertexlist = new int[p->numberofvertices]; p->vertexlist[0] = 5; p->vertexlist[1] = 6; p->vertexlist[2] = 7; p->vertexlist[3] = 8;

// Facet 3. The bottom facet. f = &in.facetlist[2]; f->numberofpolygons = 1;

f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; f->numberofholes = 0; f->holelist = NULL; p = &f->polygonlist[0]; p->numberofvertices = 4;

p->vertexlist = new int[p->numberofvertices]; p->vertexlist[0] = 1; p->vertexlist[1] = 5; p->vertexlist[2] = 6; p->vertexlist[3] = 2;

// Facet 4. The back facet. f = &in.facetlist[3]; f->numberofpolygons = 1;

f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; f->numberofholes = 0; f->holelist = NULL; p = &f->polygonlist[0]; p->numberofvertices = 4;

p->vertexlist = new int[p->numberofvertices]; p->vertexlist[0] = 2; p->vertexlist[1] = 6; p->vertexlist[2] = 7; p->vertexlist[3] = 3;

// Facet 5. The top facet. f = &in.facetlist[4]; f->numberofpolygons = 1;

f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; f->numberofholes = 0; 56

f->holelist = NULL; p = &f->polygonlist[0]; p->numberofvertices = 4;

p->vertexlist = new int[p->numberofvertices]; p->vertexlist[0] = 3; p->vertexlist[1] = 7; p->vertexlist[2] = 8; p->vertexlist[3] = 4;

// Facet 6. The front facet. f = &in.facetlist[5]; f->numberofpolygons = 1;

f->polygonlist = new tetgenio::polygon[f->numberofpolygons]; f->numberofholes = 0; f->holelist = NULL; p = &f->polygonlist[0]; p->numberofvertices = 4;

p->vertexlist = new int[p->numberofvertices]; p->vertexlist[0] = 4; p->vertexlist[1] = 8; p->vertexlist[2] = 5; p->vertexlist[3] = 1;

// Set ’in.facetmarkerlist’ in.facetmarkerlist[0] = -1; in.facetmarkerlist[1] = -2; in.facetmarkerlist[2] = 0; in.facetmarkerlist[3] = 0; in.facetmarkerlist[4] = 0; in.facetmarkerlist[5] = 0;

// Output the PLC to files ’barin.node’ and ’barin.poly’. in.save_nodes(\in.save_poly(\

// Tetrahedralize the PLC. Switches are chosen to read a PLC (p), // do quality mesh generation (q) with a specified quality bound // (1.414), and apply a maximum volume constraint (a0.1). tetrahedralize(\

// Output mesh to files ’barout.node’, ’barout.ele’ and ’barout.face’. out.save_nodes(\out.save_elements(\out.save_faces(\return 0; }

附录

这一节给出了作为快速引用的一些扩展基本概念的简单介绍

Convex Hull n维空间顶点集V的凸壳,用convV标识,是包含V的最小凸壳集

Simplex a Simplex --- 是一个几何独立的顶点集S的凸壳。--的维数是小于顶点集S的顶点个数。特别地,在三维空间中最大几何独立的点的个数是4。我们有非空simplices of dimensions 0, 1, 2 and 3被分别称为vertices, edges,

triangles ,andtetrahedra。对于任何子集T ? S,the simplex τ =convT is σ的一个面,并且我们写成 τ ≤ σ . 如果T是一个S的一个合适的子集,那么τ是σ一个合适的字面。

Simplical Complex A simplical complex K是simplices的有限集,K中simplex的任何面一定在K中,并且K中任何两个交叉的simplices也是在一个面上。条件 (ii)允许两个simplices相邻,因为空集是唯一的空间simplex,它是任意simplex的面。图21(a)说明了一个二维空间的simplical complex.

Underlying Space simplices L集的潜在空间,用| L|标识,是内部的集合, σ ∈L intσ。(见图21(b)的说明)。只有当L是一个simplical complex ,| L|是拓扑的闭合集

Subcomplex K的subcomplex是simplices of K的子集,它也是一个simplical complex。可以参考图21(c)的例子

本文来源:https://www.bwwdw.com/article/h6tr.html

Top