CGAL-三维Delaunay/Voronoi图/Powerdiagram

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/OOFFrankDura/article/details/81639592

综述

3D Vornoi和Powerdiagram的例子比较少。这里给出一些方法。

说明

这里给出两个版本
版本一
使用一般的RT完成
(注意在add_point中最后一个参数带权重则为powerdiagram,如果为0就为Voronoidiagram)
支持Delaunay三角的顶点输出
支持显示所有Voronoi顶点输出
(一般使用推荐使用版本一)

版本二
使用LCC map完成,数据查询更为方便,但是数据结构较难组织
支持Delaunay三角的顶点输出
支持显示所有Voronoi顶点输出
支持显示所有有限空间划分的顶点输出

更新

2018.8.14
2018.8.16 提供了一种更为普遍的方法

有网友和我交流问“3D powerdiagram”是否可以这样组织(通过三角正则化求对偶)?
事实上是不能的。
因为LCC没有Weighted_Point的类型,也就是说不支持。
所以还是要使用:
CGAL::Exact_predicates_inexact_constructions_kernel
下的
Weighted_Point;

环境

clion
maxos

代码

版本一代码

//作者:SDU窦志扬
//日期:2018/8/16
//联络:[email protected]
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Regular_triangulation_3.h>
#include <CGAL/Weighted_point_3.h>
#include <GLUT/glut.h>
#include <CGAL/bounding_box.h>
#include <fstream>
#include<iostream>
#include<set>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Regular_triangulation_3<K> Regular_triangulation;
typedef K::Vector_3                                     Vector;
typedef K::Point_3 Point;
typedef K::Weighted_point_3 Wp;
typedef K::Point_3                                     Point;
typedef CGAL::Regular_triangulation_3<K>               Rt;
using namespace std;
vector<Regular_triangulation::Weighted_point> wpoints;
vector<Point> points;
vector<double> X, Y, Z;
set<Point> Voronoi_vert;
void add_point(double x, double y, double z , double w){
    wpoints.push_back( Wp(Point(x,y,z), w) );
    points.push_back(Point(x,y,z) );
    X.push_back(x);
    Y.push_back(y);
    Z.push_back(z);

}

void display(void)
{
    add_point(100+0, 100+0,100+0,0); //左中
    add_point(100+100,100+0,100+0,0);
    add_point(100+0,100+0,100+400,0);   //目标点
    add_point(100+0, 100+200,100+0,0);
    add_point(300+0, 70+200,100+0,0);
    add_point(20+0, 19+200,80+0,0);
    add_point(100+0, 100+200,100+0,0);
    add_point(100+10, 100+20,100+20,000);
    Regular_triangulation rt(wpoints.begin(), wpoints.end());
    rt.is_valid();
    Regular_triangulation::Edge_iterator eit;
    Regular_triangulation::Point_iterator pit;

    //遍历Delaunay的所有边,绘制Delaunay图的对偶图,即Voronoi图


    cout << "====all points in rt====" << endl;
    for (auto vit = rt.vertices_begin(); vit != rt.vertices_end(); ++vit){
        cout << vit->point() << endl;

    }
    cout << "==== Voronoi vert ====" << endl;
    Rt::Finite_edges_iterator fei;
    for (fei = rt.finite_edges_begin(); fei != rt.finite_edges_end(); fei++)
    {
        //遍历每个边
        auto face = rt.incident_facets(*fei);
        auto face_start = face;
        //找到与边相邻的面(更准确的,遍历每个邻接面)
        do {
            CGAL::Object  dualedge = rt.dual(*face);
            //找到面对应的边
            if (CGAL::object_cast<Rt::Segment>(&dualedge))
            {
                Point source = CGAL::object_cast<Rt::Segment>(&dualedge)->source();
                Point target = CGAL::object_cast<Rt::Segment>(&dualedge)->target();
                Voronoi_vert.insert(source);
                Voronoi_vert.insert(target);
            } else if (CGAL::object_cast<Rt::Ray>(&dualedge))//如果这条边是射线,则绘制射线
            {
                Point target = CGAL::object_cast<Rt::Ray>(&dualedge)->source();
                Voronoi_vert.insert(target);
            }
            ++face;
        } while (face_start != face);
    }

}
int main(int argc, char *argv[]) {

    display();
    set<Point>::iterator iter=Voronoi_vert.begin();
    while(iter!=Voronoi_vert.end())
    {
        cout<<*iter<<endl;
        ++iter;
    }
    return 0;
}

版本二代码

/*
 * 作者:窦志扬
 * 日期:2018年8月13日
 * 联络:[email protected]
 * 院校:山东大学
 * */
