                      Trigonometry Unit - TRIG.TPU
                      ----------------------------
                  Compiled in Turbo Pascal 6.0 for DOS
                                   by
                       Sean O'Malley, February 1999

Questions?  Comments?
I can be reached at: ffrog@geocities.com
           Web Page: http://www.geocities.com/~ffrog

This TPU includes some basic (and not-so-basic) trig functions that
I've found necessary and very helpful when working with 2-D and 3-D
graphics.  Using the functions in this unit, I've made everything
from an L-Systems viewer to a program that creates 3-D DXF files out
of math equations.

There are a few functions here that require more explaining:

The "FindPolar" function works with two sets of points, one of which it
sets to the origin in its calculations and finds the angle of the
other in relation to the origin (the line going "east" from the origin
being at zero degrees).

This function and the FindAngle function - which returns degrees in the
manner of a real compass where 0 is up and degrees increase in a
clockwise direction - would have been considerably easier if Pascal had
included ArcSin and ArcCos functions.  Instead the only Arc function it
has is ArcTan!  Anyone have a fast ArcSin or ArcCos unit? :)

The procedure Rotate3D works, as all rotation, in relation to the
origin.  And as is usual, the X rotations occurs first, then the Y,
then the Z.  If you want a different order of rotation (for instance
Y first, then Z, then X), call the function three times setting the
rotations to 0 for the axes you don't want to rotate on.  This
procedure works with degrees instead of radians.

Here is the list of available functions, procedures and constants
in the TPU:

Constants:
----------
Const RadsPerDeg = (2 * Pi) / 360;   { Radians per degree. }
Const DegsPerRad = 360 / (2 * Pi);   { Degrees per radian. }
Const e = 2.718281828;               { Euler's constant. }
Const GoldenRatio = 1.618034;
      { The "Golden Ratio."  Equal to (1 + sqrt(5))/2 }

Functions & Procedures:
-----------------------
Function Rad2Deg(w:real):real;
Function Deg2Rad(w:real):real;
 { Convert radians to degrees and degrees to radians, respectively.
   I use these a LOT. :}

Function Tan(w:real):real;
 { Pascal doesn't have a built-in TAN function.  This is simply
   sin(w)/cos(w). }

Function Distance(x1,y1,x2,y2:real):real;
 { Find the distance between two points, (x1,y1) and (x2,y2).  Will
   always return a positive number. }

Function Distance3D(x1,y1,z1,x2,y2,z2:real):real;
 { Find the distance between two points in three-dimensional space. }

Function DSin(w:real):real;
Function DCos(w:real):real;
Function DTan(w:real):real;
 { Same as SIN, COS, and TAN, but can use degrees instead of radians.
   Much easier to work with! }

Function Power(x,y:real):real;
 { Returns X to the Y power.  Odd that Pascal didn't include something
   to do this ... By the way, because of the way this works Y NEEDS TO
   BE larger than 0.  If Y equals zero or negative, it will return an
   error.  (It uses the LN function, so that's why.) }

Function Cube(x:real):real;
 { Same as sqr(), only it cubes a number.  Handier than using Power,
   and it won't bother if x is zero or negative. }

Procedure Rotate3D(var x,y,z:real; ax,ay,az:real);
 { Rotate X,Y,Z *in relation to the origin* (0,0,0).  ax, ay, and az
   should be in degrees, not radians.  If you know how to do this
   rotation, you'll probably want to write a more efficient procedure
   which uses lookup tables since this procedure isn't meant to be
   highly efficient. }

Function FindAngle(x1,y1,x2,y2:real):real;
 { This function returns the angle (in degrees!) between two points,
   such as, assuming one point is at (1,1) and the second at (4,4), it
   will return 45.  This returns degrees like on a compass, NOT polar
   degrees; north is 0, east is 90, south 180, west 270.  This answers
   the question of what angle a line from point (x1,y1) would need to
   be at to intercept (x2,y2).  Note that for computer graphics the
   FindPolar function would probably be more useful. }

Function FindPolar(x1,y1,x2,y2:real):real;
 { Same as FindAngle, BUT this will return degrees based on Polar
   coordinates instead, where 0 is "east" and the numbers increase in
   a counter-clockwise direction.  (North is 90, west is 180, south is
   270, etc.)  Drawing a line from point (x1,y1) at the angle this
   function returns using the standard Polar-to-Cartesion formulae
   will result in a line which intercepts (x2,y2). }

Procedure Pol2Cart(var x,y:real;r,a:real);
 { Convert Polar coordinates (r,a) to Cartesian (x,y).  I couldn't make
   this a function since it needs to return two numbers.  It requires
   x,y to be two real variables so it can return the results.  MAKE SURE
   "a" is in degrees, not radians! }

Internal Functions
------------------
These are used internally by some of the TPU's functions.

Function FixDegs(w:real):real;
 { If w >= 360 then w := w - 360.  If w < 0 then w := w + 360.  This
   just makes sure the degree range of the variable passed to it is
   within 0 <= x < 360.  Pretty useless, but it was just easier when I
   wrote programs which would have angular increments in multiple
   variables and go over or under 360 on a regular basis. }

Function SafeDiv(x,y:real):real;
 { a := safediv(x,y) is the same as a := x/y, only this checks to make
   sure Y is not equal to zero so the program won't halt.  It will
   return 0 if Y is 0, otherwise return the result of the division.
   It makes no warnings, however. }

Function Findquad(x,y:real):byte;
 { Given an X and Y coordinate, this will tell what quadrant it's in
   based on the origin, returning either 1, 2, 3, or 4.  The quadrants
   are:  4 | 1
         --+--
         3 | 2
 }

2/99 - SMO