Graphics routines for the IBM PC. Dan Gabrielson.
One picture certainly is worth a thousand words. Think of all the ways we communicate with pictures--television, movies, paintings, maps.
Well, the coming computer revolution is going to change all that. With low cost hardware and versatile software available, more and more people are going to be communicating with pictures--through computers.
Math departments across the country are already scrambling to use personal computers as electronic blackboards--tools to bridge the gap between theory and application. In fact, some branches of mathematics, it seems, were just waiting for computer graphics to be developed, so they could really take off.
Being a math and computer major, I had seen many applications in which the two fields complemented each other. So when I began shopping for a home computer, I knew it had to have graphics capabilities.
I came across the IBM PC and was very impressed. It had some powerful graphics commands like CIRCLE and PAINT, but all of them depended on absolute coordinates of 0 to 319 in the x direction and 0 to 199 in the y. These commands were just too limited for the graphing I had in mind. I decided to write my own graphics routines and call them using dummy parameters and subroutines.
Wrong again! IBM Basic allows only GOSUBS in which all variables are global, and the chances were good that I would forget which variables I had used and confuse them with program variables. Another solution would have been to write the routines in machine language, but I didn't have an assembler.
Instead, I came up with a collection of quick and dirty routines which I call Q-Graphics. Every variable used in my subroutines begins with the letter Q, so I no longer have to worry about confusing them with program variables.
The method of calling the routines is a bit primitive, but I didn't have to buy an assembler, and they don't take up much memory. All parameters are set, and then the routine is called, but more about that later.
Q-Graphics is loosely based on the Core graphics system standard used by Siggraph, the special interest group for computer graphics. Points are referenced according to a pre-defined cworld coordinate system," and are then internally translated into the "screen coordinates" needed by the given machine. Using The Program
You will have to write a program to use these commands, which start at line 1000. All of the routines are called by the Basic command GOSUB. Along the way I have included as many examples as I could, and the program listing has three mathematical functions drawn with the Q-Graphics commands.
The first command necessary is INIT. This initializes the system to one of the two color palettes available for medium resolution graphics. To start, set the parameter variable Q1 to 0 or 1, depending on the color palette desired. The Initialize routine is on line 1000 and is called by
10 Q1=0: GOSUB 1000 INIT 0 INIT sets several default conditions which will
be explained later: VIEWPORT 0, 1, 0, 1 WINDOW 0, 1, 0, 1 MOVETO 0, 0 COLOR 3 CLS Viewport
There will be many new terms here, so I shall try to take them slowly. First, there is a viewport. This defines the region of the screen to be used for graphics. It may be the entire screen or only a small portion of it. Let's set up the screen as a one-unit square box with the lower left corner at the origin (see Figure 1). Then we can define any rectangular region of that square by four numbers, the left and right x values (between 0 and 1), and the bottom and top y values (also between 0 and 1).
For example, the left half of the screen could be defined as 0, .4,0,1. The maximum area would be defined as 0,1,0,1 (see Figure 1).
To set the viewport in the Q-Graphics system, you must specify each of the four parameters and then call the VIEWPORT routine located on line 1100. If this was to be line 140, we could say:
140 Q1=0: Q2=4: Q3=0: Q4=1: GOSUB 1100 VIEWPORT 0,.4,0,1
All further graphics commands will appear only in this portion of the entire screen. The viewport may be re-defined at any time, and all following commands will then be executed in the new region. Window
The next new term is window. This sets up a "world coordinate" system for the current viewport. If you want to graph some functions, you specify the region you want to show, and all the following commands need reference points only relative to that region. All translations between the points you choose and the corresponding points on the screen are handled by the computer.
The window is defined the same way as the viewport, but the values given to the variables are not limited to between 0 and 1. Let's say you wanted to draw the parabola y=x.sup.2 and only show the region from -5 to 5 in the x direction and -1 to 10 in the y direction. A statement like 150 Q1=-5: Q2=5: Q3=-1: Q4=10: GOSUB 1200 WINDOW -5,5,-1,10 could set up those coordinates in the current viewport (see Figure 2). Now all you have to do is work with points in this rectangular region; the translations will be handled automatically.
In the above case, the x and y scales are not the same. With a bit of calculation, you could figure out what the true-to-scale parameters would be. The command SHOW will do those calculations for you. It is called exactly the same way as WINDOW, but the values you save may be altered a bit, as the graphing area is stretched or shrunk to fit the viewport with one unit in the x direction approximately equal to one unit in the y.
Our previous example could be written as 150 Q1=-5: Q2=5: Q3=-1: Q4=10: GOSUB 1300 SHOW -5,5,-1,10 and the Q3 and Q4 values would be changed internally to -4.1 and 13.1, to better fit the viewport (see Figure 2).
Now that the graphing area has been defined and scaled, the move and draw commands can be used. Both of these reference points in the world coordinate system and refer to an imaginary pen. There are two types of move and draw commands: relative and absolute.
Absolute referencing refers to the actual points of the world system. To move the pen to the point (-5,0) without drawing any lines, we say
180 QX=-5: QY=0: GOSUB 1800 MOVETO -5,0
To draw a line from the previous point to the point (5,0), we could say
190 QX=5: QY=0: GOSUB 2000 DRAWTO 5,0
Notice that in the above examples, I used QX and QY instead of Q1, Q2, etc. The move and draw commands all use QX and QY to refer to x and y distances in world coordinates.
Relative referencing is similar to absolute but is based on the current position of the pen. A statement like
195 QX=-3: QY=4: GOSUB 1900 DRAW -3,4 would draw a line from the current position of
the pen to a point 3 units to the left and 4 units up (see Figure 3).
The relative move command does the same thing, but doesn't leave any visible line connecting the two points.
To draw our parabola y=x.sup.2 we will start at the point (-5,25) and vary x until x=5, drawing to each point on the parabola as we calculate it.
10 Q1=0: GOSUB 1000 Initialize 130 DEF FNF (X)=X.sup.2 Parabola y=x.sup.2 140 Q1=0: Q2=.4: Q3=0: Q4=1: GOSUB 1100 Viewport 0,.4,0,1 150 Q1=-5: Q2=5: Q3=-1: Q4=10: GOSUB
1300 SHOW -5,5,-1,10
170 QX=-5: QY=FNF (QX): GOSUB 1800 MOVETO x,x.sup.2 180 FOR QX=-5 to 5 STEP .2: QY=FNF (QY): GOSUB 2000: NEXT DRAWTO x,x.sup.2 Clipping
If a point specified is out of range of the window, the line is "clipped" to the edge of the window, but the computer acts as if it has drawn to that point. For example,
170 QX=0: QY=0: GOSUB 1800 MOVETO 0,0 180 QX=20: QY=6: GOSUB 2000 DRAWTO 20,6 190 QX=2: QY=9: GOSUB 2000 DRAWTO 2,9 results in the line being drawn off the page
and back on. Only those parts which fall within the window are shown (see Figure 4).
All lines are clipped to a "clipping region," which is similar to the window. In fact, for the default case, the clipping region is the window. This region can be defined smaller than the current window with the CLIP command, located on line 1400. CLIP has four parameters, Q1, Q2, Q3, and Q4, each of which is defined in world coordinates. Any parameters outside the window are reset to the window, and calling WINDOW automatically resets the clipping region to the window.
This region can also be resent manually to the window with the UNCLIP command. CLIP and UNCLIP are used to limit the region of the window to be used for graphing. In our continuous example, inserting the line 175 Q1=-32: Q2=3: Q3=0: Q4=6: GOSUB 1400 CLIP -3,3,0,6 results in only part of the parabola being graphed on the screen, even though the same exact points were referenced (see Figure 4).
The UNCLIP command has no parameters, as it sets the clipping region to the current window, and is called by a statement similar to
190 GOSUB 1500 UNCLIP
CLIP is made up of two user-transparent subroutines, SIGCLP and SIGCOD. SIGCOD assigns a binary code from 0 to 15 revealing the position of a point with respect to the clipping region (see Figure 5). SIGCLP uses the results of SIGCOD on the two endpoints of a line to determine which portion, if any, of the line will be visible in the window. The actual drawing routine, SIGDRW, draws only that visible portion.
All lines are drawn in the current pen color, the default being 3. To change this color, the COLOR routine at line 1600 is used.
160 Q1=2: GOSUB 1600 COLOR 2 Q1 can be 0, 1, 2, or 3, and the corresponding
color will be determined by the color palette specified in INIT. Drawing Instructions
The FRAME command, at line 2100, is a series of drawing instructions that draws a box around the current clipping region. This command requires no other parameters.
160 GOSUB 2100 FRAME
The GRID command draws a grid of lines in the window based on four parameters. The first one, Q1, is the distance between vertical lines in the x direction. The second, Q2, is the distance between horizontal lines in the y direction. Both Q1 and Q2 must be greater than 0. The third and fourth parameters, Q3 and Q4, are the x and y world coordinates of a point to serve as a reference point. An example is
170 Q1=1: Q2=1: Q3=0: Q4=0: GOSUB 2200 GRID 1,1,0,0 to draw a grid centered on the origin, with
horizontal and vertical lines in every unit.
The AXES command is similar to GRID, but only a set of x and y axes is drawn. The AXES command is located at line 2300 (see Figure 6).
The last command of the Q-Graphics system is a simple PAUSE routine. This allows the program to wait until the user presses the spacebar. I found this useful to halt the graphing process at various points along the way. It has no parameters and is located at line 2400.
I also wrote two functions which help to integrate my system with the existing IBM Basic commands. They return the screen coordinates of any world coordinate point. Remember, however, IBM Basic allows only x values in the range of 0 to 319 and y values from 0 to 199. X=FNQX(QX) returns the x screen coordinate Y=FNQY(QY) returns the y screen coordinate
The program listing contains a similar parabola example and a cubic equation graph. For a general cartesian function, y=f(x), the program steps are usually as follows: 1. Initialize 2. Define viewport 3. Define window 4. Frame, axes, grid, color, etc. 5. Move to first point of function, (x,f(x)) 6. Vary x in a loop until the last point, drawing to calculated function points along the way. Polar Coordinates
To graph a function in polar coordinates, such as the cardiod in the listing, the steps are similar. But instead of varying the x value, vary the angle from the positive x axes. See any calculus book for a discussion of polar coordinates.
These routines provide a fairly powerful, yet inexpensive, supplement to IBM's absolute graphics. The steps needed to call each routine are a bit awkward, but you won't have to know any machine language or buy any fancy software. The programs are easily modified to allow you to experiment without too much difficulty. As long as none of the variables in your main program begins with the letter Q, you won't mess up any of the Q-Graphics bookkeeping.
I'd be interested to hear from anybody else who uses computer graphics and finds the IBM commands too limited. There are many ways to handle a graphics system; this is only one of them.