5 - Clipping Algorithms
5 - Clipping Algorithms
Clipping Algorithms
Real world objects can be represented relative to a reference world coordinate system. It is difficult
to view all the objects on computer screen at the same time in one screen shot because they usually
occupy many places in the world coordinate system. As in human perception and cameras, one
screen shot contains the images of some objects, parts of which are probably clipped. On
determining which objects or parts of objects to display on one screen shot, one needs to run a
clipping algorithm on every object in the world to determine whether it’d appear (completely or
partially) on the screen or be clipped out. Clipping algorithms usually have parameters describing the
‘clipping window’ in 2D worlds or ‘clipping volume’ in 3D worlds plus the representation of the
object being tested for clipping. Here, we are interested in 2D clipping algorithms only. Extension to
3D clipping is straightforward in many cases. The clipping window is usually a rectangular window
although it could be of any shape (circular, polygonal or others). Rectangular windows are easy to be
mapped to computer screen using a transformation called ‘window to viewport mapping’ that is
simply composed of translation, scaling and reflection transformations. The parameters of the
rectangular clipping window are (xleft, ybottom) and (xright, ytop); the lower left and upper right
corner coordinates expressed in real-world units (e.g. meter, cm, inch, .. etc.). Screen viewport
parameters are given in pixels. The following figure shows a part of a simple viewing pipeline in 2D
graphics.
Viewport
Real-world object
representation
representation
Clipping Window to viewport
mapping
Please note that the screen’s coordinate system considers the upper-left corner to be its origin and
the y-axis points downwards. Clipping window should be described relative to world coordinate
system (not screen’s coordinate system); so its y-axis points upwards. This means that ybottom of
the clipping window is less than ytop. In these notes, we’ll adopt this view in algorithms, but in C++
implementation, since we haven’t yet studied the coordinate system transformation (window to
view port mapping), we’ll assume that the clipping window is expressed relative to screen
coordinates for simplicity.
Point clipping
Line clipping
Polygon clipping
Point Clipping
A point (x, y) is considered for drawing only if x lies between xleft and xright and y lies between
ybottom and ytop. The following algorithm reflects this fact:
Line Clipping
Clipping of lines against a window needs to determine if the line has an intersection with the edges
of the window and performs the intersection accordingly. The intersection between the line and an
edge of the window is costly since it incorporates floating point operations. Several algorithms are
introduced to clip lines against rectangular and non-rectangular windows. Efficient algorithms try to
minimize the number of intersections as much as possible. The so called ‘Cohen-Sutherland
algorithm’ is a famous line clipping algorithm and we’ll study it in the next section.
Cohen-Sutherland Algorithm
Given a rectangular clipping window, the algorithm divides the space into 9 regions w.r.t. the
window: left, left-top, top, right-top, right, right-bottom, bottom, left-bottom and inside as in Figure.
Right
Left Inside
These regions can be described as subsets of the set of basic out sides {left, top, right, bottom}. So,
the 9 regions could be represented as the subsets: {left}, {left, top}, {top}, {right, top}, {right}, {right,
bottom}, {bottom}, {left, bottom} and {}. The out code of some point is one of these 9 subsets.
The algorithm first computes the out codes of the end points of the line: ( ) and ( ). It
then does the following tests:
1. If both out codes are empty sets (meaning that both end points are inside) the line is
completely inside the window and has to be drawn with no clipping. The algorithm then
terminates.
2. If both out codes have a non-empty intersection (meaning that they have a common out-
side) the line is completely outside the window and completely clipped out (not drawn). The
algorithm then terminates.
3. If the above conditions are not true (meaning that at least one out code is non-empty and
no intersection between the two out codes), the algorithm picks one side from the non-
empty out code sets and intersects the line with this side, replaces the corresponding end
point with the point of intersection, and re-computes the out code of this end point. The
algorithm then repeats the tests until termination.
In the last test, the algorithm defines the order of picking one side from the non-empty sets. One
possibility is:
- Start with the out code of ( ) if not empty; otherwise start with that of ( )
- Pick the edges in the following (priority) order: left, top, right, bottom.
Of course we can change the order rules without any effect on the final results. Although the
algorithm can trivially accept or reject lines without doing any intersection, there is also a
possibility of doing unnecessary intersections before trivially rejecting or accepting a line.
To implement the algorithm, first we define a data structure for the out code sets. One possible
way in visual C++ is to define union containing two fields: the first field is a 4-bit field named ‘All’
and the second is a structure containing four one-bit fields which are left, top, right and bottom.
According to the definition of unions in C++, both fields are stored in the same memory location
so they are aliases to each other; updating one field leads to updating the other. The definition
of the union is shown below:
Union OutCode
{
unsigned All:4;
struct{unsigned left:1,top:1,right:1,bottom:1;};
};
Second, we write the utility function that gets the side code of a given point (x, y) with respect to
a window (xleft, ytop, xright, ybottom) as shown below:
Clearly, for the left and right edges the intersection point has its x component equals the x
component of the edge (which is either ). The y component is obtained by the
substitution in the line equation; i.e.
( )( ) ( )
Similarly, for the top and bottom edges:
( )( )
Here, we’ll study the so-called Sutherland-Hodgman algorithm for polygon clipping. The
algorithm clips the polygon by the window side by side. With rectangular windows, the
algorithm has four main iterations: clipping with the left side, clipping with the top side, clipping
with the right side and clipping with the bottom side. The four iterations are similar; so, it is
sufficient to describe the one ‘generic’ iteration. For this purpose, we need two utility functions:
The first utility function is ‘In(v, side)’ that takes two parameters: polygon vertex (v) and
window edge (side). The function tests if the vertex is ‘in’ or ‘out’ relative to the side. The
window edge line divides the space into two regions; the first is in the same side of the window
and the second is in the other side. A vertex is considered ‘in’ if it is in the same side of the
window and considered ‘out’ otherwise. The following figure shows the ‘in’ and ‘out’ regions
relative to the left window edge.
Ou I
The second utility is ‘Intersect(v1, v2, side)’ that takes three parameters: Two vertexes of a
polygon edge (v1 and v2) and the window edge (side). The function computes the intersection
between the polygon edge and the window edge and returns the intersection point.
The basic iteration of the Sutherland-Hodgman algorithm is given below:
Algorithm ClipWithEdge(polygon, side)
Define an empty list; name it ‘Clipped’
V1=polygon[n-1]
For i=0 to n-1
V2=polygon[i]
If not In(V1, side) and In(V2, side) then
Vi=Intersect(V1, V2, side)
Append Vi to Clipped
Append V2 to Clipped
Else if In(V1, side) and In(V2, side) then
Append V2 to Clipped
Else if In(V1, side) then
Vi=Intersect(V1, V2, side)
Append vi to Clipped
End if
V1=V2
End For
Return clipped
End Algorithm
To implement the algorithm, first define the data structures and type definitions used by the
algorithm implementation like the following:
#include <vector>
using namespace std;
struct Vertex
{
double x,y;
Vertex(int x1=0,int y1=0)
{
x=x1;
y=y1;
}
};
typedef vector<Vertex> VertexList;
typedef bool (*IsInFunc)(Vertex& v,int edge);
typedef Vertex (*IntersectFunc)(Vertex& v1,Vertex& v2,int edge);
As you see, we used a built-in dynamic array data structure called ‘vector’ in the standard
template library (STL) of C++ since the polygon size changes dynamically with clipping. Template
data types are generic in the sense that they allow to use variable element types. For example,
we can use the vector template to define a vector of integers as vector<int>, of float as
vector<float> and etc. The definition (typedef vector<Vertex> VertexList;) declares a new
data type called ‘VertexList’ that is a equivalent to a vector of ‘Vertex’ type. The
two definitions (typedef bool (*IsInFunc)(Vertex& v,int edge);) and (typedef
Vertex (*IntersectFunc)(Vertex& v1,Vertex& v2,int edge);) declare new data types
called ‘IsInFunc’ and ‘IntersectFunc’ that are pointer to functions. The first is
supposed to point to a Boolean function taking a vertex parameter and an edge
parameter (and returns true if the vertex is in relative to the edge). The second
is supposed to point to a function that computes the intersection between the line
connecting vertex v1 and vertex v2 and the edge.
Second, given the above data structures, we write the implementation Sutherland-
Hodgman generic iteration as below:
Third, define the following utilities to test if a vertex is in or out relative to the four window
edges. These are the functions that will be passed to the generic iteration of the algorithm