CGAL编程实现点集的Delaunay三角剖分和Voronoi图

安装 QT 4.6.3

安装 QT 4.6.3

1.安装MinGW,C:\MinGW\bin添加到环境变量。

2.下载 QT 最新版本 4.6.3

http://www.qtsoftware.com/downloads/windows-cpp

3.运行 QT 的安装程序,忽视关于版本兼容性的报警信息

4.打开 Visual Studio的命令提示窗口

cd c:\QT\4.6.3

configure -platform win32-msvc2008

5.configure 完成后,输入 nmake,大概等待5个小时。

6.将 C:\Qt\4.6.3\bin添加到环境变量中



CGAL编程实现点集的Delaunay三角剖分和Voronoi图

//使用CGAL编程实现点集的Delaunay三角剖分,voronoi图
//如果对Delaunay算法本身关注,请参考CGAL对Delaunay三角剖分的实现,CGAL对Delaunay三角剖分的实现是增量算法(Incremental)
//本程序的重点在于对CGAL中Delaunay数据结构的访问,请参考函数points_triangulation()。初次使用CGAL,不妥之处请多指正,谢谢。

//SudoLeo 2010/7/20
//CGAL required, GLUT required

代码 


//使用CGAL编程实现点集的Delaunay三角剖分,voronoi图
//如果对Delaunay算法本身关注,请参考CGAL对Delaunay三角剖分的实现,CGAL对Delaunay三角剖分的实现是增量算法(Incremental)
//本程序的重点在于对CGAL中Delaunay数据结构的访问,请参考函数points_triangulation()

//SudoLeo 2010/7/20
//CGAL required, GLUT required

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_euclidean_traits_xy_3.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <GL/glut.h>
#include <iostream>
#include <cmath>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Delaunay_triangulation_2<K> Delaunay;
typedef Delaunay::Vertex_handle Vertex_handle;

typedef K::Point_2 Point;

std::vector<Point> vertices;

int global_w, global_h;
int tri_state = 0;

void points_draw()
{
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();

std::vector <Point>::iterator iter;
glColor3f( 1.0, 1.0, 1.0 );
glPointSize(5);
glBegin(GL_POINTS);
for( iter = vertices.begin(); iter != vertices.end(); iter++ )
glVertex2i( iter->hx(), iter->hy() );
glEnd();

glPopMatrix();
glutSwapBuffers();
}

void points_add_point( int x, int y )
{ 
vertices.push_back( Point( x, global_h-y ) );
}


void points_clear()
{
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glPopMatrix();
glutSwapBuffers();

vertices.clear();
tri_state = 0;
}

void read_file()//从文件中读入点集数据,调试时所使用
{
FILE* f;
f = freopen( "data.txt", "r", stdin );

int a,b;
while(std::cin>>a >> b)
{
vertices.push_back( Point( a, b ) );
}

fclose(f);
}

void points_triangulation()
{
Delaunay dt;//Delaunay数据结构,代表当前数据的一个且仅有一个的三角剖分,详情请参考CGAL_manual

dt.insert(vertices.begin(), vertices.end());//输入数据

points_draw();//points_draw()函数中已经调用一次glutSwapBuffers(),本函数再一次调用glutSwapBuffers()
//在一帧的绘制中两次调用glutSwapBuffers(),虽对本例无影响,但存在一些问题,这不是本文的重点,可暂且忽略之

glPushMatrix();

Delaunay::Finite_faces_iterator fit;//遍历Delaunay的所有面(有限面),将每个面的边画出来
glColor3f( 0.0, 0.0, 1.0 );
for( fit = dt.finite_faces_begin(); fit != dt.finite_faces_end(); fit ++)
{
glBegin(GL_LINE_LOOP);
glVertex2i( fit->vertex(0)->point().hx(), fit->vertex(0)->point().hy() );
glVertex2i( fit->vertex(1)->point().hx(), fit->vertex(1)->point().hy() );
glVertex2i( fit->vertex(2)->point().hx(), fit->vertex(2)->point().hy() );
glEnd();
}//完成Delaunay三角剖分的绘制,Delaunay图

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

glEnable( GL_LINE_STIPPLE );//使用点画模式,即使用虚线来绘制Voronoi图
glLineStipple( 1, 0x3333 );
glColor3f( 0.0, 1.0, 0.0 );

for( eit = dt.edges_begin(); eit != dt.edges_end(); eit ++)
{
CGAL::Object o = dt.dual(eit);//边eit在其对偶图中所对应的边

if (CGAL::object_cast<K::Segment_2>(&o)) //如果这条边是线段,则绘制线段
{
glBegin(GL_LINES);
glVertex2i( CGAL::object_cast<K::Segment_2>(&o)->source().hx(), CGAL::object_cast<K::Segment_2>(&o)->source().hy() );
glVertex2i( CGAL::object_cast<K::Segment_2>(&o)->target().hx(), CGAL::object_cast<K::Segment_2>(&o)->target().hy() );
glEnd();
}
else if (CGAL::object_cast<K::Ray_2>(&o))//如果这条边是射线,则绘制射线
{
glBegin(GL_LINES);
glVertex2i( CGAL::object_cast<K::Ray_2>(&o)->source().hx(), CGAL::object_cast<K::Ray_2>(&o)->source().hy() );
glVertex2i( CGAL::object_cast<K::Ray_2>(&o)->point(1).hx(), CGAL::object_cast<K::Ray_2>(&o)->point(1).hy() );
glEnd();
}
}
glDisable( GL_LINE_STIPPLE );//关闭点画模式

glPopMatrix();
glutSwapBuffers();

tri_state = 1;//完成三角剖分,置状态为1
}

