几个经典的数学库之一学习---VCGlib(2)

1. Optional Component(可选的组件)

有许多Vertex和Face的属性并不是一直都是必要的,如Face-Face的邻接关系。VCG库提供了一种可以指定可选组件的方法。如属性信息并不是静态保存在simplex(简素)中的,而是当被需要他们的时候,静态分配这些属性信息的。

定义使用这些组件,需要做以下两种事情:  (1)使用在mesh的定义中使用经典的容器,从std::vector中继承  (2)在simplex的定义中使用指定的组分类型定义

当component被激活时,其能够被使用,即通过调用Enableing函数。VCG处理Optional Componnet采用两个机制:(1)Ocf(Optional component Fast),即使用指针对于每种“简素Simliex”,但是可以和non-optional 对象数据一样快。(2)Occ(Optional Component Compact),对于每个mesh,需要的内存空间非常小,但是这样的弊端是获取访问数据非常慢。

下面讨论两种方法。

Optional Component Fast

下面定义MyMesh,指定了定点和面的一些component。指定的属性vcg::vertex::InfoOcf 与 vcg::face::InfoOcf 是定点和面的第一个属性,并且我们使用vcg::vertex::vertex_Ocf 与 vcg::face::vectorOcf作为容器;

(www.cnblogs.com/icmzn提供)

classMyVertexOcf;classMyFaceOcf;struct MyUsedTypesOcf: public vcg::UsedTypes<:use>::AsVertexType,

vcg::Use::AsFaceType>{};class MyVertexOcf : public vcg::Vertex

vcg::vertex::InfoOcf,//

vcg::vertex::Coord3f, vcg::vertex::QualityfOcf,

vcg::vertex::Color4b, vcg::vertex::BitFlags,

vcg::vertex::Normal3f, vcg::vertex::VFAdjOcf>{};class MyFaceOcf : public vcg::Face

vcg::face::InfoOcf,//

vcg::face::FFAdjOcf, vcg::face::VFAdjOcf,

vcg::face::Color4bOcf, vcg::face::VertexRef,

vcg::face::BitFlags, vcg::face::Normal3fOcf>{};//the mesh class must make use of the 'vector_ocf' containers instead of the classical std::vector

class MyMeshOcf : public vcg::tri::TriMesh< vcg::vertex::vector_ocf,vcg::face::vector_ocf > {};

在获取Optional Component中的数据是,需要首先调用EnalbeXX()来激活相应的可选属性。然后相应的属性可以被分配空间,并且获取。直到调用disAble()为止。

MyMeshOcf cmof;

assert(tri::HasFFAdjacency(cmof)== false);

cmof.face.EnableFFAdjacency();

assert(tri::HasFFAdjacency(cmof)== true);

在激活之前,获取的Componnent的数据,或者在关闭之后,相应的组件会抛出异常。

cmof.face.EnableNormal(); //remove this line and you will throw an exception for a missing 'normal' component

tri::UpdateNormal::PerVertexPerFace(cmof);

2. Bit Flags

对于mesh的每一种simplex(简素),都有一种BitFlags的组件,保存固定的32bit的矢量标识,用来分类判别的需要。可以使用下面相关的类:

IsD():删除标识

可以判定该简素对象是否被删除。因为mesh中的元素可以被Allocating和Deleting网格。

IsB(),ClearB(),SetB():边界标识

可以判定顶点或者面是否再边界上。这些bit不是默认计算获取,他们是连同拓扑一起或者不是一起计算后的结果。如果FF拓扑计算这些标识效率高。

这些标识的关联是,有许多的算法需要边界特征来计算是高效率的。而没有必要对整个FF拓扑结构进行全部运算。

IsS(), ClearS(), SetS():选择标识

IsV(), ClearV(), SetV():访问标识

访问标识,对于一些算法是很有用的。你不应该依赖这些标识的状态,或者人工设置当前的状态,因为任何的一种算法都可以清理这些标识以及更新这些标识。

使用tri::UpdateFlags::VertexClearV(yourMesh),来清理所有的bits

用户自定义标识

如果用户定义私有的标识,通过NewBigFlag()函数方式,可以返回一个Mash(掩码)用来设置,清理,测试针对特定big。下面例子分配三个bit,对每一个face然后清理他们。

