Cyrus-Beck图像裁剪算法归纳

 此算法能使用任意多边形对一条直线段进行裁剪。

 

类GLdoublePoint: 公有—GLdouble x ,y;

类line:                 公有—GLdoublePoint first,second;

linelist:                 line型数据组成的链表,用于描述多边形;

 

伪代码:

int  CyrusBeck(line&  seg , linelist&  l)

{

   double  numer , denom ;

   double  tIn = 0.0 , tOut = 1.0;

   Vector  c , temp;

   c = seg.second - seg.first;

   for(int  i = 0 ; i < l.num ; i++)

   {

      temp = l.line[i].pt - first ;  // pt为此时多边形某边上的任意一点

      numer = dot(l.line[i].norn , temp);

      denom = dot(l.line[i].norn , c);  // dot()函数为求两向量的点积,自行编写

      if(!chopCI(numer , denom , tIn , tOut))  return  0 ; // chopCI()是用来计算射线与多边型每条边相交 的时间,并判断射线在交点处是射入还是射出,伪代码在后面      

    }                                                                              

 

 

   if(tOUt < 1.0)                                                                   //进行裁剪

   {

      seg.second.x = seg.first.x + c.x * tOut ;

      seg.second.y = seg.first.y + c.y * tOut ;

   }

   if(tIn > 0.0)

   {

      seg.first.x = seg.first.x + c.x * tIn ;

      seg.first.y = seg.first.y + c.y * tIn ; 

   }

   return 1;

}

 

 

 

int  chopCI(double  numer , double  denom ,double  tIn ,double  tOut)

{

   double  tHit;

   if(denom < 0)                                                              // 射线射入

   {

      tHit = numer / denom ;

      if (tHit > tOut) return 0;

     else  if(tHit > tIn)   tIn = tHit ;

   }

   else if(denom > 0)                                                       // 射线射出

   {

      tHit = numer / denom ;

      if(tHit < hIn) return 0;

      else  if(tHIt > tIn) tOut = tHIt ;

   }

   else                                                                            //射线与边平行

   if(numer <= 0 )  return 0;

   return 1;

}

 

 

说明

设某射线起始点为A,单位向量为c;某直线l,其上任意一点B,法向量n;先判断A和B的关系。

假设A与B相交,则焦点A+t*c与B形成的向量与n垂直,则有:

                          n ●(A+c*t — B)= 0 (1)

此处可以将参数t看为是时间,则t为射线击中l的时间,记为tHit。

(1)式经变换可得:tHit = n ●(B—A)/ (n ● c)

由向量点积的性质可得:若n ● c>0 ,则射线沿法线方向

                                   若n ● c<0 ,则射线与法线相反

                                   若n ● c=0 ,则法线与射线平行

 

代码中的tIn和tOut可以理解为候选区间,也就是射线现存的部分,剪裁时就是根据射线是射入还是射出以及tHIt和tIn与tOut的关系来修改tOut和tIn,避免了频繁进行改变点的运算,因为计算机图形学中点与向量的定义很相似,容易出错。

Cyrus-Beck裁剪算法就是依据以上方法用多边形的每条边对seg进行判断,并把剪裁后的线段返回到seg中,思路简单但是运算量较大,也不实用来计算边数多的多边形,同时此算法也只适用于凸多边形。

你可能感兴趣的:(Cyrus-Beck图像裁剪算法归纳)