光栅图形学-裁剪-Cohen_Sutherland

版权声明:转载请注明出处。 https://blog.csdn.net/baidu_38304645/article/details/82918310

使用计算机处理图形信息时,计算机内部存储的图形往往比较大,而屏幕显示的只是图的一部分,因此需要确定图形中哪些图形显示在显示区之内,哪些落在显示区之外,这样便于只显示落在显示区内的那部分图形,以提高显示效率。

直线段裁剪算法比较简单,但比较重要,是复杂图元裁剪的基础。

裁剪前(矩形为窗口区):

裁剪后:

Cohen_Sutherland裁剪算法:对于每条线段P1,P2,分为三种情况处理。

1、若P1P2完全在窗口内,则显示该线段P1P2,简称取之。

2、若P1P2明显在窗口外,则丢弃该线段,简称弃之。

3、若前段既不满足取的条件,也不满足弃的条件,则在交点处把线段分为两段,其中一段完全在窗口外,可弃之,然后对另一段重复上述处理。

用编码判断一条直线段与窗口属何种关系。

 1001|1000|1010
   ----|----|-----
 0001|0000|0010
   ----|----|-----
 0101|0100|0110

裁剪一条线段时,先求出P1P2所在的区号code1,code2,若code1=0,且code2=0,则线段P1P2在窗口内,应取之。若按位与运算code1&code2!=0,则两个端点同在窗口的上方、下方、左方或右方,可判断线段完全在窗口外,可弃之。否则按第三种情况处理。求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段在窗口外,可弃之,再对说另一段重复上述处理。

定义的宏:

#define LEFT 1 
#define RIGHT 2
#define BOTTOM 4
#define TOP 8

辅助函数:

int CDrawView::encode(int x,int y,int XL,int XR,int YB,int YT) //端点与窗口边界
{
	//获得端点的编码
	/*1001|1000|1010
      ----|----|-----
      0001|0000|0010
	  ----|----|-----
	  0101|0100|0110*/
   int c=0;
   if(x<XL) 
       c|=LEFT;
   if(x>XR) 
	   c|=RIGHT;
   if(y>YB) 
	   c|=BOTTOM;
   if(y<YT) 
	   c|=TOP;
   return c;
}

实现源码:

void CDrawView::CS_Clip(int x1,int y1,int x2,int y2,int XL,int XR,int YB,int YT) 
{
	//Cohen_Sutherland裁剪算法
	//对于每条线段p1p2分为3种情况处理:
    //若p1p2完全落在窗口内,则显示该线段p1p2,取之  (两个编码都为0)
	//若p1p2明显在窗外,则丢弃该线段,弃之          (code1&code2!=0)
	//若线段不满足取得条件,也不满足弃的条件,则在交点出把先把线段分为两段,其中
	//一段完全在窗口外,弃之,对另外一段重复处理
   int code,code1,code2,x,y;
   code1=encode(x1,y1,XL,XR,YB,YT);  //获得编码 
   code2=encode(x2,y2,XL,XR,YB,YT); 
   
   while(code1!=0||code2!=0)
   { 
      if(code1&code2)
		 return;
      if(code1)
		  code=code1;
	  else
		  code=code2;

      if(LEFT&code)  //求得与窗口边界的交点
	  {	  
	     x=XL;
	     y=y1+(y2-y1)*(x-x1)/(x2-x1);
	  }
      else if(RIGHT&code)
	  {
	     x=XR;
		 y=y1+(y2-y1)*(x-x1)/(x2-x1);
	  }
      else if(BOTTOM&code)
	  {	   
	     y=YB;
		 x=x1+(x2-x1)*(y-y1)/(y2-y1);  
	  } 
      else if(TOP&code)
	  {
	     y=YT;
		 x=x1+(x2-x1)*(y-y1)/(y2-y1);
	  }
      if(code==code1) //更新code值
	  {
         x1=x;
		 y1=y;
		 code1=encode(x1,y1,XL,XR,YB,YT);
	  }
	  else
	  {
         x2=x;
		 y2=y;
		 code2=encode(x2,y2,XL,XR,YB,YT);
	  }
   }
   MiddleDrawline(x1,y1,x2,y2,RGB(255,0,0));//绘制在窗口内的线
} 

猜你喜欢

转载自blog.csdn.net/baidu_38304645/article/details/82918310