void display(void)
{
}

void init(void) 
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);

}

void reshape(int w, int h)
{
global_w = w;
global_h = h;
points_clear();

glViewport (0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glOrtho(0, w, 0, h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void mouse(int button, int state, int x, int y) 
{
if ( button == GLUT_LEFT_BUTTON && state == GLUT_UP )
{
if( tri_state == 1 ) points_clear();
else 
{
points_add_point(x,y);
//read_file();
points_draw();
}
}
if ( button == GLUT_RIGHT_BUTTON && state == GLUT_UP ) 
{
if( tri_state == 1 ) points_clear();
else points_triangulation();
}
}

void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (800, 600); 
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display); 
glutReshapeFunc(reshape); 
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Delaunay三角剖分是计算机形学中常用的方法,它是将点云转化为无重叠的三角形集合的过程。对于三维点云而言,我们可以利用C++语言编写Delaunay三角剖分的源代码。 具体而言,我们需要借助第三方库来完成这个过程。例如,我们可以使用CGAL库中的Delaunay_triangulation_3类来实现三维点云的Delaunay三角剖分。在使用该类之前,我们需要将点云转化为一系列顶点,将顶点作为参数传入Delaunay_triangulation_3类的对象中。 在通过Delaunay_triangulation_3类计算Delaunay三角剖分后,我们可以通过遍历三角形集合,计算每个三角形的顶点坐标和法向量,从而得到三维点云的表面重建结果。 需要注意的是,Delaunay三角剖分的结果可能会产生“拟合问题”,即存在一些三角形的边缘与点云的表面重建结果不完全吻合。为了解决这个问题,我们可以使用一些优化方法,例如对三角形的边缘进行局部调整,以提高重建结果的精度。 总之,通过编写三维点云Delaunay三角剖分的源代码,我们可以将点云转化为一系列无重叠的三角形,从而实现三维模型的重建。 ### 回答2: 三维点云 delaunay 三角剖分是一种将无序的三维点云数据转化为三角形面片的方法,可以在三维建模、地质勘探等领域中应用。其源代码一般采用 C++ 编写,下面简单介绍其实现。 三维点云 delaunay 三角剖分主要分为以下几步: 1. 构建超级三角形。为了保证所有点都在三角剖分内部,需要在点云的边界之外添加一个超级三角形(一般为一个比点云面积大的等边三角形),保证所有点都在其内部。 2. 将点逐一插入。从点云中随机选取一个点开始,将其插入到当前三角剖分中。插入过程中会检查新插入点与其它三角形的关系,同时进行三角形翻转和边的反转等操作以维护 delaunay 三角剖分的特性。 3. 剖分收敛。当所有点都插入完成后,需要对剩余的三角形进行处理,将所有与超级三角形相交的三角形删除,以得到最终的三角剖分结果。 其源代码主要包括点的数据结构定义、超级三角形的构建、插入点和剖分收敛等函数的实现。在实现中需要注意,对于边界点或重复点等特殊情况需要进行处理,同时可根据具体应用场景做出一些优化。 ### 回答3: 三维点云的Delaunay三角剖分源代码是一个算法实现,可以将一个三维点云数据集转化为一组无重叠三角形的连接。这个算法通常由C++实现,并且主要包含以下步骤: 首先,需要定义一个三维点云数据结构,用于存储所有的点。然后,通过半边数据结构来表示三角形的连接关系,并创建一个起始三角形,该三角形的外接圆可以囊括所有的点。 接下来,使用一个扫描线算法来生成三角剖分。该算法主要通过在扫描线上移动,并利用拐角点的概念来不断更新Delaunay三角形网格。在每个点上,都会查找在当前点的左侧和右侧的最高顶点,并通过一个旋转操作来更新三角形的连接关系。 通过以上步骤,就可以生成一个Delaunay三角剖分,其中每个三角形都与它的外接圆不包含任何点。这个算法在计算几何和计算机形学领域十分流行,并且有多种优化和扩展,可以更好地满足具体应用的需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值