Clipping

by William Shoaff with lots of help


Contents

1.
PDF version of these notes
2.
Audio file of these notes (up to Blinn's algorithm)

Clipping refers to the removal of part of a scene. Internal clipping removes parts of a picture outside a given region; external clipping removes parts inside a region. We'll explore internal clipping, but external clipping can almost always be accomplished as a by-product.

There is also the question of what primitive types can we clip? We will consider line clipping and polygon clipping. A line clipping algorithms takes as input two endpoints of line segment and returns one (or more) line segments. A polygon clipper takes as input the vertices of a polygon and returns one (or more) polygons. There are several clipping algorithms. We'll study the Cohen-Sutherland line clipping algorithm to learn some basic concepts. Develop the more efficient Liang-Barsky algorithm and us its insights to culminate with Blinn's line clipping algorithm. The Sutherland-Hodgman polygon clipping algorithm will then be covered and the Weiler-Atherton algorithm, time permitting.

There are other issues in clipping that we will not have time to cover. Some of these are:

Cohen-Sutherland Line Clipping

The Cohen-Sutherland algorithm clips a line to an upright rectangular window. It is an application of triage, or make the simple case fast. The algorithm extended window boundaries to define 9 regions:

top-left, top-center, top-right, center-left, center, center-right, bottom-left, bottom-center, and bottom-right.
See figure 1 below. These 9 regions can be uniquely identified using a 4 bit code, often called an outcode. We'll use the order: left, right, bottom, top (LRBT) for these four bits. In particular, for each point $p=(x,\,y)$ The LRBT (Left, Right, Bottom, Top) order is somewhat arbitrary, but once an order is chosen we must stick with it. Note that points on the clipping window edge are considered inside (the bits are left at 0).


  
Figure 1: The nine region defined by an up-right window and their outcodes.
\begin{figure}\centering
\begin{tabular}{c\vert c\vert c}
&& \\
1001 & 0001 & 0...
...ndow & \\ \hline
&& \\
1010 & 0010 & 0110 \\
&& \\
\end{tabular}
\end{figure}

Given a line segment with end points $p_0=(x_0,\,y_0)$ and $p_1=(x_1,\,y_1)$, here's the basic flow of the Cohen-Sutherland algorithm:

1.
Compute 4-bit outcodes LRBT0 and LRBT1 for each end-point
2.
If both outcodes are 0000, the trivially visible case, pass end-points to draw routine This occurs when the bitwise OR of outcodes yields 0000.
3.
If both outcodes have 1's in the same bit position, the trivially invisible case, clip the entire line (pass nothing to the draw routine). This occurs when the bitwise AND of outcodes is not 0000.
4.
Otherwise, the indeterminate case, - line may be partially visible or not visible. Analytically compute the intersection of the line with the appropriate window edges

Let's explore the indeterminate case more closely. First, one of two end-points must be outside the window, pretend it is $p_0=(x_0,\,y_0)$.

1.
Read P1's 4-bit code in order, say left-to-right
2.
When a set bit (1) is found, compute intersection point I of corresponding window edge with line from p0 to p1.

As an example, pretend the right bit is set so we want to compute the intersection with the right clipping window edge, also, pretend we've already done the homogeneous divide, so the right edge is x=1, and we need to find y. The y value of the intersection is found by substituting x=1 into the line equation (from p0 to p1)

\begin{displaymath}y-y_0 = \frac{y_1-y_0}{x_1-x_0}(x-x_0)\end{displaymath}

and solving for y

\begin{displaymath}y = y_0 + \frac{y_1-y_0}{x_1-x_0}(1-x_1).\end{displaymath}

Other cases are handled similarly.

Now this may not complete the clipping of the line, so we replace p0 by the intersection point I and repeat Cohen-Sutherland algorithm. (Clearly we can save some state to avoid some computations)

The Cohen-Sutherland was one of, if not, the first clipping algorithm to be implemented in hardware. Yet the intersection was not computed analytically, as we have done, but by bisection (binary search) of the line segment.

Cohen-Sutherland in 3D

The Cohen-Sutherland algorithm extends easily to 3D. Extended the 3D clipping window boundaries to define 27 regions. Assign a 6 bit code to each region, that is, for each point $(x,\,y,\,z)$

The Left, Right, Bottom, Top, Near, Far (LRBTNF) outcode can be used to determine segments that are trivially visible, trivially invisible, or indeterminate. In the indeterminate case we intersect the line segment with faces of clipping cube determined by the outcode of an end-point that is outside of the clipping cube. More specifically, in the indeterminant case, use parametric form of the line

\begin{eqnarray*}x & = & x_0 + t(x_1 - x_0) \\
y & = & y_0 + t(y_1 - y_0) \\
z & = & z_0 + t(z_1 - z_0) \\
\end{eqnarray*}


To clip against a face, say y=1, compute

\begin{displaymath}t = \frac{1- y_0}{y_1 - y_0}\end{displaymath}

and use it to evaluate the x and z intersections

Liang-Barsky Line Clipping

The Liang-Barsky is optimized for clipping to an upright rectangular clip window (the Cyrus-Beck algorithms is similar but clips to a more general convex polygon). Liang-Barsky uses parametric equations, clip window edge normals, and inner products can improve the efficiency of line clipping over Cohen-Sutherland. Let

\begin{displaymath}L(t) = p_0 + t(p_1-p_0) = (1-t)p_0 + tp_1,\quad 0\leq t \leq 1\end{displaymath}

denote the parametric equation of the line segment from p0 to p1Let $\vec{N_e}$ denote the outward pointing normal of the clip window edge e, and let pe be an arbitrary point on edge e.

Consider the vector L(t) - pe from pe to a point on the line L(t)Figure 2 shows several of these vectors for different values of t. At the intersection of L(t) and edge e the inner product of $\vec{N_e}$ and L(t)-pe is zero, see figure 2. In fact, we have

\begin{eqnarray*}\vec{N_e}\cdot (L(t)-p_e) & = & \vec{N_e}\cdot (p_0 + t(p_1-p_0...
..._e}\cdot (p_0-p_e) + t \vec{N_e}\cdot(p_1-p_0))\\
& = & 0 \\
\end{eqnarray*}


which if we Solve for t yields

\begin{displaymath}t = \frac{\vec{N_e}\cdot (p_e - p_0)}{\vec{N_e}\cdot(p_1-p_0)}.\end{displaymath}

(Note that checks need to be made that the denominator above is not zero.)


  
Figure 2: The setup for Liang-Barsky clipping.
\begin{figure}\centering
\setlength{\unitlength}{0.0125in} %
\begin{picture}
(27...
...{\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{Inside}}}
\end{picture}
\end{figure}

Using the 4 edge normals for an upright rectangular clip window and 4 points, one on each edge, we can calculate 4 parameter values where L(t) intersects each edge Let's call these parameter values tL, tR, tB, tT Note any of the t's outside of the interval $[0,\,1]$ can be discarded, since they correspond to points before p0 (when t < 0) and points after p1 (when t>1). The remaining t values are characterized as ``potentially entering'' (PE) or ``potentially leaving'' (PL)

See figure 3


  
Figure 3: Potentially entering and leaving edge intersections.
\begin{figure}\centering
\setlength{\unitlength}{0.0125in} %
\begin{picture}
(35...
...80){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{ PL}}}
\end{picture}
\end{figure}

