夏天/isummer

Sun of my life !Talk is cheap, Show me the code! 追风赶月莫停留,平芜尽处是春山~

博客园 首页 新随笔 联系 管理

CGA裁剪算法之线段裁剪算法

  常用的线段裁剪算法有三种:【1】Cohen_SutherLand裁剪算法,【2】中点分割裁剪算法,【3】参数化方法。

1. Cohen_SutherLand裁剪算法

  为了能快速的判断一条直线矩形窗口属于何种位置关系,Cohen_SutherLand裁剪算法采用如下的编码方案,因此又称为“编码裁剪算法”。

  在编码裁剪算法中采用了如下图所示的空间划分和编码方案:

  编码的[上, 下, 右, 左], 即上: 1000, 下:0100,右:0010, 左:0001,分别对应的十进制数: 上:8, 下:4, 右:2, 左:1。所以在矩形窗口(包含四个边的边界)左上,左下,右上,右下编码如下图。

  

  裁剪一条线段时,先求出两端点所在的区号code1和code2,有如下情况:

  (1)若code1 = 0且code2 = 0,则说明线段的两个端点均在窗口内,那么整条线段必在窗口内,应取之,直线可以直接显示;

  (2)若code1和code2经按位与运算的结果不为0,则说明两个端点同在窗口的上 方、下方、左方或右方。这种情况下,对线段的处理是弃之,直线不进行显示。

  (3)如果上述两种条件都不成立,则按第三种情况处理。求出线段与窗口某边的交点,在交点处把线段一分 为二,其中必有一段完全在窗口外,可弃之,对另一段则重复上述处理,如线段P1P2, 则最终得到的显示线段为P3P4,即为裁剪后的线段,然后进行显示。

  算法分析:

  因为需要对窗口的不同防线进行编码,所以只适合方形的窗口,不适合圆形的窗口裁剪处理。

  程序如下:

  1 ////////////////裁剪算法////////////////////////
  2 #define TOP_EDGE 8
  3 #define BOTTOM_EDGE 4
  4 #define RIGHT_EDGE 2
  5 #define LEFT_EDGE 1
  6 
  7 class CBassClip
  8 {
  9 public:
 10 
 11 public:
 12     bool isInited;
 13 
 14 };
 15 
 16 class CCohenSutherLandClip:public CBassClip
 17 {
 18 public:
 19     CCohenSutherLandClip()
 20     {
 21         isInited = false;
 22     }
 23     bool cohen_SutherLandClip(Point &p_startPos, Point &p_endPos, Point &p_startResult, Point &p_endResult);
 24     void readClipInformation(Point &p_winRU, Point &p_winLB);
 25 private:
 26     //声明出编码获取说明
 27     unsigned char getCompPointCode(Point &p_Point);
 28 private:
 29     Point m_winLB, m_winRU;
 30 
 31 };
 32 
 33 //初始化裁剪信息
 34 inline void CCohenSutherLandClip::readClipInformation(Point &p_winRU, Point &p_winLB)
 35 {
 36     this->m_winLB = p_winLB;
 37     this->m_winRU = p_winRU;
 38 
 39     this->isInited = true;
 40 }
 41 //获取指定点的窗口位置编码
 42 inline unsigned char CCohenSutherLandClip::getCompPointCode(Point &p_Point)
 43 {
 44     assert(isInited);
 45     unsigned char code = 0x00;
 46     //边界位置算窗口内
 47     if (p_Point.y > m_winRU.y )
 48         code |= 8;
 49     if (p_Point.y < m_winLB.y )
 50         code |= 4;
 51     if (p_Point.x > m_winRU.x )
 52         code |= 2;
 53     if (p_Point.x < m_winLB.x )
 54         code |= 1;
 55     return code;
 56 }
 57 //编码裁剪算法实现
 58 inline bool CCohenSutherLandClip::cohen_SutherLandClip(Point &p_startPos, Point &p_endPos, Point &p_startResult, Point &p_endResult)
 59 {
 60     assert(isInited);
 61     bool accept, done;
 62 
 63     float x,y;
 64     accept = false;
 65     done  = false;
 66 
 67     unsigned char code0,code1, codeout;
 68     code0 = getCompPointCode(p_startPos);
 69     code1 = getCompPointCode(p_endPos);
 70     do{
 71         if(!(code0 | code1))//窗口内部
 72         {
 73             accept = true ;
 74             done = true;
 75         }
 76         else if(code0 & code1)//窗口外部
 77             done = true;
 78         else//不确定
 79         {
 80             if(code0 != 0)
 81                 codeout = code0;
 82             else
 83                 codeout = code1;
 84 
 85             if(codeout & LEFT_EDGE)
 86             {
 87                 y = p_startPos.y + (p_endPos.y-p_startPos.y)*(m_winLB.x-p_startPos.x)/(p_endPos.x-p_startPos.x);
 88                 x = m_winLB.x;
 89             }
 90             else if(codeout & RIGHT_EDGE){
 91                 y = p_startPos.y + (p_endPos.y-p_startPos.y)*(m_winRU.x-p_startPos.x)/(p_endPos.x-p_startPos.x);
 92                 x = m_winRU.x;
 93             }
 94             else if(codeout & BOTTOM_EDGE){
 95                 x = p_startPos.x + (p_endPos.x-p_startPos.x)*(m_winLB.y-p_startPos.y)/(p_endPos.y-p_startPos.y);
 96                 y = m_winLB.y;
 97             }
 98             else if(codeout & TOP_EDGE){
 99                 x = p_startPos.x + (p_endPos.x-p_startPos.x)*(m_winRU.y-p_startPos.y)/(p_endPos.y-p_startPos.y);
100                 y = m_winRU.y;
101             }
102 
103             if(codeout == code0)//开始顶点处理完毕
104             {
105                 p_startResult.x = x;
106                 p_startResult.y = y;
107                 code0 = getCompPointCode(p_startResult);
108             }
109             else
110             {
111                 p_endResult.x = x;
112                 p_endResult.y = y;
113                 code1 = getCompPointCode(p_endResult);
114             }
115         }
116     }while(!done);
117     return accept;
118 }

 

posted on 2015-12-25 00:44  夏天/isummer  阅读(1326)  评论(0编辑  收藏  举报