int e0bit = MyFace::NewBitFlag();

int e1bit = MyFace::NewBitFlag();

int e2bit = MyFace::NewBitFlag();

int ebit[3] = {e0bit,e1bit,e2bit};

for(MyMesh::FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)

for(int i=0;i<3;++i)

(*fi).ClearUserBit(ebit[i]);

通过使用tri::UpdateFlags::FaceClear(yourMesh,e0bit|e1bit|e2bit);来清理所有mesh的定点或者面的指定bit

3. Allocating and Deleting mesh elements

Creating elements

通过AddVertices and AddFaces functions 来给指定的mesh增加三角网格,或者增加元素。新添加的元素在mesh的最后,且函数返回第一个添加元素的指针。如果新添加元素引起vector重新内存分配,则指向该类的vector的指针将无效。这些函数管理安全的重新分配以及指针更新所有的保存在mesh内部的指针,即如果添加一些vectors,且引起了vertex vector的重新内存分配,则在face结构中的指针指向vector,这些指针将会自动进行更新通过Allocator Functions。所以,用户不能直接进行reallocate 或者resize  vectors or face vectors.

class MyMesh : public vcg::tri::TriMesh< std::vector, std::vector >{};intmain()

{

MyMesh m;

MyMesh::VertexIterator vi= vcg::tri::Allocator::AddVertices(m,3);

MyMesh::FaceIterator fi= vcg::tri::Allocator::AddFaces(m,1);

MyMesh::VertexPointer ivp[4];

ivp[0]=&*vi; vi->P()=MyMesh::CoordType ( 0.0, 0.0, 0.0); ++vi;

ivp[1]=&*vi; vi->P()=MyMesh::CoordType ( 1.0, 0.0, 0.0); ++vi;

ivp[2]=&*vi; vi->P()=MyMesh::CoordType ( 0.0, 1.0, 0.0); ++vi;

fi->V(0)=ivp[0];

fi->V(1)=ivp[1];

fi->V(2)=ivp[2];

在platonic.h文件中有很多增加元素的例子。

如果用户内部的一些指针指向mesh元素,但是增加的元素可能无效这些指针,可以通过传入vcg::tri::Allocator函数,来更新这些内部的私有指针。

//a potentially dangerous pointer to a mesh element

MyMesh::FacePointer fp = &m.face[0];

vcg::tri::Allocator::PointerUpdater<:facepointer>pu;//now the fp pointer could be no more valid due to eventual re-allocation of the m.face vector.

vcg::tri::Allocator::AddVertices(m,3);

vcg::tri::Allocator::AddFaces(m,1,pu);//check if an update of the pointer is needed and do it.

if(pu.NeedUpdate()) pu.Update(fp);

Destroying Elements

vcglib采用 lazy Deletion Strategy(惰性删除策略),即在vector中的元素通过flagged处理,进行“预删除”,即它们仍然在这里。

标记deleted的mark元素,对生于的结构没有影响。因此如果标记顶点但是没有合适所有的face,且面依附这个已经removed的vertex,则用户创建了一个非一致的状态。

用户永远不要试图自行删除vertex,即自行进行删除标记,用户需要调用Allocator Utility Function。

//Now fill the mesh with an Icosahedron(二十面体) and then delete some faces

vcg::tri::Icosahedron(m);

vcg::tri::Allocator::DeleteFace(m,m.face[1]);

vcg::tri::Allocator::DeleteFace(m,m.face[3]);

如上面的例子,在一个二十面体重删除一些vertex。通过上述操作,faces的vertor仍然包含20个元素(二十面体重包含面的数量),但是m.FN()返回的是18面,因此如果算法中含有删除处理,则可能会发生容器中的数量不等于mesh中有效的元素数量。

m.vert.size() != m.VN()

m.face.size() != m.FN()

因此,当用户扫描vertects和face的容器时,可能会遇到被deleted marked的元素,所以用户需要格外小心。通过调用IsD()进行检测判定处理。

//If you loop in a mesh with deleted elements you have to skip them!

MyMesh::CoordType b(0,0,0);for(fi = m.face.begin(); fi!=m.face.end(); ++fi )

{if(!fi->IsD()) //

{

b+= vcg::Barycenter(*fi);

}

}

在一些情形中,当用户遍历大量的mesh的元素时,通过上述isD()检测效率低,可以通过简便实用的两个garbage collection function函数,通过显示调用:

通过掉应上述两个函数,就不需要对mesh的元素进行isD()检测,直接进行操作,效率更高。

m.vert.size() == m.VN()

m.face.size() == m.FN()

注意:

1. 如果在mesh中没有deleted标识的元素, compactor函数将直接返回(其内部通过判定,容器vector的size函数是否与元素数量匹配判定),所以在左右的高强度操作前调用compactor函数非常安全。

2. 如果不清楚deleted元素位置,则不能通过m.FN ()或者m_VN()函数来作为for函数的终止条件,因为m.FN() != m.face.size(),因为m.FN()是有效的face的数量,而m.face.size()是face的容器的元素数量,因为容器中可能包含deleted标记的元素,这deleted标记的元素不是有效的元素。下面的例子是WRONG!!!!

//WRONG WAY of iterating: FN() != m.face.size() if there are deleted elements

for(int i=0;i

{if(!fi->IsD())

{

b+= vcg::Barycenter(*fi);

}

}

How to copy a mesh

考虑到intricate nature (复杂的本质) of mesh, vcglib库禁止拷贝mesh作为一个简单的对象。

如果需要拷贝mesh,则必须使用附加的工具类: The Append Utility Class。

vcg\complex\append.h文件中包含了工具类:Append的详细实现。还有可以实现可选的mesh,或者添加后一个mesh到前一个mesh中的工具。

4. Adding user defined attributes to mesh elements

User-Defined Attributes

vcglib提供简单的机制来关联user-defined 属性到“简素”simplicies以及mehs。

attributes以及components都是与simplex关联的数据,即components是静态定义的成员数据,attributes则是运行时run-time定义的,处理的数据。

二者的区别:1,conceptually(概念上) component是指来定义simplex(简素)的基本的信息,如position,normal,以及相关的信息。但是user-defined attribute是针对指定的算法而添加的可获取的数据信息,如一个定点可见的平均方向。2.pratically(事实上), 对于每一个optional Conponents,都有其本身non-optional 部分,而且可以通过simplex(简素)的成员函数可以获取,如Vi->N()。对于属性attribute则只能通过创建attribute然后返回。

//add a per-vertex attribute with type float named "Irradiance"

MyMesh::PerVertexAttributeHandle named_hv = vcg::tri::Allocator:: GetPerVertexAttribute (m,std::string("Irradiance"));

可以通过handle或者name来删除属性。注意,handle的作用于并不干扰属性的内存的分配。如果没有显示地(explicitly)删除属性,该属性将会一直保留分配的内存,指导mesh被摧毁,及时没有任何handle可以处理。

上述两个方法可以同样适应于edges,faces以及mesh。仅仅通过替换PerVertex,PerFace,PerEdge,PerMesh等。如果增加属性但是没有指定名字且丢失handle,则将不会把handle重新返回。

对于Per-Mesh的指定的属性,可以通过稍微不同的方式获取:

//you can also have PerMesh attributes

MyMesh::PerMeshAttributeHandle hm = vcg::tri::Allocator:: GetPerMeshAttribute (m,std::string("ADummyIntegerAttribute"));//PerMesh attributes are accessed directly using the handle itself

hm() = 10;

C++ type of a mesh and reflection

VCGlib 提供一系列的函数来实现reflection(反射),如在运行时获取mesh的类型。这些函数遵循以下格式: Has[attribute](mesh),然后返回一个boolean值,表示指定的属性是否存在。

因为VCGlib的反射机制考虑了可选组件optional components,因此HasPerVertexNormal(m)返回ture,如果vertex的类型包含属性vcg::vertex::Normal3f 或者如果包含属性作为opetional,vcg::vertex::Normal3fOCF 且 enabled。

5. Loading and saving meshes

VCGlib提供以下的文件格式进行导入导出:

import: PLY, STL, OFF, OBJ, 3DS, COLLADA, PTX, V3D, PTS, APTS, XYZ, GTS, TRI, ASC, X3D, X3DV, VRML, ALN

export: PLY, STL, OFF, OBJ, 3DS, COLLADA, VRML, DXF, GTS, U3D, IDTF, X3D

以下例子读取PLY的文件:

#include

//definition of type MyMesh

MyMesh m;

vcg::tri::io::ImporterPLY::Open(m,"namefile_to_open.ply");//....

vcg::tri::io::ExporterPLY::Save(m,"namefile_to_save.ply");

上述是最小要求的导入导出接口。额外的其他两个参数可以指定:mask以及callback。 callback 用于提供再长时间的导入/导出过程的回调处理。mask用来更好的指定/理解导入/导出的内容。

Saving Mask and Reading Mask

一般而言,所有的文件格式至少保留vertex位置信息,和相互之间关联(拓扑)信息。但是,这些信息之外,用户可能还保留其他信息保存在文件file中。VCGLib提供类vcg::tri::io::Mask,是bit名字的集合,用来指定components保存在file中,如vcg::tri::io::Mask::IOM_VERTColor。

当Saving, 且在Read Only模式下,mask指定来保存指定的component。如,当保存mesh normal中的每个定点的法相(用于渲染),但是保存在PLY文件中是浪费文件空间大小,则需要指定一个合适的mash,即Mask::IOM_VERTNormal bit clearled。显然,不是所有的格式能够保存所有可能的数据。例如,STL文件不能保存纹理texture coords或者每一个定点的color。所以需要首先知道需要保存的文件支持的保存的能力,通过函数ExporterXXX::GetExportMaskCapability(),返回一个bitMask,即表示该文件格式的能力。

当Loading, 且在WriteOnly模式下,可以返回给用户那些部分的数据从文件中load到mesh对象中。如mask的初始信息将被忽略。能够用来知道用来准备mesh对象需要提供的信息数据。如需要知道哪些(指定)optional components,所有的importer的函数:ImporterXXX::LoadMask(fileName, mask),将会填充mask,而不loading 文件。

Error Reporting

mesh的I/O 函数成功运行,则返回ZERO(0);当遇到失败或者致命的问题,则返回Error code代码。使用static const char * ErrorMsg(int error)函数返回可以用户阅读的错误代码描述,以及通过静态函数: bool ErrorCritical(int err)来获取Error Code是致命问题,还是警告问题。例如,在OBJ文件格式,由于文件中缺少材料描述,被认为非致命的问题,因为还可以获取模型几何信息用户建模。

VMI dump file

VMI,即Vcglib Mesh Image,并不是合适的文件格式,但是是一种简单的vcg::TRiMesh导出的文件格式。之所以认为其不是一个合适的文件格式,是因为其没有提供指定的版本用于关联VCGlib的版本库以及后端的解析能力。相反,VMI则保存所有的components,所有的历史components(Currently OCF类型),所有的点,面,mesh属性,但是算法可能会cash在n-step。则可以立即保存计算的结果在VMI文件中,然后在load 这个文件。

注意:当使用vcg::tri::ImporterVMI(...)来load VMI文件,则需要指定与vcg::tri::ExporterVMI(..)导出的文件格式一致,否则会返回FALSE。

endl;

vcg函数值_几个经典的数学库之一学习---VCGlib(2)相关推荐

  1. vcg函数值_简单介绍几种函数信号发生器的原理图及不同功能设计

    简单介绍几种函数信号发生器的原理图及不同功能设计 前言 随着大规模集成电路的迅速发展,函数发生器的应用也逐渐广泛起来.函数信号发生器(函数信号发生器的使用)是一种在科研和生产中经常用到的基本波形产生器 ...

  2. vcg函数值_从GSP机制到VCG机制

    > 机制设计 在前文[博弈论基础]中已经谈过了微观经济学与博弈论的区别,在微观经济学中市场机制是一个『看不见的手』,调整市场进入均衡状态.在博弈论中,机制设计者(委托人)设计规则,代理人参与规则 ...

  3. python清单全套教程_编程最经典的一份python学习清单,零基础都可以学会的教程...

    站在风口上,猪都能飞起来.人工智能风口,让Pyhon这门胶水语言转变成非常火的网红语言. 编程功力深厚的程序员花一两个星期就能上手Python,而一些新手程序员花几个月就可以上手. 学编程,用Pyth ...

  4. 豆瓣评分9分+,6部经典趣味数学纪录片!

    全世界只有3.14 % 的人关注了 爆炸吧知识 数学是研究数量.结构.变化以及空间模型等概念的一门学科.透过抽象化和逻辑推理的使用,由计数.计算.量度和对物体形状及运动的观察中产生.数学家们拓展这些概 ...

  5. 密码学实验题_03.3_AES实验_利用Sage构建AES的S盒和逆S盒(基于阅读Sage数学库的Python代码)

    密码学实验题_03.3_AES实验_利用Sage构建AES的S盒和逆S盒(基于阅读Sage数学库的Python代码) 3.    AES实验 3)    (思考题)利用Sage构建AES的S盒和逆S盒 ...

