_________________________________________________________________________

PROJ3D.BAS Accompanies "Three-Dimensional Perspective Plotting," by Tyrone Daulton, BYTE, December 1987, page 307.
_________________________________________________________________________

REM ********************************************************
REM *                          Three Dimension Plotting Program
REM *                                     Cartesian Coordinates
REM *                                            Version 5.1M
REM * by Tyrone Louis Daulton     October 1986
REM * Washington University in St. Louis
REM *  Department of Physics
REM *
REM *  Microsoft Basic Verison 2.1
REM *     for Apple Macintosh
REM * This is a streamlined general purpose Cartesian Plotting program.
REM *  This program is fully menu driven.
REM ********************************************************
DIM T(3,3),T1(3,3),T2(3,3)   : REM  Dimension Transformation Arrays
DIM N(3)                               : REM  Dimension Coordinate Array
DIM POLY%(12),PATT%(3)     : REM  Dimension Quick Draw Graphic Arrays
PI=3.141592654#                 : REM Value of pi
RESOLUTION=2.5                    : REM Size of grid "squares"

REM  BEGIN MAIN PROGRAM
REM * Menu Creation (Program overhead)
MENU 1,0,1,"Control"
MENU 1,1,1,"Stop": MENU 1,2,1,"Start"
MENU 2,0,1,"Grid Points"
MENU 2,1,1,"  100":MENU 2,2,1,"  156"
MENU 2,3,1,"  204":MENU 2,4,1,"  277"
MENU 2,5,1,"  400":MENU 2,6,1,"  625":MENU 2,7,1,"  800"
MENU 2,8,2,"1040":MENU 2,9,1,"1200":MENU 2,10,1,"1600":MENU 2,11,1,"1800"
MENU 2,12,1,"2500":MENU 3,0,1,"Hidden Lines"
MENU 3,1,2,"Solid Sheet":MENU 3,2,1,"Fish Net"
MENU 4,0,1,"Grid Pattern":MENU 4,1,2,"White": MENU 4,2,1,"Black":MENU 4,3,1,"Gray 1"
MENU 5,0,1,"Screen":MENU 5,1,2,"White": MENU 5,2,1,"Black"
LEAVE=0
RESOLUTION=3.1
MENU ON
ON MENU GOSUB MENUCHECK

IDLE: IF LEAVE=1 THEN CONTINUEON
GOTO IDLE

MENUCHECK: 
MENUNUMBER=MENU(0):MENUITEM=MENU(1)
IF MENUNUMBER=1 AND MENUITEM=2 THEN BLOCK1 ELSE BLOCK1A
BLOCK1: LEAVE=1: GOTO ENDOFSUB
BLOCK1A: IF MENUNUMBER=1 AND MENUITEM=1 THEN END
IF MENUNUMBER=3 THEN BLOCK2 ELSE BLOCK3
BLOCK2: IF MENUITEM=1 THEN DO1 ELSE DO2
             DO1: MENU 3,1,2 : MENU 3,2,1: MENU 4,0,1:SSFLAG=0: GOTO ENDOFSUB
             DO2: MENU 3,1,1: MENU 3,2,2:  SSFLAG=1:MENU 4,0,0:GOTO ENDOFSUB
BLOCK3: IF MENUNUMBER=2 THEN DO3 ELSE BLOCK4
             DO3:
BLOCK4: IF MENUNUMBER=2 THEN BLOCK5 ELSE BLOCK6
BLOCK5: REM * assign resolution to appropriate number of grid points
              IF MENUITEM=1 THEN RESOLUTION =10
              IF MENUITEM=2 THEN RESOLUTION=8
              IF MENUITEM=3 THEN RESOLUTION=7
              IF MENUITEM=4 THEN RESOLUTION=6
              IF MENUITEM=5 THEN RESOLUTION=5
              IF MENUITEM=6 THEN RESOLUTION=4
              IF MENUITEM=7 THEN RESOLUTION=3.53
              IF MENUITEM=8 THEN RESOLUTION=3.1
              IF MENUITEM=9 THEN RESOLUTION=2.89
              IF MENUITEM=10 THEN RESOLUTION=2.5
              IF MENUITEM=11 THEN RESOLUTION=2.36
              IF MENUITEM=11 THEN RESOLUTION=2
              FOR A=1 TO 12 : MENU 2,A,1 : NEXT A
              MENU 2,MENUITEM,2
BLOCK6: IF MENUNUMBER=4 THEN BB ELSE BLOCK7:
              BB: IF MENUITEM=1 THEN  pat=0 : GOTO EN
                    IF MENUITEM=2 THEN : pat=-1: GOTO EN
                    IF MENUITEM=3 THEN : pat=84!
                    EN: FOR A=1 TO 3 :MENU 4,A,1: NEXT A : MENU 4,MENUITEM,2
BLOCK7: IF MENUNUMBER=5 THEN BC ELSE ENDOFSUB:
              BC: IF MENUITEM=1 THEN MENU 5,1,2: MENU 5,2,1 : SCREA=0
                    IF MENUITEM=2 THEN MENU 5,2,2: MENU 5,1,1 : SCREA=-1
                    FOR A=0 TO 3: PATT%(A)=SCREA: NEXT A: CALL BACKPAT(VARPTR(PATT%(0)))
                    CLS
