A Little Geometry
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".
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.
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").
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
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)!
One of the convenient ways of expressing the formula of a line (Cartesian
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.
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.
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.
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.
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.