143 lines
7.8 KiB
Markdown
143 lines
7.8 KiB
Markdown
**LISTING 35.2 L35-2.C**
|
||
|
||
/*
|
||
* Sample program to illustrate EGA/VGA line drawing routines.
|
||
*
|
||
* Compiled with Borland C++
|
||
*
|
||
* By Michael Abrash
|
||
*/
|
||
|
||
#include <dos.h> /* contains geninterrupt */
|
||
|
||
#define GRAPHICS_MODE 0x10
|
||
#define TEXT_MODE 0x03
|
||
#define BIOS_VIDEO_INT 0x10
|
||
#define X_MAX 640 /* working screen width */
|
||
#define Y_MAX 348 /* working screen height */
|
||
|
||
extern void EVGALine();
|
||
|
||
/*
|
||
* Subroutine to draw a rectangle full of vectors, of the specified
|
||
* length and color, around the specified rectangle center.
|
||
*/
|
||
void VectorsUp(XCenter, YCenter, XLength, YLength, Color)
|
||
int XCenter, YCenter; /* center of rectangle to fill */
|
||
int XLength, YLength; /* distance from center to edge
|
||
of rectangle */
|
||
int Color; /* color to draw lines in */
|
||
{
|
||
int WorkingX, WorkingY;
|
||
|
||
/* Lines from center to top of rectangle */
|
||
WorkingX = XCenter - XLength;
|
||
WorkingY = YCenter - YLength;
|
||
for ( ; WorkingX < ( XCenter + XLength ); WorkingX++ )
|
||
EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color);
|
||
|
||
/* Lines from center to right of rectangle */
|
||
WorkingX = XCenter + XLength - 1;
|
||
WorkingY = YCenter - YLength;
|
||
for ( ; WorkingY < ( YCenter + YLength ); WorkingY++ )
|
||
EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color);
|
||
|
||
/* Lines from center to bottom of rectangle */
|
||
WorkingX = XCenter + XLength - 1;
|
||
WorkingY = YCenter + YLength - 1;
|
||
for ( ; WorkingX >= ( XCenter - XLength ); WorkingX— )
|
||
EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color);
|
||
|
||
/* Lines from center to left of rectangle */
|
||
WorkingX = XCenter - XLength;
|
||
WorkingY = YCenter + YLength - 1;
|
||
for ( ; WorkingY >= ( YCenter - YLength ); WorkingY— )
|
||
EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color );
|
||
}
|
||
|
||
/*
|
||
* Sample program to draw four rectangles full of lines.
|
||
*/
|
||
void main()
|
||
{
|
||
char temp;
|
||
|
||
/* Set graphics mode */
|
||
_AX = GRAPHICS_MODE;
|
||
geninterrupt(BIOS_VIDEO_INT);
|
||
|
||
/* Draw each of four rectangles full of vectors */
|
||
VectorsUp(X_MAX / 4, Y_MAX / 4, X_MAX / 4,
|
||
Y_MAX / 4, 1);
|
||
VectorsUp(X_MAX * 3 / 4, Y_MAX / 4, X_MAX / 4,
|
||
Y_MAX / 4, 2);
|
||
VectorsUp(X_MAX / 4, Y_MAX * 3 / 4, X_MAX / 4,
|
||
Y_MAX / 4, 3);
|
||
VectorsUp(X_MAX * 3 / 4, Y_MAX * 3 / 4, X_MAX / 4,
|
||
Y_MAX / 4, 4);
|
||
|
||
/* Wait for the enter key to be pressed */
|
||
scanf("%c", &temp);
|
||
|
||
/* Return back to text mode */
|
||
_AX = TEXT_MODE;
|
||
geninterrupt(BIOS_VIDEO_INT);
|
||
}
|
||
|
||
#### Looking at EVGALine {#Heading7}
|
||
|
||
The **EVGALine** function itself performs four operations. **EVGALine**
|
||
first sets up the VGA's hardware so that all pixels drawn will be in the
|
||
desired color. This is accomplished by setting two of the VGA's
|
||
registers, the Enable Set/Reset register and the Set/Reset register.
|
||
Setting the Enable Set/Reset to the value 0FH, as is done in
|
||
**EVGALine**, causes all drawing to produce pixels in the color
|
||
contained in the Set/Reset register. Setting the Set/Reset register to
|
||
the passed color, in conjunction with the Enable Set/Reset setting of
|
||
0FH, causes all drawing done by **EVGALine** and the functions it calls
|
||
to generate the passed color. In summary, setting up the Enable
|
||
Set/Reset and Set/Reset registers in this way causes the remainder of
|
||
**EVGALine** to draw a line in the specified color.
|
||
|
||
**EVGALine** next performs a simple check to cut in half the number of
|
||
line orientations that must be handled separately. Figure 35.4 shows the
|
||
eight possible line orientations among which a Bresenham's algorithm
|
||
implementation must distinguish. (In interpreting Figure 35.4, assume
|
||
that lines radiate outward from the center of the figure, falling into
|
||
one of eight octants delineated by the horizontal and vertical axes and
|
||
the two diagonals.) The need to categorize lines into these octants
|
||
falls out of the major/minor axis nature of the algorithm; the
|
||
orientations are distinguished by which coordinate forms the major axis
|
||
and by whether each of X and Y increases or decreases from the line
|
||
start to the line end.
|
||
|
||
------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
 *A moment of thought will show, however, that four of the line orientations are redundant. Each of the four orientations for which **DeltaY**, the Y component of the line, is less than 0 (that is, for which the line start Y coordinate is greater than the line end Y coordinate) can be transformed into one of the four orientations for which the line start Y coordinate is less than the line end Y coordinate simply by reversing the line start and end coordinates, so that the line is drawn in the other direction. **EVGALine** does this by swapping (X0,Y0) (the line start coordinates) with (X1,Y1) (the line end coordinates) whenever Y0 is greater than Y1.*
|
||
------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
This accomplished, **EVGALine** must still distinguish among the four
|
||
remaining line orientations. Those four orientations form two major
|
||
categories, orientations for which the X dimension is the major axis of
|
||
the line and orientations for which the Y dimension is the major axis.
|
||
As shown in Figure 35.4, octants 1 (where X increases from start to
|
||
finish) and 2 (where X decreases from start to finish) fall into the
|
||
latter category, and differ in only one respect, the direction in which
|
||
the X coordinate moves when it changes. Handling of the running error of
|
||
the line is exactly the same for both cases, as one would expect given
|
||
the symmetry of lines differing only in the sign of **DeltaX**, the X
|
||
coordinate of the line. Consequently, for those cases where **DeltaX**
|
||
is less than zero, the direction of X movement is made negative, and the
|
||
absolute value of **DeltaX** is used for error term calculations.
|
||
|
||
Similarly, octants 0 (where X increases from start to finish) and 3
|
||
(where X decreases from start to finish) differ only in the direction in
|
||
which the X coordinate moves when it changes. The difference between
|
||
line drawing in octants 0 and 3 and line drawing in octants 1 and 2 is
|
||
that in octants 0 and 3, since X is the major axis, the X coordinate
|
||
changes on every pixel of the line and the Y coordinate changes only
|
||
when the running error of the line dictates. In octants 1 and 2, the Y
|
||
coordinate changes on every pixel and the X coordinate changes only when
|
||
the running error dictates, since Y is the major axis.
|
||
|
||
\
|
||
**Figure 35.4** *Bresenham's eight possible line orientations.*
|