Cohen-Sutherland裁剪算法的簡單實現

最近幾天由於項目關係,接觸到裁剪算法,今天算是真正把它其中一種最簡單的Cohen-Sutherland實現了一下,算法原理很簡單,我不想多講,任何一本計算機圖形學的書應該都會有涉及到該裁剪算法,我的參考書是《計算機圖形學》(OpenGL版,第3版,清華大學出版社)下面直接把代碼貼出來吧。

#define LEFT_EDGE 1  
#define RIGHT_EDGE 2  
#define BOTTOM_EDGE 4  
#define TOP_EDGE 8  

 struct vertex
 {
	 float x;
	 float y;
 };
vertex CP;
float wxmax = 1.0, wxmin = -1.0, wymax = 1.0, wymin = -1.0;
void MoveTo(GLfloat x, GLfloat y)
{
    CP.x = x; CP.y = y;
}
void LineTo(GLfloat x, GLfloat y)
{
	glBegin(GL_LINES);
	  glVertex2f(CP.x, CP.y);
	  glVertex2f(x, y);
	glEnd();
	glFlush();
}
int CompCode(GLfloat x, GLfloat y)//位置編碼,原理上有9個位置,其實只要5個就可以了
{
	int code = 0x00;  //此處是二進制  
	if (y<wymin)
		code = code | 4;
	if (y>wymax)
		code = code | 8;
	if (x>wxmax)
		code = code | 2;
	if (x<wxmin)
		code = code | 1;
	return code;
}
void cohensutherlandlineclip()
{
	vertex p1,p2;
	int accept = 0;
	float x = 0.0, y = 0.0;
	int code0, code1, codeout;
	for (int i = 0; i < v.nedge; i++)//輸入要裁剪的邊
	{
		p1 = v.edge[0][i];
		p2 = v.edge[1][i];

		code0 = CompCode(p1.x, p1.y);
		
		code1 = CompCode(p2.x, p2.y);
		
		do{
			if (!(code0 | code1))//全部顯示(平凡接受)  
			{
				accept = 1;
				break;
			}
			if (code0 & code1)//完全不可見(平凡拒絕)
			{
				accept = 0;
				break;
			}
			if (code0 != 0)//p1在窗口外面
			{
				codeout = code0;
				if (codeout&LEFT_EDGE)//p1在窗口左邊
				{

					p1.y += (p2.y - p1.y)*(wxmin - p1.x) / (p2.x - p1.x);//左邊界截斷
					p1.x = wxmin;

				}
				else if (codeout&RIGHT_EDGE)
				{
					p1.y += (p2.y - p1.y)*(wxmax - p1.x) / (p2.x - p1.x);
					p1.x = wxmax;
				}
				else if (codeout&BOTTOM_EDGE)
				{
					p1.x += (p2.x - p1.x)*(wymin - p1.y) / (p2.y - p1.y);
					p1.y = wymin;
				}
				else if (codeout&TOP_EDGE)
				{
					p1.x += (p2.x - p1.x)*(wymax - p1.y) / (p2.y - p1.y);
					p1.y = wymax;
				}
				code0 = CompCode(p1.x, p1.y);
			}
			else//p2在窗口外
				{
				codeout = code1;
				if (codeout&LEFT_EDGE)
				{

					p2.y += (p2.y - p1.y)*(wxmin-p2.x) / (p2.x - p1.x);
					p2.x = wxmin;

				}
				else if (codeout&RIGHT_EDGE)
				{
					p2.y += (p2.y - p1.y)*(wxmax - p2.x) / (p2.x - p1.x);
					p2.x = wxmax;
				}
				else if (codeout&BOTTOM_EDGE)
				{
				    p2.x += (p2.x - p1.x)*(wymin - p2.y) / (p2.y - p1.y);
				    p2.y = wymin;
				}
				else if (codeout&TOP_EDGE)
				{
				    p2.x += (p2.x - p1.x)*(wymax - p2.y) / (p2.y - p1.y);
					p2.y = wymax;

				}
				code1 = CompCode(p2.x, p2.y);
			}
		} while (1);//並非死循環,最多四次裁剪就可以跳出循環
		if (accept)      //畫出所有被平凡接受的線段  
		{
			MoveTo(p1.x, p1.y);
			LineTo(p2.x, p2.y);
		}
		else//捨棄所有被平凡拒絕的邊
		{
			p1.x = 0.0; p1.y = 0.0; p2.x = 0.0; p2.y = 0.0;
			MoveTo(p1.x, p1.y);
			LineTo(p2.x, p2.y);
		}
	}
}

裁剪效果
裁之前:
這裏寫圖片描述

裁之後:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章