📜  梁巴尔斯基算法

📅  最后修改于: 2022-05-13 01:57:14.412000             🧑  作者: Mango

梁巴尔斯基算法

Liang-Barsky 算法是一种线裁剪算法。该算法比 Cohen-Sutherland 线裁剪算法更有效,并且可以扩展到 3 维裁剪。该算法被认为是更快的参数化剪线算法。本剪辑中使用了以下概念:

  1. 线的参数方程。
  2. 描述裁剪窗口范围的不等式,用于确定线和裁剪窗口之间的交点。

直线的参数方程可以由下式给出,

X = x1 + t(x2-x1)
Y = y1 + t(y2-y1)

其中,t 介于 0 和 1 之间。

然后,以参数形式编写点裁剪条件:

xwmin <= x1 + t(x2-x1) <= xwmax
ywmin <= y1 + t(y2-y1) <= ywmax 

上述4个不等式可以表示为,



tpk <= qk 

其中 k = 1、2、3、4(分别对应于左、右、下和上边界)。

p 和 q 定义为,

p1 = -(x2-x1),  q1 = x1 - xwmin (Left Boundary) 
p2 =  (x2-x1),  q2 = xwmax - x1 (Right Boundary)
p3 = -(y2-y1),  q3 = y1 - ywmin (Bottom Boundary) 
p4 =  (y2-y1),  q4 = ywmax - y1 (Top Boundary)  

当该线与视图窗口边界平行时,该边界的 p 值为零。
当 p k < 0 时,随着 t 的增加,线从外到内(进入)。
当 p k > 0 时,线路由内向外(退出)。
当 p k = 0 且 q k < 0 时,线几乎不可见,因为它在视窗之外。
当 p k = 0 且 q k > 0 时,该线位于相应的窗口边界内。

使用以下条件,可以确定线的位置:

ConditionPosition of line
pk = 0parallel to the clipping boundaries
pk = 0 and qk < 0completely outside the boundary
pk = 0 and qk >= 0inside the parallel clipping boundary
pk < 0line proceeds from outside to inside
pk > 0line proceeds from inside to outside

可以计算参数t 1和t 2来定义位于剪辑矩形内的线部分。
什么时候,

  1. p k < 0,取最大值(0, q k /p k )。
  2. p k > 0,取最小值(1, q k /p k )。

如果 t 1 > t 2 ,则该线完全在剪辑窗口之外并且可以被拒绝。否则,根据参数 t 的两个值计算剪裁线的端点。

算法 -

  1. 设置 t min =0,t max =1。
  2. 计算 t (t(left), t(right), t(top), t(bottom)) 的值,
    (i) 如果 t < t min忽略它并移动到下一个边缘。
    (ii) 否则使用内积将 t 值分隔为进入或退出值。
    (iii) 如果 t 是输入值,则设置 t min = t;如果 t 是现有值,则设置 t max = t。

  3. 如果 t min < t max ,从 (x 1 + t min (x 2 -x 1 ), y 1 + t min (y 2 -y 1 )) 到 (x 1 + t max (x 2 -x ) 1 ), y 1 + t max (y 2 -y 1 ))
  4. 如果线穿过窗口,(x 1 + t min (x 2 -x 1 ), y 1 + t min (y 2 -y 1 )) 和 (x 1 + t max (x 2 -x 1 ), y 1 + t max (y 2 -y 1 )) 是线和边的交点。

该算法在以下代码中给出。线相交参数初始化为值 t 1 = 0 和 t 2 = 1。

#include"graphics.h"
#define ROUND(a) ((int)(a+0.5))
int clipTest (float p,float q, float * tl, float * t2)
{
float r ;
int retVal = TRUE;
  
//line entry point
if (p < 0.0) {    
      
    r = q /p ;
      
    // line portion is outside the clipping edge
    if ( r > *t2 )                         
    retVal = FALSE;
      
    else
    if (r > *t1 )
    *tl = r; 
}
  
else
  
//line leaving point
if (p>0.0) {                             
    r = q/p ;
      
    // line portion is outside     
    if ( r<*t1 )                         
        retVal = FALSE;    
          
    else i f (r<*t2)
        *t2 = r;
}
  
// p = 0, so line is parallel to this clipping edge 
else    
  
// Line is outside clipping edge 
if (q<0.0)                                 
retVal = FALSE;
  
return ( retVal ) ;
}
  
void clipLine (dcPt winMin, dcPt winMax, wcPt2 pl , wcPt2 p2) 
  
{ 
float t1 = 0.0, t2 = 1.0, dx = p2.x-p1.x, dy;
  
 // inside test wrt left edge
if(clipTest (-dx, p1.x - winMin.x, &t1, &t2))    
  
 // inside test wrt right edge 
if(clipTest (dx, winMax.x - p1.x, &t1, &t2)) 
  
{                
    dy = p2.y - p1.y;
      
    // inside test wrt bottom edge 
    if(clipTest (-dy, p1.y - winMin.y, &t1, &t2))
      
        // inside test wrt top edge 
        if(clipTest (dy, winMax.y - p1.y, &t1, &t2)) {
              
        if(t2 < 1.0) {
            p2.x = p1.x + t2*dx;
            p2.y = p1.y + t2*dy;
        }
          
        if(t1 > 0.0) {
            p1.x += t1*dx;
            p1.y += t1*dy;
        }
          
        lineDDA ( ROUND(p1.x), ROUND(p1.y), ROUND(p2.x), ROUND(p2.y) );
          
        }
}
  
} 


参考资料: Donald Hearn, M.Pauline Baker 的计算机图形学