#include <CGAL/Linear_cell_complex_for_combinatorial_map.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <CGAL/Triangulation_3_to_lcc.h>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
typedef CGAL::Linear_cell_complex_for_combinatorial_map<3> LCC_3;
typedef LCC_3::Dart_handle                                 Dart_handle;
typedef LCC_3::Point                                          Point;
typedef CGAL::Delaunay_triangulation_3<LCC_3::Traits> Triangulation;
using namespace std;
void remove_the_infinite_volume(LCC_3 &alcc, Dart_handle adart)
{
    /*
     * 该方法参考cgal 方法
     * */
    std::stack<Dart_handle> toremove;
    LCC_3::size_type mark_toremove=alcc.get_new_mark();
    toremove.push(adart);
    CGAL::mark_cell<LCC_3,3>(alcc, adart, mark_toremove);
    //首先记录需要去除的无限区域
    for (LCC_3::Dart_of_cell_range<3>::iterator
                 it=alcc.darts_of_cell<3>(adart).begin(),
                 itend=alcc.darts_of_cell<3>(adart).end(); it!=itend; ++it)
    {
        if ( !alcc.is_marked(alcc.beta(it,3), mark_toremove) )
        {
            CGAL::mark_cell<LCC_3,3>(alcc, alcc.beta(it,3), mark_toremove);
            toremove.push(alcc.beta(it,3));


        }
    }


    while( !toremove.empty() )
    {
        Dart_handle tem = toremove.top();
        alcc.remove_cell<3>(tem);

        toremove.pop();
    }

    CGAL_assertion(alcc.is_without_boundary(1) && alcc.is_without_boundary(2));

    std::cout<<"Voronoi subdvision, only finite volumes:"<<std::endl<<"  ";
    alcc.display_characteristics(std::cout) << ", valid="
                                            << alcc.is_valid()
                                            << std::endl; std::cout<<"Voronoi剖分中所有的有限空间点: "<< endl;
    for (LCC_3::Vertex_attribute_const_range::iterator
                 v=alcc.vertex_attributes().begin(),
                 vend=alcc.vertex_attributes().end();
         v!=vend; ++v)
        std::cout <<"v "<< alcc.point_of_vertex_attribute(v) << endl;
    std::cout<<std::endl;
}


template<typename LCC, typename TR>
void transform_dart_to_their_dual(LCC& alcc, LCC& adual,
                                  std::map<typename TR::Cell_handle,
                                          typename LCC::Dart_handle>& assoc)
{
    typename LCC::Dart_range::iterator it1=alcc.darts().begin();
    typename LCC::Dart_range::iterator it2=adual.darts().begin();

    std::map<typename LCC::Dart_handle, typename LCC::Dart_handle> dual;

    for ( ; it1!=alcc.darts().end(); ++it1, ++it2 )
    {
        dual[it1]=it2;
    }

    for ( typename std::map<typename TR::Cell_handle, typename LCC::Dart_handle>
    ::iterator it=assoc.begin(), itend=assoc.end(); it!=itend; ++it)
    {
        assoc[it->first]=dual[it->second];
    }
}

template<typename LCC, typename TR>
void set_geometry_of_dual(LCC& alcc, TR& tr,
                          std::map<typename TR::Cell_handle,
                                  typename LCC::Dart_handle>& assoc)
{
    for ( typename std::map<typename TR::Cell_handle, typename LCC::Dart_handle>
    ::iterator it=assoc.begin(), itend=assoc.end(); it!=itend; ++it)
    {
        if ( !tr.is_infinite(it->first) )
            alcc.set_vertex_attribute
                    (it->second,alcc.create_vertex_attribute(tr.dual(it->first)));
        else
            alcc.set_vertex_attribute(it->second,alcc.create_vertex_attribute());
    }
}



int main()
{

    char*input1 =  "/Users/frankdura/Desktop/222.txt";


    vector<Point> boundaryPoints;  //装载边界点
    ifstream in_boundary(input1);
    Point p;
    while (in_boundary >> p){   //读入边界点
        cout << p << endl;
        boundaryPoints.push_back(p);
    }
    cout << "read in vertexs: " << boundaryPoints.size() << endl;
    in_boundary.close();

    //请输入您的剖分点

    Triangulation T;//用于三角剖分
    T.insert(boundaryPoints.begin(), boundaryPoints.end());
    LCC_3 lcc;
    std::map<Triangulation::Cell_handle,
            LCC_3::Dart_handle > vol_to_dart;

    Dart_handle dh=CGAL::import_from_triangulation_3<LCC_3, Triangulation>
            (lcc, T, &vol_to_dart);

    std::cout<<"Delaunay triangulation :"<<std::endl<<"  ";
    lcc.display_characteristics(std::cout) << ", valid="
                                           << lcc.is_valid() << std::endl;


    CGAL::set_ascii_mode(std::cout);
    std::cout<<"狄洛尼三角剖分顶点: "<< endl;
    for (LCC_3::Vertex_attribute_const_range::iterator
                 v=lcc.vertex_attributes().begin(),
                 vend=lcc.vertex_attributes().end();
         v!=vend; ++v)
        std::cout << lcc.point_of_vertex_attribute(v) << "\n\r";
    std::cout<<std::endl;
    cout <<"end"<< endl;
    LCC_3 dual_lcc;
    Dart_handle ddh=lcc.dual(dual_lcc, dh);
    // Here, dual_lcc is the 3D Voronoi diagram.
    CGAL_assertion(dual_lcc.is_without_boundary());

    transform_dart_to_their_dual<LCC_3,Triangulation>
            (lcc, dual_lcc, vol_to_dart);
    set_geometry_of_dual<LCC_3,Triangulation>(dual_lcc, T, vol_to_dart);

    // 5) Display the dual_lcc characteristics.
    std::cout<<"Voronoi剖分信息 :"<<std::endl<<"  ";
    dual_lcc.display_characteristics(std::cout) << ", valid="
                                                << dual_lcc.is_valid()
                                                << std::endl;


    std::cout<<"Voronoi剖分中所有点: "<< endl;
    for (LCC_3::Vertex_attribute_const_range::iterator
                 v=dual_lcc.vertex_attributes().begin(),
                 vend=dual_lcc.vertex_attributes().end();
         v!=vend; ++v)
        std::cout <<"v " <<dual_lcc.point_of_vertex_attribute(v) << endl;
    remove_the_infinite_volume(dual_lcc, ddh);

    return EXIT_SUCCESS;
}

猜你喜欢

转载自blog.csdn.net/OOFFrankDura/article/details/81639592