前提知识:多面体表面

多面体表面是通过点(vertices)、边(edges)、没有洞的面(facets) 入射关系(incidence relationship)表示的。属于二维可定向流形(简单来说是分里面和外面的,莫比乌斯环属于不可定向流形)的多面体表面可以通过半边(halfedge)来存储这些结构。

所谓半边,是指构成多面体表面每条边的两条方向相反的半边。

如上图所示,多面体的每一个面(facets)是由一串有顺序的循环的半边定义的,这些半边是该面的边缘。

在三维空间中,多面体表面是一个封闭的表面,这要求构成多面体的面不可以有洞。一个洞周围的半边被称为border halfedge,border halfedge是没有incident facet的(也就是面的某条半边没有对面的那条半边)。一条边是border halfedge当且仅当它的其中一条halfedge是border halfedge。因此,如果一个表面不含border halfedge,那它就是封闭的,至少需要两个其他的面与之相邻。

人为规定,从多面体的外部观察,围绕面的半边按照逆时针排列,而这就意味着点周围的半边是按照顺时针排列的。

代码:

//构建一个正四面体,以off格式输出到屏幕并写入off文件#include <CGAL/Simple_cartesian.h>#include <CGAL/Polyhedron_3.h>#include <iostream>#include <fstream>typedef CGAL::Simple_cartesian<double>               Kernel;typedef Kernel::Point_3                              Point_3;typedef CGAL::Polyhedron_3<Kernel>                   Polyhedron;typedef Polyhedron::Facet_iterator                   Facet_iterator;typedef Polyhedron::Halfedge_around_facet_circulator Halfedge_facet_circulator;int main() {    /*--step 1. 建立正四面体--*/    //设置四面体的4个顶点,类型为Point_3(const)    Point_3 p(0.0, 0.0, 0.0);//点(0.0,0.0,0.0)    Point_3 q(1.0, 0.0, 0.0);//点(1.0,0.0,0.0)    Point_3 r(0.0, 1.0, 0.0);//点(0.0,1.0,0.0)    Point_3 s(0.0, 0.0, 1.0);//点(0.0,0.0,1.0)    //建立多面体变量P    Polyhedron P;    //从点p,q,r,s构建一个四面体,返回入射顶点初始化为p的四面体的半边。    P.make_tetrahedron(p, q, r, s);    /*--step 2. 准备输出--*/    //将IO流std::cout的格式设置为ascii码    CGAL::set_ascii_mode(std::cout);    //step 2.1 输出到屏幕    //OFF文件格式    /*--------------------------------------------------------------------------------------------------        OFF文件全是以OFF关键字开始的ASCII文件。        下一行说明顶点的数量、面片的数量、边的数量。边的数量可以安全地省略。        顶点按每行一个列出x、y、z坐标。        在顶点列表后,面片按照每行一个列表,对于每个面片,顶点的数量是指定的,接下来是顶点索引列表。        例如:        OFF        顶点数 面片数 边数(总是0)        x y z        x y z         ...        n个顶点 顶点1的索引 顶点2的索引 … 顶点n的索引(顶点索引从0开始)        ...    ----------------------------------------------------------------------------------------------------*/   //输出关键字OFF,顶点数,面数,边数(0)    std::cout << "OFF" << std::endl << P.size_of_vertices() << ' '        << P.size_of_facets() << " 0" << std::endl;    //将多面体P点序列p,q,r,s连续(iterator)写入(std::copy)输出流(std::ostream)中,并打印在屏幕上    std::copy(P.points_begin(), P.points_end(),        std::ostream_iterator<Point_3>(std::cout, "\n"));    //输出每个面的顶点索引列表    for (Facet_iterator i = P.facets_begin(); i != P.facets_end(); ++i) {//迭代所有面        Halfedge_facet_circulator j = i->facet_begin();//围绕面的半边        CGAL_assertion(CGAL::circulator_size(j) >= 3);//使用断言检查每个面至少是三角形(有三条半边)(没有洞)        std::cout << CGAL::circulator_size(j) << ' ';//输出面的顶点数        do {            std::cout << ' ' << std::distance(P.vertices_begin(), j->vertex());//通过计算两个迭代器间的距离(中间有多少个元素)计算点索引号        } while (++j != i->facet_begin());//一个面的循环结束        std::cout << std::endl;    }//多面体循环结束    //step 2.2 输出到文件    //文件指针F    std::ofstream F;    //使用写方式创建并打开文件regular_tetrahedron.off        F.open("data/regular_tetrahedron.off");    //输出关键字OFF,顶点数,面数,边数(0)    F << "OFF" << std::endl << P.size_of_vertices() << ' '        << P.size_of_facets() << " 0" << std::endl;     std::copy(P.points_begin(), P.points_end(),        std::ostream_iterator<Point_3>(F, "\n"));    for (Facet_iterator i = P.facets_begin(); i != P.facets_end(); ++i) {        Halfedge_facet_circulator j = i->facet_begin();        CGAL_assertion(CGAL::circulator_size(j) >= 3);        F << CGAL::circulator_size(j) << ' ';        do {            F << ' ' << std::distance(P.vertices_begin(), j->vertex());        } while (++j != i->facet_begin());        F << std::endl;    }    //关闭文件    F.close();    //程序结束    return 0;}

结果

  • 输出:

  • 使用meshlab查看off文件:

参考

CGAL文档

https://doc.cgal.org/latest/Polyhedron/index.html

