Ubuntu下改编了一个用CGAL计算输入点的三角剖分,并用OpenGL显示结果的C++程序。
该Demo可作为一个计算几何及绘图的框架。
代码如下:
//编译命令:g++ spatial_sort.cpp -lglut -lGL -lGLU -lCGAL -lCGAL_Core -lgmp
#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>
#include <time.h>
using namespace std;
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, mypts;
int global_w, global_h;
//绘制用户添加的点Pt(hx(), hy())
void points_draw()
{
glPushMatrix();
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
std::vector <Point>::iterator iter;
glColor3f( 1.0, 1.0, 1.0 );
glPointSize(8);
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();
}
//计算点的三角剖分————Delaunary
void points_triangulation()
{
//Delaunay数据结构,代表当前数据的一个且仅有一个的三角剖分,详情请参考CGAL_manual
Delaunay dt;
//将所有点加入dt
dt.insert(vertices.begin(), vertices.end());//输入数据
//开始绘制
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();
}
void display(void)
{
//清除屏幕内容
/*
glClear(GL_COLOR_BUFFER_BIT);
points_triangulation();
points_draw();
//刷新结果
glFlush() ;
glutSwapBuffers();
*/
}
//初始化背景与shade模式
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;
//设置视口属性
glViewport (0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//设置坐标系
glOrtho(0, w, 0, h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//重新绘制点
points_draw();
}
//鼠标事件处理
void mouse(int button, int state, int x, int y)
{
//如果按下鼠标左键,则添加点
if ( button == GLUT_LEFT_BUTTON )
{
points_add_point(x,y);
points_draw();
}
//若按下右键,则绘制三角剖分结果---计算
if ( button == GLUT_RIGHT_BUTTON )
points_triangulation();
}
//键盘事件处理
void keyboard(unsigned char key, int x, int y)
{
//按下ESC键,则程序退出
switch (key) {
case 'c':
points_clear();
break;
case 'r':
points_draw();
break;
case ' ':
points_triangulation();
break;
case 's':
break; //save_as_png('test.png');
case 27 :
case 'x':
exit(0);
break;
}
}
//主函数
int main(int argc, char** argv)
{
//初始化随机种子
srand(time(NULL));
//glutInit...
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (800, 600); //设置窗口宽度和高度
glutInitWindowPosition (0, 0); //初始化窗口位置
//窗口
glutCreateWindow (argv[0]);
//设置背景色及阴影模式
init();
//绘画函数
glutDisplayFunc(display);
//改变窗口大小时的绘制函数
glutReshapeFunc(reshape);
//鼠标事件处理函数
glutMouseFunc(mouse);
//键盘事件处理函数
glutKeyboardFunc(keyboard);
//无限主循环
glutMainLoop();
return 0;
}