  6. 豆瓣评分9分+,这6部经典趣味数学纪录片堪称神作!

    全世界只有3.14 % 的人关注了 爆炸吧知识 数学是研究数量.结构.变化以及空间模型等概念的一门学科.透过抽象化和逻辑推理的使用,由计数.计算.量度和对物体形状及运动的观察中产生.数学家们拓展这些概 ...

  7. 兔子数列规律怎么讲_探究“兔子数列”提升数学能力

    倪丽君 [摘 要]在解决问题过程中,教师一般根据问题类型进行模式教学,而建模的过程中,能力的培养则是数学教学的重点.以斐波那契数列的教学为例,通过外在的操作活动,培养学生的数学应用能力,让学生经历从形 ...

  8. 开源项目推荐:我个人中意的Python/C++/.Net数学库(★精品收藏★)

    Numpy和SciPy 大名鼎鼎的 NumPy python版本 https://github.com/numpy/numpy https://github.com/dpilger26/NumCpp  ...

  9. 数学/数论专题-学习笔记:狄利克雷卷积

    数学/数论专题-学习笔记:狄利克雷卷积 1. 前言 2. 一些基础函数 3. 积性函数 4. 狄利克雷卷积 5. 总结 6. 参考资料 1. 前言 狄利克雷卷积,是学习与继续探究 μ\muμ 函数和 ...

最新文章