The inner product of the outward pointing edge normal $\vec{N}_i$with p1-p0 can be used to classify the parameter tias either PE or PL.

1.
If

\begin{displaymath}\vec{N}_i\cdot (p_1 - p_0) < 0\end{displaymath}

the parameter ti is potentially entering (PE). The vectors $\vec{N}_i$ and p1-p0 point in opposite directions. Since $\vec{N}_i$ is outward, the vector p1-p0 from p0 to p1 points inward.
2.
If

\begin{displaymath}\vec{N}_i\cdot (p_1 - p_0) > 0\end{displaymath}

the parameter ti is potentially leaving (PL). The vectors $\vec{N}_i$ and p1-p0 point in similar directions. Since $\vec{N}_i$ is outward, the vector p1-p0 from p0 to p1 points outward too.
3.
Let tpe be the largest PE parameter value and tpl the smallest PL parameter value
4.
The clipped line extends from L(tpe) to L(tpl), where $0\leq t_{pe} \leq t_{pl} \leq 1$


\begin{picture}(265,192)(175,625)
\thicklines
\put(240,800){\line( 0,-1){160}}
...
...}}
\put(250,715){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{ PE}}}
\end{picture}

Blinn's Line Clipping

A clipping volume can be defined as set of bounding planes. Choosing simple planes is a good idea. We'll define the clipping volume by:

\begin{displaymath}X=0,\,X=1,\,Y=0,\,Y=1,\,Z=0,\,Z=1\end{displaymath}

We'll call these the real space interpretation of the clipping volume bounding planes.

It is convenient to think of these in terms of inner products. More specifically, the X=0 plane can be thought of at the column vector:

\begin{displaymath}\left[\begin{array}{r} 1 \\ 0 \\ 0 \\ 0 \end{array}\right]\end{displaymath}

