用OpenGL实现二维图形裁剪的梁友栋-Barsky算法代码(有注释)
以下是算法代码,环境是vs2010:
梁友栋-Barsky算法主体:
//liang_barsky算法
int LBarsky(float points[2][2],float wl,float wr,float wt,float wb)
{
//points为直线的起点(x0,y0)终点(x1,y1),wl,wr,wt,wb分别为裁剪窗口的左右上下边界
//该直线需要舍弃时,返回0,否则返回1,并更新起点和终点坐标
float dx, dy, u1 = 0, u2 = 1;
float p[4] = {0}, q[4] = {0};
//计算dx,dy
dx = points[1][0] - points[0][0];
dy = points[1][1] - points[0][1];
//计算p和q
p[0] = -dx;
p[1] = dx;
p[2] = -dy;
p[3] = dy;
q[0] = points[0][0] - wl;
q[1] = wr - points[0][0];
q[2] = points[0][1] - wb;
q[3] = wt - points[0][1];
for(int i=0; i<4; i++){
float r = q[i]/p[i];
//当p为0,q小于1时舍弃
if(p[i] == 0 && q[i] < 0){
return 0;
}
//p小于0时
if(p[i] < 0){
//更新
u1 = max(u1,r);
}
//p大于0时
if(p[i] > 0){
//更新
u2 = min(u2, r);
}
}
//当u1>u2时,舍弃
if(u1>u2)
return 0;
//更新点坐标
points[1][0] = points[0][0] + u2 * dx;
points[1][1] = points[0][1] + u2 * dy;
points[0][0] += u1 * dx;
points[0][1] += u1 * dy;
return 1;
}
以下是算法其它部分,主要是画出裁剪效果
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
//4条直线的起点和终点,可以自己设置
float lines[4][2][2] = {{{100,120},{190,200}}, {{130,250},{300,350}}, {{160,160},{250,160}}, {{130,160},{140,300}}};
//裁剪窗口的左右上下边界,可以自己设置
float wl = 150, wr = 300, wt = 300, wb = 150;
//先画裁剪窗口
glBegin(GL_LINES);
glColor3f(0.0, 1.0,0.0);
glVertex2f(wl, wb);
glVertex2f(wl, wt);
glVertex2f(wr, wb);
glVertex2f(wr, wt);
glVertex2f(wl, wt);
glVertex2f(wr, wt);
glVertex2f(wr, wb);
glVertex2f(wl, wb);
glColor3f(0.0, 0.0,1.0);
//画出原直线
for(int j=0;j<4;j++){
glVertex2f(lines[j][0][0], lines[j][0][1]);
glVertex2f(lines[j][1][0], lines[j][1][1]);
}
glEnd();
//画出裁剪后的直线
for(int k=0;k<4;k++){
if(LBarsky(lines[k],wl,wr,wt,wb)!=0){
glBegin(GL_LINE_STRIP);
glColor3f(1.0, 0.0,0.0);
glVertex2f(lines[k][0][0], lines[k][0][1]);
glVertex2f(lines[k][1][0], lines[k][1][1]);
glEnd();
}
}
glFlush();
}
结果:
上图中绿色线为裁剪窗口,蓝色为直线舍弃的部分,红色为保留的部分
如果想理解算法思想原理,请移步到下面的链接:
梁友栋-Barsky算法原理