OpenGl----Cohen-Sutherland算法

                                              Cohen-Sutherland

一、剪裁原理:

Cohen-Sutherland算法:对于每一条线段P1P2分成了三种情况(1)P1P2完全在窗口之内,则显示该线段P1P2。(2)P1P2在窗口之外,则丢弃该线段.(3)如果该线段一部分在窗口之外,一部分在窗口之内,那么就将窗口之外的丢弃,窗口之内的重复上述理.

   对于代码中的P1和P2所在的区号code1和code2.如果code1=0且code2=0,则说明P1和P2均在窗口之内,那么整条线应必在窗口内,应取之。若code1与code2经按位运算后的结果code1&code2不为0,则说明两个端点同在窗口的上方、下方、左方、右方。例如code1=0101,code2=0110,code1&code2=0100的左起第二位不为0,这说明两端点均在窗口的下方,在这种情况,可判断线段完全在窗口外,可弃之。

  若线段的端点P1P2所在的区编码均不为零,但code1&code2=0,故属于第三种情况,由code1=0001知P1在窗口的左边,计算线段与窗口左边界的交点P3.P1P3必在窗口外,可弃之。对于线段P3P2重复上述定理.由于P3的区域编码为0000,说明P3已在窗口内。P2的区域编码为code2=0100,则说明P2在窗口之外,code2的左起第二位不为零,说明P2在窗口的下方,用窗口的下边界与线段求交点P4,丢弃P4P2,剩下的线段P3P4就全在窗口之中。

二、实现代码

#include <GL/glut.h>
#include <cstdio>
#define LEFT 1//0001
#define RIGHT 2//0010
#define BOTTOM 4//0100
#define TOP 8//1000
int x1 = 150, y1 = 50, x2 = 50, y2 = 250, XL = 100, XR = 300, YB = 100, YT = 200;  //(x1,y1)、(x2,y2)为直线段的端点,XL为左边界,XR为右边界,YB为下边界,YT为上边界
int x1_init = 150, y1_init = 50, x2_init = 50, y2_init = 250;  //将直线段端点备份,以便画出裁剪前的直线段
void encode(int x, int y,int &c)
{//|或运算两者有一个为1结果就为1
	c = 0;
	if (x < XL) c |= LEFT;//按照数字进行或运算,左边界
	else if (x > XR) c |= RIGHT;//右边界
	if (y < YB) c |= BOTTOM;//下边界
	else if (y > YT) c |= TOP;//上边界
}
//上左:1001; 中左:0001; 下左:0101;
//上中:1000; 中中:0000 下中:0100
//上右:1010  中右:0010  下右:0110
void CS_LineClip()  //Cohen-Sutherland裁剪算法
{
	int x, y;
	int code1, code2, code;
    encode(x1, y1, code1);//先求出端点所在的区号
    encode(x2, y2, code2);//先求出端点所在的区号
	//循环处理
	while (code1 != 0 || code2 != 0)//只有两个端点同时都在矩形区域里才不使用函数
	{
		if (code1 & code2)//两个都为1才成立,这两个都在同一个区域中 直接不进行处理
			return;
		if (code1 != 0)//如果
			code = code1;
		else
			code = code2;

		if (LEFT & code)//线段与左边界相交(如果
		{
			x = XL;//求出的左边界的交点的x值
			y = y1 + (y2 - y1)*(XL - x1) / (x2 - x1);//求出左边交点的y值
		}
		else if (RIGHT & code)//线段与右边界相交
		{
			x = XR;//求出右边界的交点的x值
			y = y1 + (y2 - y1)*(XR - x1) / (x2 - x1);//根据斜率计算出右边界的交点的y值
		}
		else if (BOTTOM & code)//线段与下边界相交
		{
			y = YB;//求出下边界的交点的y值
			x = x1 + (x2 - x1)*(YB - y1) / (y2 - y1);//求出下边界的交点的x值根据斜率
		}
		else if (TOP & code)//线段与上边界相交
		{
			y = YT;
			x = x1 + (x2 - x1)*(YT - y1) / (y2 - y1);
		}
		if (code == code1)
		{
			x1 = x; y1 = y;  encode(x1, y1, code1);//将区域 外的端点覆盖掉
		}
		else
		{
			x2 = x; y2 = y; encode(x2, y2, code2);//将区域 外的端点覆盖掉
		}
	}
}
void mydisplay()  //显示函数
{
	//绘制方形边界
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 0.0, 0.0);//设置背景颜色
	glPointSize(2);//设置点的大小
	glBegin(GL_LINE_LOOP);//绘制区域的操作
	glVertex2i(XL, YT);//绘制矩形
	glVertex2i(XL, YB);
	glVertex2i(XR, YB);
	glVertex2i(XR, YT);
	glEnd();
	glFlush();
	//绘制未裁剪前的线段
	glBegin(GL_LINES);//绘制直线的操作
	glVertex2i(x1_init, y1_init);
	glVertex2i(x2_init, y2_init);
	glEnd();
	glFlush();
	//绘制裁剪后的线段
	glColor3f(0.0, 0.0, 0.0);
	glBegin(GL_LINES);
	glVertex2i(x1, y1);
	glVertex2i(x2, y2);
	glEnd();
	glFlush();
	//绘制剪裁区域外的直线段
	x1_init = 400, y1_init = 50, x2_init = 300, y2_init = 250;
	glColor3f(0.0, 0.0, 0.0);
	glBegin(GL_LINES);
	glVertex2i(x1_init, y1_init);
	glVertex2i(x2_init, y2_init);
	glEnd();
	glFlush();
}
int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(500, 100);//窗口位置
	glutInitWindowSize(500, 400);
	glutCreateWindow("Cohen-Sutherland裁剪算法");
	glClearColor(1.0, 1.0, 1.0, 0.0);  //设置背景颜色
	glMatrixMode(GL_PROJECTION);       // 设置投影参数
	gluOrtho2D(0.0, 600.0, 0.0, 400.0); // 设置场景的大小
	CS_LineClip();  //执行一次裁剪算法
	glutDisplayFunc(&mydisplay);//调用绘制函数
	glutMainLoop();
	return 0;
}

三、实现结果

猜你喜欢

转载自blog.csdn.net/qq_38345598/article/details/84552753