A homogeneous point $(x,\, y, \, z,\, w)$ is then ``in the plane'' if the inner product of the point and vector is zero, that is,

\begin{displaymath}(x,\, y, \, z,\, w)\cdot
\left[\begin{array}{r} 1 \\ 0 \\ 0 \\ 0 \end{array}\right] = x = 0\end{displaymath}

To obtain the real plane we must divide x by w (whatever its value other than 0), but we'll still get X=x/w = 0 since x=0.

(Recall the homogeneous divide necessary to map points after a perspective projection into real points: X=x/w, Y=y/w, Z=z/w.)

Using this notation, the six bounding planes become the six column vectors:

\begin{displaymath}B_0=\left[\begin{array}{r} 1 \\ 0 \\ 0 \\ 0 \end{array}\right...
...B_2=\left[\begin{array}{r} 0 \\ 1 \\ 0 \\ 0 \end{array}\right],\end{displaymath}


\begin{displaymath}B_3=\left[\begin{array}{r} 0 \\ -1 \\ 0 \\ 1 \end{array}\righ...
...B_5=\left[\begin{array}{r} 0 \\ 0 \\ -1 \\ 1 \end{array}\right]\end{displaymath}

We'll call these the homogeneous space interpretation of the clipping volume bounding planes.

Nota bene:

1.
The first three elements of each column vector form an inward, unit length normal vector to the plane in real space.
2.
When the homogeneous coordinate (w) is equal to 1 and the inner product of a point with the bounding plane column vector is set to 0, the equation reduces to the real space equation. That is, for example,

\begin{displaymath}(x, y, z, 1) \cdot
\left[\begin{array}{r} 0 \\ 0 \\ -1 \\ 1 \end{array}\right] = -z+1=0\end{displaymath}

or

z = z/1 = Z = 1.

3.
Or, better yet, dividing the equation by w produces the real equation, for example w-z=0 becomes 1-z/w=1-Z=0 or Z=1.

Boundary coordinates

Following Blinn's terminology we'll call the inner products of a point with the bounding planes the boundary coordinates of a point. They are listed in the table below.

Boundary Number (Homogeneous Value) Real Plane
  Boundary Coordinate  
0 x X=0
1 w-x X=1
2 y Y=0
3 w-y Y=1
4 z Z=0
5 w-z Z=1

Outcodes

The question we want to answer is:

Given two end points (P0 and P1) of a line segment, how can we use the boundary coordinates to determine a points Cohen-Sutherland outcode?

Let's assume the 6-bit outcode is in the order left, right, bottom, top, near, far (LRBTNF) so it corresponds to the order of the boundary coordinates. A particular bit is set (to 1) if the point is in the designated region and unset (to 0) otherwise.

We'll assume w>0. Recall that the value of w that comes out of the perspective transform is $w=z\sin(\theta)$ where $\theta$ is (half of) the field of view angle. Now both $\sin(\theta)>0$ and z>0(provided we're looking at something in front of us) so w>0. The bottom line is division by a positive quantity does not affect the sense of an inequality!

Consider the left plane X=0.

This works with the other planes too. Consider the right plane X=1. All outcodes are set by testing inequality against 0.
x < 0 Set L (to 1)
w-x < 0 Set R
y < 0 Set B
w-y < 0 Set T
z < 0 Set N
w-z < 0 Set F

For a particular bounding plane (bit in the outcode) and a pair of line segment end points there are four cases.

Bit for P0 Bit for P1 Interpretation
0 0 Segment visible w.r.t. this boundary
1 0 Straddles boundary, P0 outside
0 1 Straddles boundary, P1 outside
1 1 Segment invisible w.r.t. this boundary

Given the outcodes LRBTNF for P0 and P1 (set by considering the boundary coordinates x, w-x, etc.) we can apply the trivial accept and reject tests:

1.
If outcode(P0) | outcode(P1) == 000000 accept line segment. (All bits in both outcodes must be 0)
2.
If outcode(P0) & outcode(P1) != 000000 reject line segment. (Some bit is set in both outcodes for some plane)

Interpolation

When the trivial tests fail we must calculate the intersections and this is best done by parametric linear interpolation, our old friend. Let

P(u)=P0 + u(P1-P0)

be the (directed) line segment from P0 to P1 as parameter uincreases from 0 to 1. We need to calculate u and this is done by inner products with the boundary column vectors, say Bi, that is,

\begin{displaymath}P(u)\cdot B_i = P_0 \cdot B_i + u(P_1-P_0) \cdot B_i\end{displaymath}

and since we want the point P(u) to be on the boundary this inner product should be 0. Or

\begin{displaymath}u = \frac{P_0 \cdot B_i}{(P_0-P_1)\cdot B_i}=
\frac{P_0 \cdot B_i}{P_0\cdot B_i - P_1\cdot B_i}\end{displaymath}

but these inner products are just the boundary coordinates! To be explicit,

\begin{displaymath}P(u)=(x_0 + u(x_1-x_0),\,y_0 + u(y_1-y_0),\,z_0 + u(z_1-z_0),\,
w_0 + u(w_1-w_0))\end{displaymath}

and let's assume the line straddles the X=1 plane, so we're working with boundary column vector

\begin{displaymath}B_1=\left[\begin{array}{r} -1 \\ 0 \\ 0 \\ 1 \end{array}\right]\end{displaymath}

and the inner product is

\begin{displaymath}P(u)\cdot B_1 = -[x_0 + u(x_1-x_0)] + [w_0+u(w_1-w_0)]\end{displaymath}

which if we set to zero and solve for u yields

\begin{displaymath}u = \frac{w_0 - x_0}{(w_0-x_0) - (w_1-x_1)}.\end{displaymath}

Note this value of u will be in the range 0 to 1 only when boundary coordinates (w0-x0 and w1-x1 in the above example) have opposite signs. This is easy to interpret in real space (see figure 4). But you can also establish it algebraically by considering the inequality

\begin{displaymath}0 < \frac{a}{a-b} < 1.\end{displaymath}

If a is positive, then a-b must be positive and greater than a, that is b is negative. Something similar happens when a is negative. The point is we only want to calculate u when the boundary coordinates differ in sign, that is the line segment straddles the boundary.


  
Figure: Crossing boundaries for u<0, $0\leq u \leq 1$ and u>1
\begin{figure}\end{figure}

The Algorithm

Blinn's clipping algorithm Jim Blinn presents this material better than I can. See [2] and, in particular, [1].

Polygon Clipping

Polygon clipping differs from line clipping in several respects.

1.
The input to the clipper is a polygon, which for simplicity we will view as a list of $n\geq 3$ vertices $(v_0,\,v_1,\ldots,v_{n-1})$.
2.
The output from the clipper is one or more polygons.
3.
The clipping process may generate vertices that do not lie on any of the edges of the orginal polygon.
4.
Complex polygons (that is, non-convex) may lead to strange artifacts.

Sutherland-Hodgman Polygon Clipping

Since polygons are basic primitives, algorithms have been developed for clipping them directly. The Sutherland-Hodgman algorithm is a polygon clipper. It was a basic component in James Clark's ``Geometry Engine,'' which was the precursor to the first Silicon Graphics machines. This algorithm clips any subject polygon (convex or concave) against any convex clipping window, but we will usually pretend the clipping window is an upright rectangle.

Given a subject polygon with an ordered sequence of vertices

\begin{displaymath}v_1,\,v_2,\,\ldots,\,v_{n-1},\,n\geq 3,\end{displaymath}

Sutherland-Hodgman compares each subject polygon edge against a single clip window edge, saving the vertices on the in-side of the edge and the intersection points when edges are crossed. The clipper is then re-entered with this intermediate polygon and another clip window edge.

Given a clip window edge and a subject polygon edge, there are four cases to consider:

1.
The subject polygon edge goes from outside clip window edge to outside clip window edge. In this case we output nothing.
2.
The subject polygon edge goes from outside clip window edge to inside clip window edge. In this case we save intersection and inside vertex.
3.
The subject polygon edge goes from inside clip window edge to outside clip window edge. In this case we save intersection point.
4.
The subject polygon edge goes from inside clip window edge to inside clip window edge. In this case we save second inside point (the first was saved previously).
To complete the description, we need to consider the first vertex of the subject polygon and its last edge. If the first vertex is inside the current edge we save it to the list of vertices in the intermediate polygon, otherwise we drop it out. For the last edge, note that if nothing has yet been saved in the intermediate polygon, the entire subject must not be visible in the clip window, so we can quit. Otherwise, if the last subject edge crosses clip window edge, the intersection point must be appended to the intermediate polygon.

Figure 5 shows an example of the Sutherland-Hodgman clipping process. The clip window edge currently be used is solid, the others are dashed.

First Clip Window Edge:
Starting with the original triangle (subject polygon), we set the intermdiate polygon to null and find
1.
Start vertex: p0 is outside the edge, so not saved in the intermediate polygon vertex list.
2.
Subject edge p0p1 crosses the clip edge and so the intersection i01 is saved -- intermediate list (i01).
3.
p1 is inside the edge, so it is saved -- intermediate list $(i_{01},\,p_1)$.
4.
Subject edge p1p2 does not crosses the clip edge and so no intersection is computed.
5.
p2 is inside the edge, so it is saved -- intermediate list $(i_{01},\,p_1,\,p_2)$.
6.
Last edge p2p0: We have output some data, so we'll continue.
(a)
Subject edge p2p0 does crosses the clip edge and so the intersection i01 is saved -- intermediate list $(i_{01},\,p_1,\,p_2,\,i_{20})$.
Second Clip Window Edge:
Start vertex: i01 is inside the edge, so saved in the intermediate polygon vertex list -- intermediate list (i01).
Subject edge i01p1 crosses the clip edge and so the intersection i011 is saved -- intermediate list $(i_{01},\,i_{011})$.
p1 is outside the edge, so it is not saved.
Subject edge p1p2 does crosses the clip edge and so the intersection i12 is saved -- intermediate list $(i_{01},\,i_{011},\,i_{12})$.
p2 is inside the edge, so it is saved -- intermediate list $(i_{01},\,i_{011},\,i_{12},\,p_2)$.
Subject edge p2i20 does not cross the clip edge and so no interesection is computed.
i20 is inside the edge, so it is saved -- intermediate list $(i_{01},\,i_{011},\,i_{12},\,p_2,\,i_{20})$.
Last edge i20i01: We have output some data, so we'll continue.
1.
Subject edge i20i01 does not crosses the clip edge and so no intersection is saved.
As an exercise, you can complete the clipping process.


  
Figure 5: An Example of Sutherland-Hodgman Clipping.
sh-ex.eps

The Sutherland-Hodgman algorithm is not too difficult to code either.

Inside/Outside Testing

The Sutherland-Hodgman algorithm depends on our ability to determine that a point (vertex) is inside or outside of a given edge (line). This is a fairly common decision problem in computer graphics, yet due to the build up of floating point arithmetic errors, it may be difficult to answer the question exactly. We will declare that vertices that lie on the edge are inside.

There are several ways to answer the question: Is point $p=(x,\,y)$ on the in or out side of a line determined by vertices $v_0=(x_0,\,y_0)$ and $v_1= (x_1,\,y_1)$. The one we present is based on inner products, but before we can begin, we must know what is meant by inside and outside. A complete description of this topic and related one is included in the chapter on basic concepts. Recall, that our polygon vertices are listed in counter-clockwise when viewed from the front side, and this implies that the inside of the polygon is on our left as we traverse its vertices.

These assumption lead to the mathematical result that the outward edge normal from vertex v0 to v1 is given by

\begin{displaymath}\vec{n_{01}} = \langle y_1-y_0,\,-(x_1-x_0)\rangle.\end{displaymath}

Now, consider the vector

\begin{displaymath}\vec{p-v_0} = \langle x-x_0,\,y-y_0\rangle\end{displaymath}

from v0 to p. If the inner product of $\vec{n_{01}}$ and $\vec{p-v_0}$ is
1.
positive, p is on the out side.
2.
zero, p is on the edge and consider inside.
3.
negative, p is on the in side.

Crossings

We can use the inside/outside decision algorithm to determine whether or not two edges cross.

Click here to see the code

Intersections

The last task we must complete is developing the code to compute an intersection.

Sutherland-Hodgman Summary

The Sutherland-Hodgman polygon clipping algorithm clips polygons against convex clipping windows. It does so by clipping the subject polygon against each clip edge producing intermediate subject polygons. Although we have not done so, the Sutherland-Hodgman algorithm easily extends to 3 dimensions.

The Sutherland-Hodgman may produce connecting lines that were not in the original polygon. When the subject polygon is concave (not convex) these connecting lines may be undesirable artifacts.



\begin{picture}(505,180)(100,600)
\thicklines
\put(160,640){\framebox (160,120)...
...lb]{\raisebox{0pt}[0pt][0pt]{ $V_9$ }}}
\put(485,705){\circle*{4}}
\end{picture}

The Weiler-Atherton, which we will consider next, clips arbitrary polygons against arbitrary clipping windows, the price we pay for this generally is that Weiler-Atherton is only a 2D clipper.

Weiler-Atherton Polygon Clipper

Bibliography

1
J. BLINN, A trip down the graphics pipeline: Line clipping, IEEE Computer Graphics and Applications, 11 (1991), pp. 98 - 105.

2
height 2pt depth -1.6pt width 23pt, Jim Blinn's Corner: a trip down the graphics pipeline, Morgan Kaufmann Publishers, Inc., 1996.
1-55860-387-5.


William D. Shoaff
2002-03-12