home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-02-11 | 49.3 KB | 1,119 lines |
- The Graphics Wizard's Library for BASIC page 1
- =-------------------------------------=
- Version 1.5
-
- GRAFWIZ Copyright (c) 1990-1991 Thomas G. Hanlin III
-
-
-
- This is GRAFWIZ, a library of assembly language and BASIC routines for use
- with QuickBASIC version 4.5. Support for other recent versions of the BASIC
- compiler is provided with registration. The GRAFWIZ collection is
- copyrighted and may be distributed only under the following conditions:
-
- 1) No fee of over $10.00 may be charged for distribution. This
- restriction applies only to physical copies and is not meant to
- prevent distribution by telecommunication services.
-
- 2) All GRAFWIZ files must be distributed together in original, unaltered
- form. This includes GRAFWIZ.BI, GRAFWIZ.DOC, GRAFWIZ.LIB, GRAFWIZ.NEW,
- GRAFWIZ.REF, BIBLIO.TXT, CATALOG.TXT, CREATE.BAT, DEMO.BAS, DEMO.PCX,
- FILES.LST, LIBRARY.TXT, MIRRORS.BAS, PRODUCT.TXT, QUESTION.TXT,
- REGISTER.TXT, ROSES.BAS, S&B4EGA.BAS, S&B4EGA.EXE, VGABOX.BAS, and
- VGABOX.EXE.
-
- You use this library at your own risk. It has been tested by me on my own
- computer, but I will not assume any responsibility for any problems which
- GRAFWIZ may cause you. If you do encounter a problem, please let me know
- about it, and I will do my best to verify and repair the error.
-
- It is expected that if you find GRAFWIZ useful, you will register your copy.
- You may not use GRAFWIZ routines in programs intended for sale unless you
- have registered. Registration entitles you to receive the latest version of
- GRAFWIZ, complete with full source code in assembly language and BASIC. The
- assembly code is designed for the OPTASM assembler by SLR Systems and will
- require modifications if you wish to use it with MASM or TASM. You will be
- able to compile the BASIC code with whatever version of the compiler you
- have, allowing you to use GRAFWIZ with QuickBASIC versions 4.0 - 4.5 and
- BASCOM versions 6.0 - 7.1 (QBX and BASCOM 7.x far strings aren't supported).
-
- Warning: Use of GRAFWIZ for more than 30 days without registering may cause
- the author to play the drums outside your window at two in the morning!
-
- The GRAFWIZ.QLB file is no longer included in order to save space. You can
- create it by doing the following:
-
- LINK GRAFWIZ.LIB/Q/SE:512,,NUL,BQLB45;
-
- For an example of how to set up your program to access the GRAFWIZ library,
- how to LINK the routines, and so forth, take a look at the CREATE.BAT and
- DEMO.BAS files. The LIBRARY.TXT file explains libraries.
-
- So who's the Graphics Wizard? With this library, you will be! Read this
- tome well, for invoking these routines without proper preparation may bring
- unexpected results. Cape and hat (optional) not included. No assembly
- required.
-
- Table of Contents page 2
-
-
-
- Overview and Legal Info ................................................ 1
-
- Non-Specific Routines .................................................. 3
-
- Mode-Specific Routines ................................................. 4
-
- Printer Routines ...................................................... 16
-
- A Little Geometry ..................................................... 17
-
- Equations, Etc ........................................................ 20
-
- Miscellaneous Notes ................................................... 23
-
- Memory Considerations ................................................. 25
-
- Troubleshooting ....................................................... 26
-
- Using GRAFWIZ with PDQ ................................................ 27
-
- Credits ............................................................... 28
-
- Non-specific Routines page 3
-
-
-
- These are routines that will work with more than one graphics mode, more than
- one text mode, or with many combinations of graphics and text modes.
-
- The PrintScreen routine will work in all text modes and in most graphics
- modes. It sends the contents of the screen to LPT1/PRN, the standard
- printer. It expects an Epson-compatible printer for graphics modes.
- Graphics printing is not particularly sophisticated in that there is no
- attempt to provide gray levels-- a point is either on or off, so complex
- screens with images in many colors may not print out very well.
-
- You must specify the screen mode when the PrintScreen routine is used. You
- may choose SCREEN 0, 1, 2, 7, 8, 9, 11, 12, or 13. This covers virtually all
- CGA, EGA, and VGA text and graphics modes. Text mode support includes
- automatic handling of 25x40, 25x80, 43x80, 50x80 and 60x80 text modes from
- MDA to VGA. Here's how to print the screen:
-
- PrintScreen ScreenMode%
-
- In order to determine what size a text mode screen is, PrintScreen relies on
- another routine which may be used independently. That's called ScreenSize,
- simply enough. It returns the number of rows and columns available for a
- display in any of the text modes, like so:
-
- ScreenSize Rows%, Columns%
-
- The GetDisplay routine tells what kind of display adapter is active and
- whether it's hooked up to a color monitor. The only time it can't detect the
- monitor type is on CGA setups (it assumes "color"). It's a good idea to
- allow a "/B" switch for your program so the user can specify if a monochrome
- monitor is attached to a CGA.
-
- GetDisplay Adapter, Mono
- IF Mono THEN
- PRINT "Monochrome monitor"
- ELSE
- PRINT "Color monitor"
- END IF
- SELECT CASE Adapter
- CASE 1: PRINT "MDA"
- CASE 2: PRINT "Hercules"
- CASE 3: PRINT "CGA"
- CASE 4: PRINT "EGA"
- CASE 5: PRINT "MCGA"
- CASE 6: PRINT "VGA"
- END SELECT
-
- The GetDisplay routine is also included in my BASWIZ library. If you intend
- to use both libraries together, you should remove this routine from GRAFWIZ:
-
- LIB GRAFWIZ,-GETDISP,NUL;
- LINK GRAFWIZ.LIB/Q,,NUL,BQLB45; (or whatever BQLBxx you have)
-
- Mode-Specific Routines page 4
-
-
-
- These routines are designed to work with specific graphics modes, so your
- program will only include those routines which apply to the modes you use.
- The following modes are currently supported:
-
- SCREEN # Adapter Graphics Res Colors Text Res Notes
- 1 CGA 320x200 4 40x25
- 2 CGA 640x200 2 80x25
- 3 Herc 720x348 2 90x43 *1
- 7 EGA 320x200 16 40x25
- 8 EGA 640x200 16 80x25
- 9 EGA 640x350 16 80x25 *2
- 11 VGA 640x480 2 80x30 *2
- 12 VGA 640x480 16 80x30 *2
- 13 VGA 320x200 256 40x25
- N0 VGA 360x480 256 45x60 *3
- N1 VGA 320x400 256 40x50 *4
- N2 <Epson> 480x640 2 60x80 *5
- N4 any 80x50 2 10x6 *6
-
- *1 Note that the GRAFWIZ Hercules routines, unlike those provided with
- QuickBASIC, do not require the QBHERC TSR to be loaded. They are
- entirely self-contained. However, they may need to be compiled by BC
- instead of QB, which may refuse to deal with the video mode change.
-
- *2 These text resolutions are capable of more rows than indicated, but
- GRAFWIZ doesn't yet support such extra-row modes.
-
- *3 This is a non-standard VGA mode. It should work on many VGAs, however.
-
- *4 This is a non-standard VGA mode. It should work on nearly all VGAs.
-
- *5 This works with an Epson-compatible printer rather than the display. The
- results may be previewed on a VGA, however. See "Printer Routines" for
- additional information.
-
- *6 This actually provides graphics in text mode. It will work on any
- display adapter. 80x25 text remains available through PRINT.
-
-
-
- See "Miscellaneous Notes" for additional comments on the new modes.
-
- The routine for a specific mode is indicated by a prefix of "G", followed by
- the mode number, and then the routine name. For example, if you wished to
- plot a point in SCREEN 2 mode, you would use:
-
- G2Plot X%, Y%
-
- Mode-Specific Routines page 5
-
-
-
- Many of these routines correspond with existing BASIC instructions. However,
- they are smaller and usually faster by 22% - 64%. See "Miscellaneous Notes"
- for notes on the differences between BASIC and the GRAFWIZ routines.
-
- The smaller size may not be noticeable if you use the SCREEN statement, since
- that causes BASIC to link in some of its own graphics routines. If you
- intend to use only GRAFWIZ routines for graphics, you can avoid that by using
- the G#Mode command instead of SCREEN:
-
- G#Mode Graphics% ' use 0 for SCREEN 0, any other for SCREEN #
-
- One difference between BASIC and GRAFWIZ is that, instead of each "draw"
- command requiring a color parameter as in BASIC, the GRAFWIZ library provides
- a separate color command:
-
- G#Color Foreground%, Background%
-
- The "foreground" color is used by all graphics routines. The background
- color is used by the G#Cls routine. Both foreground and background colors
- are used in the G#Write and G#WriteLn routines.
-
- Mode-Specific Routines page 6
-
-
-
- Here is a list of the corresponding routines, first BASIC, then GRAFWIZ
- (replace the "#" with the appropriate mode number):
-
- ' get the color of a specified point
- colour% = POINT(x%, y%)
- colour% = G#GetPel(x%, y%)
-
- ' set the color of a specified point
- PSET (x%, y%), colour%
- G#Color colour%, backgnd% : G#Plot x%, y%
-
- ' draw a line of a specified color
- LINE (x1%, y1%) - (x2%, y2%), colour%
- G#Color colour%, backgnd% : G#Line x1%, y1%, x2%, y2%
-
- ' draw a box frame of a specified color
- LINE (x1%, y1%) - (x2%, y2%), colour%, B
- G#Color colour%, backgnd% : G#Box x1%, y1%, x2%, y2%, 0
-
- Mode-Specific Routines page 7
-
-
-
- Here are some more BASIC and GRAFWIZ routines:
-
- ' draw a box of a specified color and fill it in
- LINE (x1%, y1%) - (x2%, y2%), colour%, BF
- G#Color colour%, backgnd% : G#Box x1%, y1%, x2%, y2%, 1
-
- ' clear the screen and home the cursor
- CLS
- G#Cls
-
- ' get the current cursor position
- Row% = CSRLIN: Column% = POS(0)
- G#GetLocate Row%, Column%
-
- ' set the current cursor position
- LOCATE Row%, Column%
- G#Locate Row%, Column%
-
- ' display a string without a carriage return and linefeed
- PRINT St$;
- G#Write St$
-
- ' display a string with a carriage return and linefeed
- PRINT St$
- G#WriteLn St$
-
- Note that GRAFWIZ, unlike BASIC, allows both foreground and background colors
- for text in graphics mode. It also displays text substantially faster than
- BASIC. See the "Miscellaneous Notes" section for information on other
- differences in text printing.
-
- If you need to print a number rather than a string, just use the BASIC
- function STR$ to convert it. If you don't want a leading space (assuming the
- number is not negative), use this formula:
-
- St$ = MID$(STR$(Number), 2)
-
- The GRAFWIZ library has other routines which have no BASIC equivalent. One
- allows you to get the current colors:
-
- G#GetColor Foreground%, Background%
-
- Mode-Specific Routines page 8
-
-
-
- Sometimes the normal text services seem unduly limited. Text is displayed
- only at specific character positions, so it may not align properly with a
- graph, for instance. Text is also of only one specific size. These are
- limitations which make the normal text routines very fast, but for times when
- you need something a little bit more fancy, try:
-
- G#Banner St$, X%, Y%, Xmul%, Ymul%
-
- You may display the string starting at any graphics position. The Xmul% and
- Ymul% values are multipliers, specifying how many times larger than normal
- each character should be. Using Xmul% = 1 and Ymul% = 1 will give you
- normal-sized characters. What "normal" means depends on the font in use.
-
- Since G#Banner "draws" the text onto the screen, it is a bit slower than the
- normal text services. It also uses only the foreground color, so the letters
- go right on top of anything that was previously there. Use G#Box to clear
- the area beforehand if this is a problem for you.
-
- The G#Banner routine supports several fonts. The larger fonts provide a more
- precise character set but leave you with less room on the screen. You may
- choose from these fonts:
-
- Font Number Font Size (width x height)
- 0 8 x 8 --- default
- 1 8 x 14
- 2 8 x 16
-
- Select a font like so:
-
- BFont FontNr%
-
- If you want to find out what the current font is, that's possible too:
-
- FontNr% = GetBFont
-
- Besides looking more elegant, the larger fonts are easier to read. They will
- also suffer less from being increased in size, although some deterioration is
- inevitable when magnifying these kinds of fonts.
-
- The G#Banner routines accept CHR$(0) - CHR$(127). No handling of control
- codes is done. All codes are displayed directly to the screen.
-
- Mode-Specific Routines page 9
-
-
-
- Circles and ellipses can be drawn with the Ellipse routine. This is similar
- to the BASIC CIRCLE statement. You specify the center of the ellipse (X,Y),
- plus the X and Y radius values:
-
- G#Ellipse CenterX%, CenterY%, XRadius%, YRadius%
-
- A circle is an ellipse with a constant radius. So, to draw a circle, just
- set both radius values to the single desired radius.
-
- As well as the usual points, lines, and ellipses, GRAFWIZ also allows you to
- draw polygons: triangles, squares, pentagons, hexagons, all the way up to
- full circles!
-
- G#Polygon X%, Y%, Radius%, Vertices%, Angle!
-
- The X% and Y% values represent the coordinates of the center of the polygon.
- The Radius% is the radius of the polygon (as if you were fitting it into a
- circle). Vertices% is the number of angles (also the number of sides) for
- the polygon to have. Angle! specifies the rotation of the polygon, and is
- specified in radians. See "A Little Geometry" for more information.
-
- Mode-Specific Routines page 10
-
-
-
- Another new routine is designed to manipulate a GET/PUT image. Given an
- image in array Original%() and a blank array of the same dimensions called
- Flipped%(), this routine copies the original image to the new array as a
- mirror image about the horizontal axis. This is the same as the image you'd
- see if you turned your monitor upside-down: the resulting image is
- upside-down and backwards.
-
- G#MirrorH Original%(), Flipped%()
-
- Don't forget to make the Flipped%() array the same DIM size as the original,
- or the picture will overflow into main memory, probably causing disaster!
-
- Note that G#MirrorH will only work properly on images with byte alignment.
- This means that the width of the image must be evenly divisible by four if
- SCREEN 1 is used, or evenly divisible by eight if SCREEN 2 is used. EGA
- modes are not yet supported for this routine.
-
- Mode-Specific Routines page 11
-
-
-
- There are more routines that work only with SCREEN 2. One allows you to load
- a MacPaint-type image ("ReadMac" or .MAC files) into an array which can then
- be PUT onto the screen:
-
- G2LoadMAC FileName$, Image%(), StartRow%
-
- Note that a full .MAC picture is 576x720, which won't fit on the screen, so
- the image will be truncated to 576x200. You may specify a starting row
- within the .MAC image, StartRow%, which may be 0-521, allowing the entire
- picture to be loaded in several parts.
-
- The Image%() must be dimensioned with 7202 elements:
-
- DIM Array(1 TO 7202) AS INTEGER
-
- If you don't give an extension in the FileName$, an extension of ".MAC" will
- be used. There is no checking to see if the file actually exists, so you may
- wish to do this beforehand.
-
- There is no way of knowing whether a .MAC picture is supposed to be black on
- white or white on black. If the image doesn't look right when you PUT using
- PSET, you can switch it around by using PUT with PRESET instead.
-
- PC PaintBrush (.PCX) pictures can also be loaded. These images can be of
- various sizes, so you need to dimension a dynamic array for them:
-
- REM $DYNAMIC
- DIM Image(1 TO 2) AS INTEGER
-
- The array will be set to the correct size by the loader. It goes like this:
-
- G2LoadPCX FileName$, Image%(), ErrCode%
-
- If you don't give an extension in the FileName$, an extension of ".PCX" will
- be used. You may wish to check to see if the file exists beforehand.
- Possible errors are as follows:
-
- -1 File is not in PCX format
- 1 Image is too large for desired screen mode
- 2 Image won't work in desired screen mode (too many planes/colors)
-
- Mode-Specific Routines page 12
-
-
-
- Two new routines are replacements for the GET and PUT image statements in
- BASIC. They are on the slow side, but if you don't intend to use them for
- animation, they will serve to save some memory:
-
- REM $DYNAMIC
- DIM Image(1 TO 2) AS INTEGER
- G2Get X1%, Y1%, X2%, Y2%, Image()
-
- Note the DIMensioning of a dynamic array. The G2Get routine will set the
- array to the appropriate size to hold the image.
-
- The PUT replacement assumes that you intend to PSET the image. It doesn't
- allow for other display modes yet:
-
- G2Put X%, Y%, Image()
-
- See "Miscellaneous Notes" for more information on using GET/PUT images and
- the directions I'll be taking with them in the future. Note that SCREEN 13
- is also supported, via G13Get and G13Put.
-
- The COLOR statement in SCREEN 1 is anomalous. It doesn't really control
- color at all, which is why QuickBASIC proper doesn't support colored text in
- this (or any graphics) mode. Instead, it is used for controlling the
- background/border color and palette. Since GRAFWIZ -does- support a true
- G1COLOR routine, there are different routines which allow you to change the
- palette and border colors. To change the background (and border) color, use:
-
- G1Border Colour%
-
- Mode-Specific Routines page 13
-
-
-
- There are two palette routines. Why two? Well, QuickBASIC supports two CGA
- palettes. One of the routines works like QuickBASIC and can be used on any
- CGA, EGA or VGA display (as long as it's in CGA mode). The other routine
- gives you a wider choice of palettes, but will only work on true CGAs (and
- some EGA or VGA systems that have been "locked" into CGA mode).
-
- Here's the QuickBASIC-style two-palette routine for any CGA/EGA/VGA:
-
- G1PaletteA PaletteNr%
-
- The PaletteNr% may be as follows:
-
- 0 (bright) Green, Red, Yellow
- 1 Cyan, Violet, White
-
-
- The more flexible six-palette routine (for CGA only) works like this:
-
- G1PaletteB PaletteNr%
-
- Palettes are as follows:
-
- 0 Green, Red, Brown 4 (bright) Green, Red, Yellow
- 1 Cyan, Violet, White 5 (bright) Cyan, Violet, White
- 2 Cyan, Red, White 6 (bright) Cyan, Red, White
-
- Mode-Specific Routines page 14
-
-
-
- The EGA has a number of features which work in all its modes, so rather than
- giving them screen mode prefixes, they are simply named with an "E". These
- routines allow you to get or set the palette, get or set the border color,
- and determine whether the higher background colors should be displayed as
- bright colors or as blinking.
-
- To get a palette color value, use:
-
- Colour% = EGetPalette(ColorNumber%)
-
- To set the color value, use:
-
- EPalette ColorNumber%, Colour%
-
- To get the border color:
-
- Colour% = EGetBorder%
-
- You can probably guess how to set the border color:
-
- EBorder Colour%
-
- Finally, the blink vs. intensity. Actually, this is designed for text mode;
- I'm not sure whether it has any function in graphics modes. The text-mode
- default is for blinking to be turned on. With BASIC, you add 16 to the
- foreground color to make it blink. That's a little weird, since the "blink"
- attribute is actually a part of the background color, but that's how BASIC
- views it. You can tell the EGA to turn off blinking, in which case adding 16
- to the foreground color makes the background color intense. This doubles the
- number of available background colors.
-
- EBlink Blink%
-
- Use -1 for blinking (default), or 0 to turn off blinking.
-
- Mode-Specific Routines page 15
-
-
-
- Like the EGA, the VGA has a number of features which work in all its modes.
- Again, rather than giving them screen mode prefixes, we simply name them with
- a "V". The current routines allow you to get or set the palette colors.
-
- To get a palette color value, use:
-
- VGetPalette(ColorNumber%, Red%, Green%, Blue%)
-
- To set the color value, use:
-
- VPalette ColorNumber%, Red%, Green%, Blue%
-
- As you've probably noticed, this doesn't work the same way as the QuickBASIC
- PALETTE statement. Rather than using a formula to calculate a single LONG
- color value, like QuickBASIC, the GRAFWIZ library allows you to specify the
- color in a more meaningful way. The Red%, Green%, and Blue% parameters each
- hold an intensity value (0-63). By mixing these three, you can get an
- immense variety of shades-- well over 200,000 combinations in all.
-
- If you need to keep track of the intensities in your program, I'd suggest the
- following TYPE definition:
-
- TYPE VGAcolor
- Red AS INTEGER
- Green AS INTEGER
- Blue AS INTEGER
- END TYPE
-
- If speed is not of the essence, you can compress that to half the size by
- using STRING * 1 instead of INTEGER. In that case, you will need to use the
- CHR$ and ASC functions to convert the intensities between string and integer.
-
- Printer Routines page 16
-
-
-
- The GRAFWIZ printer routines allow you to work with a printer using the same
- convenient methods you'd use on a screen. The image is created with the
- usual G# routines (use mode N2), but the results are kept in a buffer in
- memory (about 37K bytes) rather than being displayed directly. The image can
- be previewed on a VGA or printed out at your convenience, to any printer or
- even a file. The results will take up a single printer page, assuming normal
- 8.5" x 11" paper.
-
- Printing a finished page works like this:
-
- GN2Print Device$
-
- The Device$ variable should be set to the name of the device:
-
- LPT1 parallel printer on port 1
- LPT2 parallel printer on port 2
- LPT3 parallel printer on port 3
- COM1 serial printer on port 1
- COM2 serial printer on port 2
-
- Instead of using a device name, you can also use a file name, to store the
- results for later printing. Output is done using BASIC file handling, so it
- would be a good idea to provide an ON ERROR GOTO trap in case of problems.
- The FREEFILE function is used, so you don't have to worry about conflicts
- with any files in use by your program.
-
- Getting a page layout just right can consume a lot of paper. Fortunately,
- there's a "preview" routine that allows you to display the results on a VGA.
- The display will be sideways, allowing the whole page to be seen at once.
- This will exactly match the printed output in N2 mode. Here's how it works:
-
- G11Mode 1 ' set SCREEN 11 (VGA graphics mode, 640x480 x2)
- GN2Display ' display the page
- DO ' wait for a key to be pressed
- LOOP UNTIL LEN(INKEY$) '
- G11Mode 0 ' set SCREEN 0 (text mode)
-
- The G#Write and G#WriteLn printer routines are unlike the display versions of
- the same routines in that they don't scroll. These routines only allow you
- to design one page at a time.
-
- A Little Geometry page 17
-
-
-
- The increasing capabilities of computer graphics systems has left many of us
- in the dust. It's great to be able to run dazzling applications or to doodle
- with a "paint" program, but many of us find it difficult to design appealing
- images of our own. Becoming an artist is perhaps a bit more than most of us
- are willing to take on! It is important to remember, however, that computers
- are wonderful number-crunchers. With a little application of plane geometry,
- you can have the computer take on much of the work for you-- and after all,
- isn't that why we have computers in the first place?
-
- A complete review of plane geometry is a bit beyond the scope of this text.
- However, I'm going to run through some of the things I think you'll find most
- useful. I'd also like to suggest that you might dig out your old textbooks
- or rummage through your local used book store. It may have seemed like a dry
- subject at the time, but when you can watch the results growing on your
- computer screen, you will have a much better idea of how geometry can be
- useful to you-- and it can be surprisingly fun, too!
-
- In geometry talk, a "point" doesn't have any actual size. In our case, we
- want to apply geometry to physical reality, namely the computer screen. As
- far as we're concerned, a "point" will be an individual graphics dot, also
- called a "pel" or "pixel" (for "picture element"). We can safely dispense
- with such formalities for our applications, for the most part.
-
- The most important thing about a point is that it has a location! Ok, that
- may not seem staggering, but it happens that there are a number of ways of
- specifying that location. The most common method is called the Cartesian
- coordinate system. It is based on a pair of numbers: X, which represents the
- distance along a horizontal line, and Y, which represents the distance along
- a vertical line. Consider the CGA in SCREEN 2, for instance. It has a
- coordinate system where X can be 0 - 639 and Y can be 0 - 199. The points
- are mapped on kind of an invisible grid.
-
- The Cartesian coordinate system makes it easy to visualize how a given point
- relates to other points on the same plane (or screen). It is particularly
- useful for drawing lines. Horizontal and vertical lines become a cinch: just
- change the X value to draw horizontally, or the Y value to draw vertically.
- Squares and rectangles (or boxes) can be formed by a combination of such
- lines. You can define an area of the screen in terms of an imaginary box
- (as GET and PUT do) with nice, clean boundaries. When we get to diagonal
- lines, it's a bit more of a nuisance, but still easy enough with the proper
- formula. That means we can do triangles too. Curves are worse... when it
- comes to even a simple circle or ellipse, the calculations start to get on
- the messy side. For things like that, though, there is an alternative.
-
- Another way of describing the location of a point is by Polar coordinates.
- In Cartesian coordinates, the location is specified by its horizontal and
- vertical distances from the "origin" or reference point, (0,0). In Polar
- coordinates, the location is specified by its distance and angle from the
- origin. Think of it as following a map: Cartesian coordinates tell you how
- many blocks down and how many blocks over the point is, whereas Polar
- coordinates tell you in which direction the point is and how far away it is
- "as the crow flies".
-
- A Little Geometry page 18
-
-
-
- The Polar coordinate system is great for describing many kinds of curves,
- much better than Cartesian. For example, a circle is defined as all of the
- points at a given (fixed) distance from a center point. Polar coordinates
- include both a distance and an angle, and we've already got the distance, so
- all we need to do is plot points at all of the angles on a circle.
- Technically, there is an infinite number of angles, but since our points
- don't follow the mathematical definition (they have a size), we don't have to
- worry about that.
-
- Let me digress for a moment to talk about angles. In BASIC, angles are
- specified in "radians". People more often use "degrees". Fortunately, it
- isn't hard to convert from one to the other. Both may be visualized on a
- circle. In radians, the sum of the angles in a circle is twice pi. In
- degrees, the sum of the angles is 360. That's something like this:
-
-
- 90 deg, 1/2 * pi rad
- /---|---\
- / | \
- / | \
- 180 degrees |___ . ___| 0 deg, 0 rad; or...
- pi radians | | 360 deg, 2 * pi rad
- \ | /
- \ | /
- \---|---/
- 270 deg, 3/2 * pi rad
-
-
- Ok, so that's a grotesquely ugly circle! Hopefully it shows the important
- thing, though. Angles start at zero on the extreme right and get larger as
- they work around counter-clockwise. The places marked on the "circle" are
- places where lines drawn horizontally and vertically through the center
- intersect the outside of the circle. These serve as a useful reference
- point, especially in that they help show how the angles can be construed from
- a Cartesian viewpoint.
-
- So much for angles. I'll go into conversion formulae, the value of pi, and
- other good junk a bit later on. Right now, let's get back to our discussion
- of Polar coordinates.
-
- I've explained how the Polar system makes it easy to draw a circle. Since
- you can vary the range of angles, it's equally simple to draw an arc. If you
- wanted to make a pie chart, you might want to join the ends of the arcs to
- the center of the circle, in which case you'd keep the angle constant (at the
- ends of the arc) and plot by changing the distance from zero to the radius.
- Circles are also handy for drawing equilateral polygons... you know, shapes
- with sides of equal length: triangle, square, pentagon, hexagon, etc. In
- this case, the best features of the Cartesian and Polar systems can be joined
- to accomplish something that would be difficult in either alone.
-
- A Little Geometry page 19
-
-
-
- The starting point for these polygons is the circle. Imagine that the
- polygon is inside a circle, with the vertices (pointy ends, that is, wherever
- the sides meet) touching the edge of the circle. These are equilateral
- polygons, so all of the sides and angles are the same size. Each of the
- vertices touches the circle, and each does it at exactly the same distance
- from each other along the arc of the circle. All of this detail isn't
- precisely necessary, but I hope it makes the reasoning a bit more clear!
-
- The circle can be considered as being divided by the polygon into a number of
- arcs that corresponds to the number of vertices (and sides) the polygon has.
- Think of a triangle inside a circle, with the tips all touching the circle.
- If you ignore the area inside the triangle, you will see that the circle is
- divided into three equal arcs. The same property is true of any equilateral
- polygon. As a matter of fact, as the number of vertices goes up, the circle
- is partitioned into more, but smaller, arcs... so that a polygon with a large
- enough number of vertices is effectively a circle itself!
-
- Anyway, the important thing is the equal partitioning. We know how many
- angles, be they degrees or radians, are in a circle. To get the points of a
- polygon, then... well, we already know the "distance" part, that's the same
- as the radius. The angles can be calculated by dividing the angles in the
- whole circle by the number of vertices in the desired polygon. Trying that
- case with the triangle, assuming a radius of 20 (why not), and measuring in
- degrees, that would give us the Polar points (20, 0), (20, 120), (20, 240).
- To make this a triangle, we need to connect the points using lines, which is
- easy in Cartesian coordinates. Since the computer likes Cartesian anyway, we
- just convert the Polar coordinates to Cartesian, draw the lines, and viola!
-
- That's essentially the method used by the G#Polygon routines. It's very
- simple in practice, but I haven't seen it elsewhere... probably because
- people forget about the Polar coordinate system, which is what makes it all
- come together. Polar coordinates also have simple equations for figures that
- look like daisies, hearts, and other unusual things. See "Equations, Etc"
- and ROSES.BAS for more information.
-
- On a side note, the Cartesian system isn't used by all computers, although
- it's the most common. Cartesian coordinates are the standard for what is
- called "raster" displays. The Polar coordinate system is used on "vector"
- displays. One example of a vector display that you may have seen is the old
- Asteroids video arcade game. They tend to be used for drawing monochrome
- "framework" pictures where the image must be very sharp (unlike in raster
- images, the diagonal lines aren't jagged, since there's no raster "grid").
-
- Equations, Etc page 20
-
-
-
- In this section, I'm going to list a number of equations and so forth. Some
- of them will be useful to you in experimenting with Polar coordinates. Some
- of them provide formulae for things that are already in GRAFWIZ, but which
- you might like to understand better. Some of them are just for the heck of
- it... note that not all of this information may be complete enough for you to
- just use without understanding it.
-
- One problem is... if you try to draw a circle, for instance, it will come out
- looking squashed in most SCREEN modes. Remember we said our points, unlike
- mathematical points, have a size? In most graphics modes, the points are
- effectively wider than they are high, so a real circle looks like an ellipse.
-
- Another problem is that these equations are based on an origin of (0,0) which
- is assumed to be at the center of the plane. In our case, (0,0) is at the
- upper right edge, which also makes the Y axis (vertical values) effectively
- upside-down. This isn't necessarily a problem, but sometimes it is! Adding
- appropriate offsets to the plotted X and Y coordinates often fixes it. In
- the case of Y, you may need to subtract the value from the maximum Y value to
- make it appear rightside-up.
-
- The displayed form of these equations may contain "holes", usually again
- because the points have a size, and/or since we try to use integer math to
- speed things up. If the screen had infinite resolution, this would not be a
- problem... meanwhile (!), getting around such problems takes fiddlin'.
-
- There are other problems, mostly due to forcing these simplified-universe
- theoretical equations into practical use. It's a lot easier to shoehorn in
- these simple equations than to use more accurate mathematical descriptions,
- though... a -lot- easier. So a few minor quirks can be ignored!
-
- With those disclaimers, here's the scoop on some handy equations.
-
- Polar coordinates may be expressed as (R, A), where R is radius or
- distance from the origin, and A is the angle.
-
- Cartesian coordinates may be expressed as (X, Y), where X is the distance
- along the horizontal axis and Y is the distance along the vertical axis.
-
- Polar coordinates can be converted to Cartesian coordinates like so:
- X = R * COS(A)
- Y = R * SIN(A)
-
- Angles may be expressed in radians or degrees. BASIC prefers radians.
- Radians are based on PI, with 2 * PI radians in a circle. There are 360
- degrees in a circle. Angles increase counter-clockwise from a 3:00 clock
- position, which is the starting (zero) angle. Angles can wrap around: 720
- degrees is the same as 360 degrees or 0 degrees, just as 3:00 am is at the
- same clock position as 3:00 pm.
-
- Angles may be converted between degrees and radians as follows:
- radians = degrees * PI / 180
- degrees = radians * 180 / PI
-
- Equations, Etc page 21
-
-
-
-
- The value PI is approximately 3.14159265358979. For most graphics
- purposes, a simple 3.141593 should do quite nicely. The true value of PI
- is an irrational number (the decimal part repeats forever, as near as
- anyone can tell). It has been calculated out to millions of decimal
- points by people with a scientific bent (and/or nothing better to do)!
-
- Line Drawing:
-
- One of the convenient ways of expressing the formula of a line (Cartesian
- coordinates) is:
- Y = M * X + B
-
- Given the starting and ending points for the line, M (the slope,
- essentially meaning the angle of the line) can be determined by:
- M = (Y2 - Y1) / (X2 - X1)
-
- The B value is called the Y-intercept, and indicates where the line
- intersects with the Y-axis. Given the ingredients above, you can
- calculate that as:
- B = Y1 - M * X1
-
- With this much figured out, you can use the original formula to calculate
- the appropriate Y values, given a FOR X = X1 TO X2 sort of arrangement.
- If the slope is steep, however, this will result in holes in the line. In
- that case, it will be smoother to recalculate the formula in terms of the
- X value and run along FOR Y = Y1 TO Y2... in that case, restate it as:
- X = (Y - B) / M
-
- Keep an eye on conditions where X1 = X2 or Y1 = Y2! In those cases,
- you've got a vertical or horizontal line. Implement those cases by simple
- loops to improve speed and to avoid dividing by zero.
-
-
-
- Circle Drawing:
-
- The Cartesian formula gets messy, especially due to certain aspects of the
- display that are not accounted for (mainly that pixels, unlike theoretical
- points, have a size and shape which is usually rectangular). The Polar
- formula is trivial, though. The radius should be specified to the circle
- routine, along with the center point. Do a FOR ANGLE! = 0 TO 2 * PI! STEP
- 0.5, converting the resulting (Radius, Angle) coordinates to Cartesian,
- then adding the center (X,Y) as an offset to the result. The appropriate
- STEP value for the loop may be determined by trial and error. Smaller
- values make better circles but take more time. Larger values may leave
- "holes" in the circle.
-
- Equations, Etc page 22
-
-
-
- Polygon Drawing:
-
- I've already discussed that, so I'll leave it as an exercise... or of
- course you can examine my source code if you register GRAFWIZ! The
- polygon routines are in BASIC, except for the line-drawing parts.
-
-
-
- Flower Drawing:
-
- This sort of thing would be rather difficult to do using strictly
- Cartesian methods, but with Polar coordinates, no problem. Here we
- calculate the radius based on the angle, using something like:
-
- FOR Angle! = 0 TO PI! * 2 STEP .01
-
- (a low STEP value is a good idea). The radius is calculated like so:
-
- Radius! = TotalRadius! * COS(Petals! * Angle!)
-
- The Petals! value specifies how many petals the flower should have. If it
- is odd, the exact number of petals will be generated; if even, twice that
- number will be generated.
-
- These figures are technically called "roses", although they more resemble
- daisies. Try the ROSES.BAS program to see how they look.
-
-
-
- Other Drawing:
-
- Experiment! There are all sorts of interesting things you can do with the
- Polar coordinate system in particular. Dig up those old Geometry texts or
- see if your Calculus books review it. If you've kept well away from math,
- try your local library or used book store.
-
- Miscellaneous Notes page 23
-
-
-
- Limitations:
-
- The EGA graphics routines are designed for use with EGAs having at least
- 256K RAM on board. They will not operate properly on old 64K EGA systems.
-
- Image loading (.MAC and .PCX) is quite slow. The bulk of the code is in
- BASIC at this point, to make it easier for me to extend the routines to
- cover other graphics modes. They will be translated to assembly later.
-
- The G#Write and G#WriteLn services do not allow for extended ASCII
- characters at this time. This includes CHR$(128) - CHR$(255). Later
- versions of these services will include support for extended ASCII,
- allowing for a redefinable extended character set as well as providing the
- standard characters as defined in text modes.
-
- The G#Write and G#WriteLn services interpret ASCII control characters,
- i.e. CHR$(0) - CHR$(31), according to the more standard handling used by
- DOS rather than the esoteric interpretation offered by QuickBASIC. This
- is not entirely a limitation, but it could conceivably cause confusion if
- your program happens to use these characters. The ASCII interpretion runs
- as follows:
-
- Code Meaning
- ==== =======
- 7 Bell (sound a beep through the speaker)
- 8 Backspace (destructive: eliminates the previous character)
- 9 Tab (based on 8-character tab fields)
- 10 LineFeed (move down one line, keep current column)
- 12 FormFeed (clear the screen)
- 13 Return (move to the start of the current line)
-
- G#MirrorH will only work properly on images with byte alignment! This
- means that the width of the image must be evenly divisible by four if
- SCREEN 1 is used, or evenly divisible by eight if SCREEN 2 is used.
-
- The graphics routines provide little error checking and will not do
- clipping (which ignores points outside the range of the graphics mode).
- If you specify coordinates which don't exist, the results will be unusual
- at best. Try to keep those values within the proper range!
-
- A very few of the graphics routines are slower than their counterparts in
- QuickBASIC. These are mostly drawing diagonal lines and filling boxes. I
- hope to get these better optimized in a future release. The GET/PUT image
- replacements are quite slow, but that's strictly temporary! I rushed 'em
- in by special request from a registered GRAFWIZ owner.
-
- Miscellaneous Notes page 24
-
-
-
- If you use PRINT in conjunction with GN4Write/WriteLn, be sure to save the
- cursor position before the PRINT and restore it afterwards... or use
- GN4Locate to position the GN4Write. BASIC and GRAFWIZ share the cursor
- position, but each interprets it to mean a different thing.
-
- The GN0 (360x480x256) and GN1 (320x400x256) routines use nonstandard VGA
- modes. The GN1 routines should work on just about any VGA, however. The
- GN0 routines will work on many VGAs, but are somewhat less likely to work
- than the GN1 routines due to the techniques involved.
-
- The GN0Write, GN0WriteLn, GN1Write and GN1WriteLn routines are somewhat
- slow in general and quite slow when it comes to scrolling the screen.
- These problems are related to peculiarities of these modes that I'm still
- grappling with. They will hopefully be improved in a future release.
-
- The EGA and VGA versions of G#Write and G#WriteLn routines expect to see a
- particular number of text rows per screen, although their expectations may
- be incorrect. This will be fixed in a later release.
-
- The G1Border routine is normally used to select the background (and
- border) color for SCREEN 1 mode. It can also be used in SCREEN 2 mode,
- where it will change the foreground color instead. Note that this may
- produce peculiar results if an EGA or VGA is used and it isn't locked into
- "CGA" mode, so be careful if your program may run on systems with displays
- other than true CGAs.
-
- GET/PUT Images:
-
- These guys have a lot of possibilities that Microsoft has never touched
- on. I'll be exploring this extensively in future versions. Among other
- things, expect the ability to change the colors, rotate the image, and
- translate the image from one graphics mode format to another. Enlarging
- and shrinking the image will also be a good bet.
-
- Odd ends:
-
- You can GET an image in SCREEN 1 and PUT it in SCREEN 2! It'll be shaded
- instead of in colors. This is a side-effect of the CGA display format.
-
- The first two elements of a GET/PUT array (assuming it's an integer array)
- tells you the size of the image. The first element is the width and the
- second is the height, in pixels. Actually, that's not quite true. Divide
- the first element by 2 for the width if the image is for SCREEN 1, or by 8
- if for SCREEN 13.
-
- Memory Considerations page 25
-
-
-
- GrafWiz uses almost none of BASIC's data space. Since the code is split into
- many modules, none of which are large, it is unlikely to affect your
- available programming memory either (unless you are using the QB environment
- with GRAFWIZ.QLB loaded). In other words, you will rarely have to worry
- about the RAM used by GrafWiz. The possible exception to this is if you use
- the Epson graphics routines, as they must allocate about 37K as a graphics
- buffer. The memory requirements listed here are included in case you are
- interested, not because I expect them to matter.
-
- Keep in mind that the memory used is offset to some extent by the memory you
- save by not using the graphics routines provided by BASIC. You save the most
- amount of memory by not using -any- BASIC graphics command, as this will
- avoid loading BASIC graphics support into your program.
-
- The GrafWiz routines are largely in modules based on specific graphics mode,
- i.e. each graphics mode has its own separate module(s). This means that only
- the mode(s) that you use are brought into your BASIC program.
-
- The overhead to support for each graphics mode ranges from around 1K-2K,
- depending on the routines you use.
-
- There is an additional module which supports the fonts for the G#Banner
- routine. If you use G#Banner, regardless of the graphics mode(s), the font
- module will be added to your program (just once). This adds about 4K.
-
- The G#Polygon routine is written in BASIC and uses single-precision math. It
- is not particularly large in itself, but will cause BASIC's floating point
- support to be linked in to your program. Depending on the program, this may
- cause the executable to grow by as much as 14K or so.
-
- Troubleshooting page 26
-
-
-
- Problem:
- QB says "subprogram not defined".
-
- Solution:
- The definition file was not included. Your program must contain the line
- REM $INCLUDE: 'GRAFWIZ.BI'
- before any executable code in your program. You should also start
- QuickBASIC with
- QB /L GRAFWIZ
- so it knows to use the GRAFWIZ library.
-
-
- Problem:
- LINK says "unresolved external reference".
-
- Solution:
- Did you specify GRAFWIZ as the library when you used LINK? You should!
- The GRAFWIZ.LIB file must be in the current directory or along a path
- specified by the LIB environment variable (like PATH, but for LIB files).
-
-
- Problem:
- The G#MirrorH routine is -almost- working right, but the results are
- truncated or wrapped to one side.
-
- Solution:
- Make your GET image a tad wider! The number of pixels wide must be evenly
- divisible by four in SCREEN 1, or by eight in SCREEN 2.
-
- Using GRAFWIZ with PDQ page 27
-
-
-
- Crescent Software's PDQ library does not currently support floating point
- math, which is required by the G#Polygon routines. Other than that, all of
- the routines should work fine with PDQ.
-
- Crescent thoughtfully provided me with a free copy of PDQ in order that I
- might resolve any incompatibilities between it and my BASIC libraries. If
- you are not familiar with PDQ, it is a replacement library for BASIC's own
- runtime libraries. While not providing every capability of plain QuickBASIC,
- it allows you to create substantially smaller EXE files for those programs
- that qualify. Support is currently lacking for floating point (single/double
- precision) numbers, music, and graphics, among other things. I understand
- that these will be added to a future version of the library. Communications
- support is available as an add-on package. PDQ also adds new capabilities
- which are quite impressive, such as being able to write small TSRs in BASIC.
- Check with Crescent for more recent details.
-
- Credits page 28
-
-
-
- For some of the reference works I have used in writing GRAFWIZ, see the
- BIBLIO.TXT file.
-
- I am also indebted to the following people, among others:
-
- Bill Cliver, president of F & I Controls, which markets software and hardware
- solutions for every aspect of car dealerships. He has provided me with the
- VGA system which has allowed me to support VGA graphics modes in GRAFWIZ.
-
- Mike Welch, co-sysop of The Shipyard BBS, the best BASIC support BBS that
- I've ever encountered. Among other fine deeds, he is responsible for the
- S&B4EGA and VGABOX demonstration programs which accompany GRAFWIZ.
-
- The 360x480 256-color VGA mode was made possible by John Bridges' VGAKIT 3.4
- library for C. Two of the most vital low-level routines are based directly
- on code from VGAKIT. If you use C, check your local BBS for this library.
-
-