--
--3d parametric plot
--By Matt Wachowski     
--See bottom of document for full instructions

f(u,v) = {cos(v)*u,sin(v)*u,u}

--Range variables  -- set u&v ranges  -- *** Uses Radians ***
umin:=-pi:
umax:=pi:
vmin:=-pi/2:
vmax:=pi/2:

--Our angle variables
--Set these for different views 
Angx:=pi/6:;     --angle of x axis (0=right)
Angy:=-pi/5:
Angz:=pi/2:
xscale:=1:;      --scale of values on x axis
yscale:=1:
zscale:=1:
len:=10:;        --length of axis lines

steps:=15:;      --this is detail level
s:=steps+1:;     --don't change this
Xmin:=-len:
Xmax:=len:
Ymin:=-len:
Ymax:=len:
plotline {Lx,Ly}
plotline {Hx,Hy}

--Put tidles around this block to hide xyz axis
plotline l3d({-len,0,0},{len,0,0})
plotline l3d({0,-len,0},{0,len,0})
plotline l3d({0,0,-len},{0,0,len})


--add tidles to hide alternate view--

--Alternate View--
Angx:=0:
Angy:=0:
Angz:=pi/2:
xscale:=1:
yscale:=0:
zscale:=2:
len:=10:
steps:=15:
s:=steps+1:
newaxis
plotline {Lx,Ly}
plotline {Hx,Hy}

--Put tidles around this block to hide xyz axis
plotline l3d({-len,0,0},{len,0,0})
plotline l3d({0,-len,0},{0,len,0})
plotline l3d({0,0,-len},{0,0,len})
--Alternate View end--


--The 3d code
p3dx(A) = cos(Angx)*A[1]*xscale+cos(Angy)*A[2]*yscale+cos(Angz)*A[3]*zscale
p3dy(A) = sin(Angx)*A[1]*xscale+sin(Angy)*A[2]*yscale+sin(Angz)*A[3]*zscale
l3d(A,B) = {{p3dx(A),p3dx(B)},{p3dy(A),p3dy(B)}}

Lx[x] = p3dx(f(uact(x),vact(x))) dim[s^2-s]
Ly[y] = p3dy(f(uact(y),vact(y))) dim[s^2-s]

Hx[x] = p3dx(f(uact2(x),vact2(x))) dim[s^2-s]
Hy[y] = p3dy(f(uact2(y),vact2(y))) dim[s^2-s]

uact(x) = (V(x)-1)*(umax-umin)/(steps-1)+umin
vact(x) =  (H(x)-1)*(vmax-vmin)/(steps-1)+vmin
frac(x) = x-trunc(x)
uact2(x) = (H(x)-1)*(umax-umin)/(steps-1)+umin
vact2(x) =  (V(x)-1)*(vmax-vmin)/(steps-1)+vmin
H(x) = trunc(x/s)+1 when frac(x/s)*s>.1, 0/0
V(x) = frac(x/s)*s when  frac(x/s)*s>.1, 0/0

~
*******************************
*        Documentation        *
*******************************
        
This program plots 3d parametric surfaces.  The surface is defined by:

f(u,v) = {xfunc(u,v),yfunc(u,v),zfunc(u,v)}

*Example surfaces*

f(u,v) = {cos(u),sin(u),v} --cylinder
f(u,v) = {g(u,v)*cos(u),g(u,v)*sin(u),v} --cylindrical plot
f(u,v) = {u,v,g(u,v)} --"normal" 3d plot
f(u,v) = {sin(u)*cos(v),sin(u)*sin(v),cos(u)} --sphere
f(u,v) = {g(u,v)*sin(u)*cos(v),g(u,v)*sin(u)*sin(v),g(u,v)*cos(u)}--spherical plot


*Plot Angle*

To set the viewing angle, set the variables Angx, Angy, and Angz.  These
three variables represent the angle in which corresponding axes will be
traced.  Angle variables are represented in radians.  The variables xscale,
yscale, and zscale are used to scale values on each of these axes.  The
following examples should give you the idea:

Angx=pi/6
Angy=-pi/6
Angz=pi/2
xscale=1
yscale=1
zscale=1

These values would give an isometric view, setting zscale=2 would make the
plot appear twice as "high" because the z-axis is pointing at pi/2 radians
(straight up).

Angx=0
Angy=pi/2
Angz=anything
xscale=1
yscale=1
zscale=0

These values would give a "top view" of the curve.  Note that Angz is
irrelevant in this case because it's scaled to 0 anyway by zscale.

Angx=pi/2
Angy=0
Angz=-pi/4
xscale=1
yscale=1
zscale=1

These values would give a "normal" 2d x-y axis with positive z values
shifting the curve downward at a 45 degree angle.

*plot speed and detail*

This program can be slow on non PPC machines.  Plot speed and detail can be
modified in the following ways:

1) Insert tildes, the symbol above `, around the block entitled "alternate
view" to suppress the plot to one view only.

2) Decrease the variable entitled "steps" to a lower integer value to cause
the curve to be plotted with fewer points.

3) Insert -- in front of either "plotline {Lx,Ly}" or "plotline {Hx,Hy}" to
suppress the "crossing" effect in the plot.  You may also want to do this in
cases of curves that form solid objects (such as a sphere) because more
lines in objects such as these often make the plot more confusing to view.

*other useful tips*

1) Plot curves with a low step value to set up viewing angle and scale, then
raise the step value to view the curve in more detail.

2) copy the "Alternate view" block multiple times in the file to create as
many views of the object as needed (Although too many make the plots look
smashed)

3) the len variable is mainly for convenience purposes.  Set Xmin, Xmax,
Ymin, and Ymax manually to shift or compress the resulting plot as needed

*A More Complex Example*

By using conditionals in your function, you can create interesting shapes:

g(x) = 4-x when (x<1),
       5-2*x when (x>=1 and x<2),
       1/4*x+.5 when (x>=2 and x<6),
       x-4 when (x>=6 and x<7),
       3 when (x>=7 and x<8),
       19-2*x when (x>=8 and x<9),
       5.5-1/2*x when (x<11), 0

f(u,v) = {g(v)*cos(u),g(v)*sin(u),v}
umin:=0
umax:=2*pi
vmin=:0
vmax=:11
steps:=12
~