ENDOFSUB:
RETURN

CONTINUEON:
MENU 1,1,1: MENU 1,2,0
MENU 2,0,0:MENU 3,0,0:MENU 4,0,0:MENU 5,0,0
ON MENU GOSUB MENUCHECK2:
INPUT" Vantage Point {X,Y,Z} ",VX,VY,VZ   : REM Vantage Point
CALL Quadrant(VX,VY,Quad)
CALL Configuration(VX,VY,VZ)                  : REM  Construct Rotation transformations
CALL PLOT                                                : REM Plot the function
MENUCHECK2:END
STOP


REM ********************************************************
SUB PLOT STATIC
        SHARED SX0,SY0,Beta,T(),M,RESOLUTION,VR,I,J,PI,T1(),T2(),POLY%(),PATT%(),Quad,SSFLAG,pat,SCREA
        CLS:
                                          REM  {NX, NY, NZ} True coordinate system
                                          REM  {STX, STY} Screen coordinate system
DIM HOLDX(4),HOLDY(4)     :REM  Arrays to hold four image points' coordinates

X=0 : Y=0 : Z=50
IF pat=-1 THEN COL=30 ELSE COL=33
REM PLOT X,Y,Z AXIS
     IF SCREA=-1 THEN COLOR=30 ELSE COLOR=33
     CALL Transformation(X,Y,Z,STX,STY)
     LINE(SX0,SY0)-(STX,STY),COLOR
     X=50 : Y=0 : Z=0
     CALL Transformation(X,Y,Z,STX,STY)
     LINE(SX0,SY0)-(STX,STY),COLOR
     X=0 : Y=50 : Z=0
     CALL Transformation(X,Y,Z,STX,STY)
     LINE(SX0,SY0)-(STX,STY),COLOR

REM Calculate which quardrant to start plotting ( needed for hidden line removal)
NYlosign=1:NYhisign=1:NXlosign=1:NXhisign=1:ressignx=1:ressigny=1
IF Quad=1 THEN 1 ELSE 2
1 : NYlosign=-1 : NXlosign=-1
2 : IF Quad=2 THEN 3 ELSE 4
3 : NYlosign=-1: NXhisign=-1:ressignx=-1
4 : IF Quad=3 THEN 5 ELSE 6
5 : NYhisign=-1 : NXhisign=-1:ressignx=-1:ressigny=-1
6 : IF Quad=4 THEN 7 ELSE 8
7 : NYhisign=-1:NXlosign=-1:ressigny=-1
8 :

FLAG=0  : STX1=121 : STY1=50
FOR NY=NYlosign*50 TO NYhisign*50 STEP RESOLUTION*ressigny
    FOR NX=NXlosign*50 TO NXhisign*50 STEP RESOLUTION*ressignx
REM Construct the plot grid
   GOSUB FUNCTION                                                     : REM Calculate NZ
        CALL Transformation(NX,NY,NZ,STX,STY): REM Transform to screen coordinates
        PSET(STX,STY)
        IF NX=NXlosign*50 THEN BELOW ELSE GOON
        BELOW: NY=NY+RESOLUTION*ressigny: REM Calculate first pair of points
        
    GOSUB FUNCTION: REM Calculate NZ
        CALL Transformation(NX,NY,NZ,STX2,STY2): REM Transform to screen coordinates
        PSET(STX2,STY2)
        NY=NY-RESOLUTION*ressigny: REM Reset to current point in for loops
        HOLDX(1)=STX:HOLDX(2)=STX2: REM Remember point
        HOLDY(1)=STY:HOLDY(2)=STY2: REM Remember point
        NX=NX+RESOLUTION*ressignx 

        GOON:                                                                    : REM Calculate second pair, first pair is known
     GOSUB FUNCTION                                                     : REM Calculate NZ
        CALL Transformation(NX,NY,NZ,STX2,STY2): REM Transform to screen coordinates
        PSET (STX2,STY2)
        HOLDX(3)=STX2:HOLDY(3)=STY2: REM Remember point
        NY=NY+RESOLUTION*ressigny 

    GOSUB FUNCTION: REM Calculate NZ
        CALL Transformation(NX,NY,NZ,STX2,STY2): REM Transform to screen coordinates
        PSET (STX2,STY2)
        HOLDX(4)=STX2:HOLDY(4)=STY2: REM Remember point
        NY=NY-RESOLUTION*ressigny: REM Reset to current point in for loops
       
        CALL SOLIDSHEET(HOLDY(1),HOLDX(1),HOLDY(2),HOLDX(2),HOLDY(3),HOLDX(3),HOLDY(4),HOLDX(4),COL)
        HOLDX(1)=HOLDX(3):HOLDY(1)=HOLDY(3): REM Remember first pair
        HOLDX(2)=HOLDX(4):HOLDY(2)=HOLDY(4): REM Remember first pair
        NEXT NX