  1. puppeteer php,puppeteer 页面爬取实例(元素遍历)
  2. 关于ospf区域认证以及虚链路之间的配置问题
  3. 超级实用的linux 下shell快捷键汇总
  4. 从AX4.0本地化SP2凭证系统的一个bug看UserConnection的使用
  5. UI组件:ext、JqueryEasyUI、miniui、dhtmlx及自定义页面
  6. Python利用pymysql连接Mysql数据库
  7. python编程题三
  8. 《剑指offer》-- 回溯法:矩阵中的路径、机器人的运动范围
  9. python读excel 包含格式_python里读写excel等数据文件的几种常用方式
  10. JSON学习笔记(二)- 对象
  11. 如何在 React Native 中写一个自定义模块
  12. Java使用IntelliJ IDEA创建JavaWeb应用程序并配置Tomcat
  13. [TimLinux] JavaScript AJAX接收到的数据转换为JSON格式
  14. 删除Flex Builder中没用的工作空间
  15. java接口文档怎么写_如何写好API接口文档
  16. arm板gdb调试移植
  17. php大道至简之框架
  18. 怎样赚钱?互联网赚钱才是草根最好的方式!
  19. switch监听android代码,Android switch当代码setCheck时,不调用onCheckedChanged
  20. JavaScript实现注册功能

热门文章

  1. Java基础阶段界面的登录界面设计
  2. 利用copy命令合成一个图片马使用
  3. 编程之类的文案_有什么有逼格的四字文案?
  4. Oracle SQL的多表查询 看这一篇文章就够了~
  5. mht转换html delphi,delphi – 创建*. Mht文件(网络档案)
  6. linux安装搜狗中文,Ubuntu 17.04 安装搜狗中文输入法
  7. 个人怎么做独立站Shopify商店!Shopify建站教程详解!(实操干货)
  8. 题库(3)_计算圆周率Π
  9. EOJ 3256:拼音魔法
  10. slowfast网络解读