[CGAL]建立一个正四面体
前提知识:多面体表面
多面体表面是通过点(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]建立一个正四面体相关推荐
- 建立一个php 基础类
在些PHP文件的时候,一般首先都是要先写一下基础类: 主要包括以下几个方面: 1.服务器的链接:包括主机,用户名,密码 2.数据库的选择:要操作哪个数据库 3.字符集的设置:设置什么样的编码 4.查询 ...
- 用matlab自己搭建bp神经网络,怎样在matlab里建立一个BP神经网络模型?
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 用以下的数据怎样在matlab里建立一个BP神经网络模型?求高手帮忙!!最好是有详细步骤以及代码 年份 WTI(美元/桶) 2007-1 54.26 20 ...
- bulma.css_如何建立一个? 具有Bulma CSS的特斯拉响应页面
bulma.css by ZAYDEK 由ZAYDEK 0-60 in 1.9s? (0-60 in 1.9s ?) 如何建立一个? 具有Bulma CSS的特斯拉响应页面 (How To Build ...
- linux用户在哪个文件夹,LINUX中用命令成功建立一个用户后信息会记录在哪个文件中...
LINUX中用命令成功建立一个用户后信息会记录在哪个文件中 发布时间:2007-07-28 10:14:57来源:红联作者:MPiops 增加用户帐号后 新建用户的命令十分简单,在命令行下使用 use ...
- 建立一个按年龄排序的有序链表,每个结点包括学号、姓名、性别、年龄。建立一个新的结点,通过年龄将此结点插入到链表中去,使之仍然有序
<程序设计基础实训指导教程-c语言> ISBN 978-7-03-032846-5 p143 7.1.2 上级实训内容 [实训内容12]建立一个按年龄排序的有序链表,每个结点包括学号.姓名 ...
- 吴恩达:如何建立一个成功的人工智能创业公司
# 吴恩达:如何建立一个成功的人工智能创业公司 # 很多初创企业的失败都来自于产品制造,因为他们的产品没人想要.我本身倾向于结果以及客户驱动的商业模式.只有当客户决定给你的产品伸大拇指,还是小拇指的时 ...
- 周鸿祎谈抢票:技术推动建立一个高效的公平社会
<周鸿祎谈抢票:技术推动建立一个高效的公平社会>,原文链接:http://news.cnblogs.com/n/170178/ 分享自:博客园Android客户端(http://andro ...
- bat 删除文件_利用电脑文本文档建立一个简单方便的删除文件的小程序
删除文不需要的文件或者资料,是日常工作中必定会遇到了. 各种的杀毒软件或者防护软件都具备删除文件的功能,例如360.腾讯电脑管家.这些操作起来其实也不是太麻烦! 不过呢!今天来和大家分享一个更简单的方 ...
- 建立一个Web项目及一些错误解决办法
培训之前,先自学一波,写一个从Hello World,然后记录一下每天学习Java Web的过程:东西很多,有用的会写大量解释,希望能最终学完 然后搞定这门语言吧. 1.配置tomacat:点击win ...
- tensorflow学习笔记二——建立一个简单的神经网络拟合二次函数
tensorflow学习笔记二--建立一个简单的神经网络 2016-09-23 16:04 2973人阅读 评论(2) 收藏 举报 分类: tensorflow(4) 目录(?)[+] 本笔记目的 ...
最新文章
- DuiLib学习笔记5——标题栏不能正常隐藏问题
- linux内核编译感想,Linux内核编译小结
- IDEA把Java Web导出为war文件
- mysql 嵌入式_MySql移植到嵌入式Linux平台
- java 接口中变量修饰符,Java的访问修饰符与变量的作用域讲解
- 找出没有出现的数 题解
- 前端基础7:a标签常用方法和元素居中方式,响应式@media
- 常用1寸,2寸照片标准尺寸
- 微博简单的免登陆获取
- 输入大写字母,将大写字母转换为小写字母
- error:crosses initialization of
- AMD和英特尔cpu区别
- Wap Push 源码java实现
- gird布局之容器属性justify-items与align-items
- 计算机专业对于未来的规划,对所学专业的认识及对未来的规划.doc
- 少儿C++编程从入门到进阶 信奥学奥赛从启蒙到NOI、ACM-ICPC(一)
- JS实现表格增、删、排序
- 阿里云神龙团队拿下 TPCx-BB 排名第一的背后技术
- 读取超大json文件中数据格式的方法
- 总结XSS与CSRF两种跨站攻击