NEXT NY
GOTO JUMPER

REM Gosub routine to calculate NZ
       FUNCTION:
       NZ=COS( (NX^2+NY^2)/600*PI)*60: REM Insert Function Here <--
       IF NZ<0 THEN NZ=NZ/2
       IF (NX^2+NY^2)>900 THEN NZ=0
       RETURN
JUMPER:
END SUB


REM ********************************************************
SUB Transformation(X1,X2,X3,STTX,STTY) STATIC
      SHARED T(),VR,SX0,SY0,Beta,I,J
REM N(1)=X point               N(2)=Y point          N(3)=Z point


REM Rotate the coordinate axis with rotation transformation
REM  In other words transform true coordinates to proper coordinates
N(1)=X1:N(2)=X2:N(3)=X3
FOR I=1 TO 3
      NR(I)=0
      FOR J=1 TO 3
             NR(I)=NR(I)+T(I,J)*N(J)
      NEXT J
NEXT I


RDTP=VR-NR(1)          :REM This is the distance to the point if its y,z=0
IF RDTP<0 OR RDTP=0 THEN ohno ELSE Contin
ohno:
REM The point is at the viewer's location or it is behind the viewer
REM  The point can not be plotted
REM An error occurs
STOP

Contin:
REM : Transform proper coordinates into adjusted screen coordinates
TanThetasx=NR(2)/RDTP
TanThetasy=NR(3)/RDTP
SX=SX0*TanThetasx/TAN(Beta)
SY=SX0*TanThetasy/TAN(Beta)

REM: Transform adjusted screen coordinates into screen coordinates
STTX=SX0+SX:STTY=SY0-SY
END SUB



REM*********************************************************
SUB Configuration(VX,VY,VZ)STATIC
        SHARED PI,T(),T1(),T2(),PI,Beta,RS,SX0,SY0,VR,VRpolar,I,J
        
REM T2 is  the rotation matrix about the z axis
REM T1 is the rotation matrix about the y axis

Beta=PI/4      : REM   Angle the window subtends
RS=10            : REM    Distance viewer is away from window
SX0=250        : REM   1/2 screen size in x direction
SY0=150        : REM    1/2 screen size in y direction

FOR I=1 TO 3:FOR J=1 TO 3:T1(I,J)=0:T2(I,J)=0: NEXT J,I: REM Zero Arrays

REM Calculate needed values
VR=SQR( (VX)^2 + (VY)^2 + (VZ)^2 )    
VRpolar=SQR( (VX)^2 + (VY)^2 )

REM Create the two rotation transformation matrices
FOR I=1 TO 3: FOR J=1 TO 3:T1(I,J)=0:T2(I,J)=0: NEXT J,I
T2(1,1)=1:T2(2,2)=1:T2(3,3)=1
IF VRpolar=0 THEN SKIProtation
     T2(1,1)=(VX)/VRpolar
     T2(1,2)=(VY)/VRpolar
     T2(2,1)=-T2(1,2)
     T2(2,2)=T2(1,1)
SKIProtation:
T1(1,1)=VRpolar/VR
T1(1,3)=(VZ)/VR
T1(2,2)=1
T1(3,1)=-T1(1,3)
T1(3,3)=T1(1,1)

REM : Multiply the two matrices together
FOR I=1 TO 3
FOR J=1 TO 3
T(I,J)=0
FOR K=1 TO 3
T(I,J)=T(I,J)+T1(I,K)*T2(K,J)
NEXT K,J,I
END SUB


REM *********************************************************
SUB SOLIDSHEET(A1,B1,A2,B2,A3,B3,A4,B4,COL)STATIC
SHARED POLY%(),PATT%(),SSFLAG,pat,SCREA

REM This subroutine uses the quick draw machine routines
 CALL PENNORMAL
 CALL SHOWPEN
 
POLY%(0)=26
POLY%(1)=0 : POLY%(2)=0 : POLY%(3)=500 : POLY%(4)=250
POLY%(5)=A1 : POLY%(6)=B1 : POLY%(7)=A2 : POLY%(8)=B2
POLY%(9)=A4 : POLY%(10)=B4 : POLY%(11)=A3: POLY%(12)=B3
FOR A=0 TO 3 : PATT%(A)=pat : NEXT A
IF SSFLAG=0 THEN CALL FILLPOLY(VARPTR(POLY%(0)),VARPTR(PATT%(0)))
CALL FRAMEPOLY(VARPTR(POLY%(0)))
LINE(B1,A1)-(B3,A3),COL:  LINE(B2,A2)-(B4,A4),COL
 LINE(B1,A1)-(B2,A2),COL:  LINE(B3,A3)-(B4,A4),COL
END SUB


REM**********************************************************
SUB Quadrant(VX,VY,Quad)STATIC
IF VX>0 AND VY>0 THEN Quad=1
IF VX<0 AND VY>0 THEN Quad=2
IF VX<0 AND VY<0 THEN Quad=3
IF VX>0 AND VY<0 THEN Quad=4
END SUB

