[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. 我的公众号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值