Open In App

Liang-Barsky Algorithm

Improve
Improve
Like Article
Like
Save
Share
Report

The

Liang-Barsky algorithm

is a line clipping algorithm. This algorithm is more efficient than Cohen–Sutherland line clipping algorithm and can be extended to 3-Dimensional clipping. This algorithm is considered to be the faster parametric line-clipping algorithm. The following concepts are used in this clipping:

  1. The parametric equation of the line.
  2. The inequalities describing the range of the clipping window which is used to determine the intersections between the line and the clip window.

The parametric equation of a line can be given by,

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

Where, t is between 0 and 1. Then, writing the point-clipping conditions in the parametric form:

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

The above 4 inequalities can be expressed as,

tpk <= qk 

Where k = 1, 2, 3, 4 (correspond to the left, right, bottom, and top boundaries, respectively). The p and q are defined as,

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)

When the line is parallel to a view window boundary, the p value for that boundary is zero. When p

k

< 0, as t increase line goes from the outside to inside (entering). When p

k

> 0, line goes from inside to outside (exiting). When p

k

= 0 and q

k

< 0 then line is trivially invisible because it is outside view window. When p

k

= 0 and q

k

> 0 then the line is inside the corresponding window boundary. Using the following conditions, the position of line can be determined:

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

Parameters t

1

and t

2

can be calculated that define the part of line that lies within the clip rectangle. When,

  1. pk < 0, maximum(0, qk/pk) is taken.
  2. pk > 0, minimum(1, qk/pk) is taken.

If t

1

> t

2

, the line is completely outside the clip window and it can be rejected. Otherwise, the endpoints of the clipped line are calculated from the two values of parameter t.

Algorithm –

  1. Set tmin=0, tmax=1.
  2. Calculate the values of t (t(left), t(right), t(top), t(bottom)), (i) If t < tmin ignore that and move to the next edge. (ii) else separate the t values as entering or exiting values using the inner product. (iii) If t is entering value, set tmin = t; if t is existing value, set tmax = t.
  3. If tmin < tmax, draw a line from (x1 + tmin(x2-x1), y1 + tmin(y2-y1)) to (x1 + tmax(x2-x1), y1 + tmax(y2-y1))
  4. If the line crosses over the window, (x1 + tmin(x2-x1), y1 + tmin(y2-y1)) and (x1 + tmax(x2-x1), y1 + tmax(y2-y1)) are the intersection point of line and edge.

This algorithm is presented in the following code. Line intersection parameters are initialised to the values t

1

= 0 and t

2

= 1.

C++ code for Liang-Barsky Algorithm:

Cpp


#include&quot;graphics.h&quot;
#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 &lt; 0.0) {    
    
    r = q /p ;
    
    // line portion is outside the clipping edge
    if ( r &gt; *t2 )                         
    retVal = FALSE;
    
    else
    if (r &gt; *t1 )
    *tl = r; 
}

else

//line leaving point
if (p&gt;0.0) {                             
    r = q/p ;
    
    // line portion is outside     
    if ( r&lt;*t1 )                         
        retVal = FALSE;    
        
    else i f (r&lt;*t2)
        *t2 = r;
}

// p = 0, so line is parallel to this clipping edge 
else    

// Line is outside clipping edge 
if (q&lt;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, &amp;t1, &amp;t2))    

 // inside test wrt right edge 
if(clipTest (dx, winMax.x - p1.x, &amp;t1, &amp;t2)) 

{                
    dy = p2.y - p1.y;
    
    // inside test wrt bottom edge 
    if(clipTest (-dy, p1.y - winMin.y, &amp;t1, &amp;t2))
    
        // inside test wrt top edge 
        if(clipTest (dy, winMax.y - p1.y, &amp;t1, &amp;t2)) {
            
        if(t2 &lt; 1.0) {
            p2.x = p1.x + t2*dx;
            p2.y = p1.y + t2*dy;
        }
        
        if(t1 &gt; 0.0) {
            p1.x += t1*dx;
            p1.y += t1*dy;
        }
        
        lineDDA ( ROUND(p1.x), ROUND(p1.y), ROUND(p2.x), ROUND(p2.y) );
        
        }
}

} 

Reference:

Computer Graphics by Donald Hearn, M.Pauline Baker

Python code for Liang-Barsky Algorithm and Visualization using matplotlib:

Python3

import matplotlib.pyplot as plt

# Function to implement Liang-Barsky line clipping algorithm
def liang_barsky(x_min, y_min, x_max, y_max, x1, y1, x2, y2):
    dx = x2 - x1
    dy = y2 - y1
    p = [-dx, dx, -dy, dy]
    q = [x1 - x_min, x_max - x1, y1 - y_min, y_max - y1]
    t_enter = 0.0
    t_exit = 1.0

    for i in range(4):
        if p[i] == 0:  # Check if line is parallel to the clipping boundary
            if q[i] < 0:
                return None  # Line is outside and parallel, so completely discarded
        else:
            t = q[i] / p[i]
            if p[i] < 0:
                if t > t_enter:
                    t_enter = t
            else:
                if t < t_exit:
                    t_exit = t

    if t_enter > t_exit:
        return None  # Line is completely outside

    x1_clip = x1 + t_enter * dx
    y1_clip = y1 + t_enter * dy
    x2_clip = x1 + t_exit * dx
    y2_clip = y1 + t_exit * dy

    return x1_clip, y1_clip, x2_clip, y2_clip


# Define the clipping window
x_min, y_min = 20, 20
x_max, y_max = 80, 80

# Define the line (starting and ending points) - you can adjust these coordinates
x1, y1 = 10, 30
x2, y2 = 90, 60

# Apply the Liang-Barsky algorithm to clip the line
clipped_line = liang_barsky(x_min, y_min, x_max, y_max, x1, y1, x2, y2)

# Plotting
plt.figure(figsize=(8, 6))

# Plot the clipping window
plt.plot([x_min, x_max, x_max, x_min, x_min], [y_min, y_min,
                                               y_max, y_max, y_min], 'b', label='Clipping Window')

if clipped_line is not None:
    x1_clip, y1_clip, x2_clip, y2_clip = clipped_line
    # Plot the original line
    plt.plot([x1, x2], [y1, y2], 'r', label='Original Line')
    # Plot the clipped line
    plt.plot([x1_clip, x2_clip], [y1_clip, y2_clip], 'g', label='Clipped Line')
    plt.title('Liang-Barsky Line Clipping Algorithm')
    plt.legend()
else:
    # The line is completely outside or parallel, so just plot the window
    plt.title('Line is outside the clipping window')

plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.grid()
plt.axis('equal')
plt.show()

Output:

Screenshot-2023-11-03-020241
Line Clipping using Liang – Barsky Algorithm



Last Updated : 06 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads