[基本数据结构]网格(Mesh)和几何体(Geometry)

本人为个人学习之便在此转载,局部加工,版权归原作者:李若所有,更多文章请访问 作者的BLOG
(转载时请注明作者和出处。未经许可,请勿用于商业用途)

[摘要]
1、Geometry —— 几何体类,将点(0维)、线(1维)、面(2维)、体(3维)等维数(dim)不同的基本形状大一统,打包处理。“单独一个几何体中存储的数据是没有意义的,几何体这个类的对象必须在网格类中间存储,才能够有意义。”
(GeometryBM 类 继承 Geometry 类,仅附加信息: boundary_mark_type(即int)     bm
私有数据成员:
            int        ind     // 几何体在mesh中的编号,mesh.geo[dim][ind]即是该几何体
std::vector <   int   >      vtx     // 几何体顶点在mesh中的编号,vtx.size()即该几何体顶点个数
std::vector <   int   >      bnd    // 几何体边界在mesh中的编号,bnd.size()即该几何体边界个数
(对于各维图形,顶点和边界的概念略有不同,0维需注意)

2、Mesh —— 网格类,自然应该包含网格上所有几何体集合的信息,通过这些信息彼此索引。“在AFEPack内部的设计语言中,每个几何体的表述方法,都是按照“第n维的第m个几何体”这样的方式来叙述的。”
私有数据成员:
             std::vector <  Point <  DOW  >   >      pnt     // 网格上结点坐标
std::vector <  std::vector <  GeometryBM  >   >      geo     // geo[k][l]即第k维的第l个几何体

3、DIM是网格所在的区域作为一个流形的维数。e.g.球面是二维的,DIM=2。
   DOW(Dimension Of World),是网格所在的流形在欧式空间的维数。e.g.球面 DOW=3。


网格和几何体
AFEPack /老弱 

应Wang Han的要求,写一些解释AFEPack的基本数据结构的内容。首先,我们说一下关于网格和几何体的数据结构。

几何体的类就是Geometry,如果需要材料标识,则叫做GeometryBM,这个名字比较难看,是因为开始的时候没有设计好造成的。单独一个几何体中存储的数据是没有意义的,几何体这个类的对象必须在网格类中间存储,才能够有意义。

Mesh这个类存储着各维几何体的数组。其中,最高维的几何体就是网格中间的单元,最低维的几何体则是网格中的节点。因为使用了数组,就可以使用随机读取方式来取其中的元素,因此,在AFEPack内部的设计语言中,每个几何体的表述方法,都是按照 “第n维的第m个几何体”这样的方式来叙述的。

在Geometry中,于是就使用存储序号的方式进行相互引用。Geometry中有两个数组,一个存储它的顶点的序号,一个存储它的拓扑边界几何体的序号。

几何体的顶点是网格中的节点,我们称为“第0维几何体”。而对于一个“第m维几何体”来说,它的拓扑边界几何体是“第m-1维的几何体”。每个几何体总是往低维进行索引,从而获得关于其自身结构的所有信息。

于是,对于一个给定的网格类的对象 a_mesh,为了得到某一个维数(比如第k维)的几何体的个数,我们可以使用
    u_int n  =  a_mesh.n_geometry(k);
得到。而为了得到第k维的第l个几何体,则可以使用
    GeometryBM &  geo  =  a_mesh.geometry(k, l);

这样,我们获得了一个几何体的对象,然后就可以知道它的顶点和拓扑边界的序号,就可以继续往低维进行索引了,比如我们取出上面得到的这个几何 geo 自己的边界,可以使用如下的代码:
    u_int n_bnd  =  geo.n_boundary();  /// geo 的拓扑边界几何体的个数
     for  (u_int i  =   0 ;i  <  n_bnd;i  ++ /// 进行遍历
      u_int bnd_idx = geo.boundary(i); /// 第i个边界几何体的序号
      GeometryBM& bnd_geo = a_mesh.geometry(k-1, bnd_idx); /// 取出来
      ... ...
    }

网格类有两个模板参数,一个是DIM,一个是DOW。其中DIM是网格所在的区域,作为一个流形的维数。比如平面上的一个多边形,是二维的,球面也是二维的。这个数决定了Mesh类中间,用来存储各维几何体的数组的数组的大小,事实上这是一个 DIM+1 个元素的数组,分别存储第 0 维一直到第 DIM 维的几何体。

另外一个模板参数 DOW是Dimension Of World的缩写,标识的是网格所在的流形所在的欧式空间的维数。比如平面上的一个多边形,DOW=2,而对于球面,则DOW=3。

不知你注意到没有,我们事实上到现在为止还没有说网格中的点的坐标呢!DOW事实上给定的就是网格中的点的坐标的维数。在Mesh类中,存储着一个坐标的数组,其中每个元素是一个Point<DOW>型的对象,事实上就是一个坐标而已。

对于一个“0维几何体”,它的顶点序号具有不一样的意义,事实上是说自己作为网格中的一个节点,坐标是坐标数组中的哪一个。而“0维几何体界”的拓扑边界是没有意义的,所以请不要使用其中的信息:那个数AFEPack不会负责维护的!

“0维几何体”的这种特殊性,给我们的程序常常带来了一些麻烦。比如,我们想 取一个几何体 geo 的第k个顶点的坐标,需要使用下面的方式:
    u_int vtx_idx  =  geo.vertex(k);  /// 节点几何体的序号
    GeometryBM &  vtx_geo  =  a_mesh.geometry( 0 , vtx_idx);  /// 取出该节点几何体
    u_int pnt_idx  =  vtx_geo.vertex( 0 );  /// 取出坐标的序号
    Point < DOW >&  pnt  =  a_mesh.point(pnt_idx);  /// 取出坐标

有时候,你自己可以保证 vtx_idx 和 pnt_idx 是一样的,这样可以省下来两行,但是库的内部并不能保证这一点。

AFEPack的内部设计语言将节点称为“0维几何体”,把线段称为“1维几何体”等等的目标并不是想标新立异,而是为了统一,因为计算机更善于理解更加统一的语言。而且,在这样的语言下,我们事实上可以描述任意维数的网格,对网格中的几何体的形状也没有什么既定的要求,是一种非常灵活的描述网格的数据格式。

一个Mesh类中的数据,如果被写到文件中,就是完全按照其在内存中的方式进行输出的。首先输出的是坐标,然后是0维几何体,1维几何体,...,直到DIM维几何体。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值