一位好心人的翻译

https://www.douban.com/note/545941784/

关于OFF文件格式

https://blog.csdn.net/A_L_A_N/article/details/84874463

P.S. 我的公众号

[CGAL]建立一个正四面体相关推荐

  1. 建立一个php 基础类

    在些PHP文件的时候,一般首先都是要先写一下基础类: 主要包括以下几个方面: 1.服务器的链接:包括主机,用户名,密码 2.数据库的选择:要操作哪个数据库 3.字符集的设置:设置什么样的编码 4.查询 ...

  2. 用matlab自己搭建bp神经网络,怎样在matlab里建立一个BP神经网络模型?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 用以下的数据怎样在matlab里建立一个BP神经网络模型?求高手帮忙!!最好是有详细步骤以及代码 年份 WTI(美元/桶) 2007-1 54.26 20 ...

  3. bulma.css_如何建立一个? 具有Bulma CSS的特斯拉响应页面

    bulma.css by ZAYDEK 由ZAYDEK 0-60 in 1.9s? (0-60 in 1.9s ?) 如何建立一个? 具有Bulma CSS的特斯拉响应页面 (How To Build ...

  4. linux用户在哪个文件夹,LINUX中用命令成功建立一个用户后信息会记录在哪个文件中...

    LINUX中用命令成功建立一个用户后信息会记录在哪个文件中 发布时间:2007-07-28 10:14:57来源:红联作者:MPiops 增加用户帐号后 新建用户的命令十分简单,在命令行下使用 use ...

  5. 建立一个按年龄排序的有序链表,每个结点包括学号、姓名、性别、年龄。建立一个新的结点,通过年龄将此结点插入到链表中去,使之仍然有序

    <程序设计基础实训指导教程-c语言> ISBN 978-7-03-032846-5 p143 7.1.2 上级实训内容 [实训内容12]建立一个按年龄排序的有序链表,每个结点包括学号.姓名 ...

  6. 吴恩达:如何建立一个成功的人工智能创业公司

    # 吴恩达:如何建立一个成功的人工智能创业公司 # 很多初创企业的失败都来自于产品制造,因为他们的产品没人想要.我本身倾向于结果以及客户驱动的商业模式.只有当客户决定给你的产品伸大拇指,还是小拇指的时 ...

  7. 周鸿祎谈抢票:技术推动建立一个高效的公平社会

    <周鸿祎谈抢票:技术推动建立一个高效的公平社会>,原文链接:http://news.cnblogs.com/n/170178/ 分享自:博客园Android客户端(http://andro ...

  8. bat 删除文件_利用电脑文本文档建立一个简单方便的删除文件的小程序

    删除文不需要的文件或者资料,是日常工作中必定会遇到了. 各种的杀毒软件或者防护软件都具备删除文件的功能,例如360.腾讯电脑管家.这些操作起来其实也不是太麻烦! 不过呢!今天来和大家分享一个更简单的方 ...

  9. 建立一个Web项目及一些错误解决办法

    培训之前,先自学一波,写一个从Hello World,然后记录一下每天学习Java Web的过程:东西很多,有用的会写大量解释,希望能最终学完 然后搞定这门语言吧. 1.配置tomacat:点击win ...

  10. tensorflow学习笔记二——建立一个简单的神经网络拟合二次函数

    tensorflow学习笔记二--建立一个简单的神经网络 2016-09-23 16:04 2973人阅读 评论(2) 收藏 举报  分类: tensorflow(4)  目录(?)[+] 本笔记目的 ...

最新文章

  1. DuiLib学习笔记5——标题栏不能正常隐藏问题
  2. linux内核编译感想,Linux内核编译小结
  3. IDEA把Java Web导出为war文件
  4. mysql 嵌入式_MySql移植到嵌入式Linux平台
  5. java 接口中变量修饰符,Java的访问修饰符与变量的作用域讲解
  6. 找出没有出现的数 题解
  7. 前端基础7:a标签常用方法和元素居中方式,响应式@media
  8. 常用1寸,2寸照片标准尺寸
  9. 微博简单的免登陆获取
  10. 输入大写字母,将大写字母转换为小写字母
  11. error:crosses initialization of
  12. AMD和英特尔cpu区别
  13. Wap Push 源码java实现
  14. gird布局之容器属性justify-items与align-items
  15. 计算机专业对于未来的规划,对所学专业的认识及对未来的规划.doc
  16. 少儿C++编程从入门到进阶 信奥学奥赛从启蒙到NOI、ACM-ICPC(一)
  17. JS实现表格增、删、排序
  18. 阿里云神龙团队拿下 TPCx-BB 排名第一的背后技术
  19. 读取超大json文件中数据格式的方法
  20. 总结XSS与CSRF两种跨站攻击

热门文章

  1. 微信多客服系统开发教程
  2. NOWCODER 虚无的后缀(贪心)
  3. 虚无缥缈的代码到底是如何控制硬件工作的?
  4. 我是个Java开发者,我到底要不要学大数据开发?
  5. 【读书有感】——你只是看起来很努力
  6. linux修改mac地址_如何(以及为什么)在Windows,Linux和Mac上更改您的MAC地址
  7. 2020最新中高阶Android面试题总结-上(附解题思路)
  8. mysql将公历农历转换_SQL农历转换函数(显示中文格式,加入润月的显示)
  9. Accumulator Proof解析
  10. [Python3]利用tkinter为数独计算器编写GUI