home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d514
/
dkbtrace.lha
/
DKBTrace
/
dkbutsrc.lzh
/
lissajou.bas
< prev
next >
Wrap
BASIC Source File
|
1991-05-16
|
35KB
|
1,144 lines
'*************************
' LISSAJOU.BAS
' This program displays spherical Lissajous figures
' and writes a DKB Ray Tracer data file.
' Program written by Dan Farmer using algorithms from Clifford Pickover.
' See Scientific American January 1991 and Omni February 1990 for
' excellent examples by Pickover.
' COMPILING: QB3.0 or greater
' Requires /e switch (on error).
' Revision:
' Add EXPONENT variable
' Bug Fix: CLOSE #1 when finished with it.
' In WRITE.HEADER, use correct variable for R1 reference.
'
' 01/16/90 DMF Change most GOSUBS to SUBPROGRAMS and FUNCTIONS
' Specify type of most integers. (Default is single precision)
' Replace Shellsort with Quicksort
' Allow pausing of display, with option to write only the
' spheres displayed.
' Use Fractint color map or specified color(s) for DKB script.
' 03/08/91 DMF Drop FRACTINT color map option. Doubt if anyone uses it.
' Make colors all color declarations and use the names in
' the objects, rather than the values. Easier to edit when
' you have 100s of objects and several colors to change.
' 05/01/91 AAC Updated to DKB 2.11 by Aaron A. Collins
'*************************
' The following variables are public to all sub-programs:
'-----------------------------
COMMON SHARED S(2),F10$,FK10$,CU$,CD$,CR$,CL$,CSRL$,RTN$,ESC$,_
BS$,TB$,HOM$,EN$,PGUP$,PGDN$,ALPHAS$,NUMBERS$,P$
COMMON SHARED LABEL$(1),DATA$(1),TRUE%,FALSE%,GRMODE%
COMMON SHARED MAXCOLORS%, BG%,WINXCENTER%,WINYCENTER%
COMMON SHARED RADIUS, VIEWER
'-----------------------------
FALSE% = 0 : TRUE% = NOT FALSE%
'========================== USER-DEFINED FUNCTIONS
' FUNCTION: DESCRIPTION:
' ----------- ------------
' FNLOOKKEY$(X) --- Wait for a keystroke (called by SUB GETKEY)
' FUNUPPER$(X$) --- Convert X$ to upper case
' FNISBLANK(X$) --- Boolean : is string X$ NULL?
' FNCOMPARE(X$,Y$) --- Compare 2 strings for partial match
' FNPAD$(X$,LENG) --- Right-pad X$ with spaces to length LENG
' FNUNPAD$(X$) --- Remove leading & trailing spaces from string X$
' FNFMT$ (A#) --- Create a string from float A#
' FNFORMAT$(A#,FORM$) --- Create a formatted string from float A#
' FNZSCALE (RADIUS,Z,VIEWER) --- Adjust RADIUS to simulate perspective.
' --- LOOK FOR A KEYSTROKE
DEF FNLOOKKEY$(X)
STATIC A$
A$=INKEY$
IF LEN(A$)=2 THEN ' FILTER UNUSED CONTROL CODES
IF ASC(RIGHT$(A$,1)) > 81 THEN A$=""
END IF
FNLOOKKEY$=A$
END DEF
' --- CONVERT STRING TO UPPER CASE
DEF FNUPPER$(X$)
STATIC A$,I%
IF LEN(X$) >0 THEN
FOR I% = 1 TO LEN(X$)
A$ = MID$(X$,I%,1)
IF A$ >= "a" AND A$ <= "z" THEN_
MID$(X$,I%,1) = CHR$(ASC(A$)-32)
NEXT I%
END IF
FNUPPER$ = X$
END DEF
' --- IS A STRING A BUNCH OF BLANKS?
DEF FNISBLANK(X$) = (X$=SPACE$(LEN(X$)))
' --- COMPARE STRINGS FOR PARTIAL MATCH
DEF FNCOMPARE(X$,Y$) = (LEFT$(X$,LEN(Y$))=Y$)
'
' --- LEFT-JUSTIFY, BLANK FILL A STRING
DEF FNPAD$(X$,LENG) = LEFT$(X$+SPACE$(LENG),LENG)
' --- REMOVE LEADING AND TRAILING SPACES
DEF FNUNPAD$(X$)
WHILE LEFT$(X$,1)=" "
X$=MID$(X$,2)
WEND
WHILE RIGHT$(X$,1)=" "
X$=LEFT$(X$,LEN(X$)-1)
WEND
FNUNPAD$=X$
END DEF
' --- FORMAT A NUMERIC STRING, SIMPLE VERSION
DEF FNFMT$ (A#)
FORM$="-####.######"
STATIC SIGN, S$, P, A$, DEC, W$, F$, WF$, FF$, PAD$, ADD$
SIGN = SGN(A#)
A# = ABS(A#)
' --- SEPARATE WHOLE AND FRACTIONAL PARTS OF NUMBER
W$ = MID$(STR$(INT(A#)), 2)
IF W$ = "" THEN W$ = "0"
S$ = STR$(1 + A#)
P = INSTR(S$, ".")
IF P = 0 THEN
F$ = ""
ELSE F$ = MID$(S$, P + 1)
END IF
' --- SEPARATE WHOLE AND FRACTION FORMAT STRINGS
DEC = INSTR(FORM$, ".")
IF DEC = 0 THEN
WF$ = FORM$: FF$ = ""
ELSE WF$ = LEFT$(FORM$, DEC - 1)
FF$ = MID$(FORM$, DEC + 1)
END IF
ADD$ = "": PAD$ = " "
' --- ADD SIGN CHARACTER
IF LEFT$(WF$, 1) = "-" THEN
WF$ = MID$(WF$, 2)
IF SIGN = -1 THEN
ADD$ = ADD$ + "-"
ELSE ADD$ = ADD$ + " "
END IF
END IF
' --- HANDLE NUMERIC OVERFLOW AND UNDERFLOW
IF LEN(W$) > LEN(WF$) THEN W$ = "%" + RIGHT$(W$, LEN(WF$) - 1)
IF LEN(F$) > LEN(FF$) THEN F$ = LEFT$(F$, LEN(FF$))
' --- FORMAT THE NUMBER STRING
IF DEC > 0 THEN W$ = W$ + "." + F$ + STRING$(LEN(FF$) - LEN(F$), "0")
FNFMT$ = ADD$ + W$
END DEF
' --- FORMAT A NUMERIC STRING, DELUXE VERSION, WITH FORMAT STRING
DEF FNFORMAT$(A#,FORM$)
' A#: A POSITIVE INTEGER OR FLOATING POINT NUMBER
' FORM$: ##### RIGHT JUSTIFY, BLANK FILL
' 0#### RIGHT JUSTIFY, ZERO FILL
' $#### ADD DOLLAR SIGN
' -#### ADD MINUS SIGN IF NEGATIVE
' ##.## FORMAT DECIMAL POINT
STATIC SIGN,S$,P,A$,DEC,W$,F$,WF$,FF$,PAD$,ADD$
'
SIGN=SGN(A#)
A#=ABS(A#)
' --- SEPARATE WHOLE AND FRACTIONAL PARTS OF NUMBER
W$=MID$(STR$(INT(A#)),2)
S$=STR$(1+A#)
P=INSTR(S$,".")
IF P=0 THEN
F$=""
ELSE F$=MID$(S$,P+1)
END IF
' --- SEPARATE WHOLE AND FRACTION FORMAT STRINGS
DEC=INSTR(FORM$,".")
IF DEC=0 THEN
WF$=FORM$ : FF$=""
ELSE WF$=LEFT$(FORM$,DEC-1)
FF$=MID$(FORM$,DEC+1)
END IF
' --- DECIDE ON A PAD CHARACTER
IF LEFT$(WF$,1)="$" THEN
WF$=MID$(WF$,2)
ADD$="$"
ELSE ADD$=""
END IF
' --- ADD SIGN CHARACTER
IF LEFT$(WF$,1)="-" THEN
WF$=MID$(WF$,2)
IF SIGN=-1 THEN
ADD$=ADD$+"-"
ELSE ADD$=ADD$+" "
END IF
END IF
IF LEFT$(WF$,1)="0" THEN
PAD$="0"
ELSE PAD$=" "
END IF
' --- HANDLE NUMERIC OVERFLOW AND UNDERFLOW
IF LEN(W$)>LEN(WF$) THEN W$="%"+RIGHT$(W$,LEN(WF$)-1)
IF LEN(F$)>LEN(FF$) THEN F$=LEFT$(F$,LEN(FF$))
' --- FORMAT THE NUMBER STRING
A$=STRING$(LEN(WF$)-LEN(W$),PAD$)+W$
IF DEC>0 THEN A$=A$+"."+F$+STRING$(LEN(FF$)-LEN(F$),"0")
FNFORMAT$=ADD$+A$
END DEF
' ---
' --- Scale radius based upon distance from viewer
' ---
DEF FNZSCALE (RADIUS,Z,VIEWER)
FNZSCALE = TAN(ATN(RADIUS / ABS(VIEWER - Z))) * VIEWER
END DEF
'------------------------------------------------------------------------------
' DATA INPUT VARIABLES
' --- CONTROL CODES
CU$=CHR$(0)+CHR$(72) ' UP ARROW
CD$=CHR$(0)+CHR$(80) ' DOWN ARROW
CR$=CHR$(0)+CHR$(77) ' RIGHT ARROW
CL$=CHR$(0)+CHR$(75) ' LEFT ARROW
CSRL$=CHR$(29) ' CURSOR LEFT
RTN$=CHR$(13) ' CARRIAGE RETURN
ESC$=CHR$(27) ' ESCAPE
BS$=CHR$(8) ' BACKSPACE
TB$=CHR$(9) ' TAB
BT$=CHR$(0)+CHR$(15) ' BACKTAB
F10$=CHR$(0)+CHR$(68) ' FUNCTION KEY 10
HOM$=CHR$(0)+CHR$(71) ' HOME
EN$=CHR$(0)+CHR$(79) ' END
PGUP$=CHR$(0)+CHR$(73) ' PAGE UP
PGDN$=CHR$(0)+CHR$(81) ' PAGE DOWN
ALPHAS$="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "
NUMBERS$="0123456789"
P$=CHR$(250) ' DATA ENTRY FIELD PROMPT
' --- ENTRY SCREEN EDIT ARRAY
MAXFIELD%=11 ' SIZE OF FIELD SPEC TABLE
PARMFIELDS% = 10 ' NUMBER OF PARAMETER FIELD TO EDIT
DIM DATA$(MAXFIELD%): DIM LABEL$(MAXFIELD%)
DIM S(MAXFIELD%,3) ' DATA ENTRY FIELD SPECS
'
'
'
' --- DATA ENTRY/DISPLAY SCREEN TABLES
' S(Y,Z) :=
' Y := FIELD NUMBER
' Z := FIELD SPECS:
' 1 := FIELD LENGTH
' 2 := FIELD TYPES AVAILABLE:
' 1 := NUMERIC OR ALPHA
' 2 := NUMERIC
' 3 := ALPHA
' 4 := SIGNED NUMERIC
' 5 := DOLLAR
' 3 := Y-COORDINATE
' 4 := X-COORDINATE
'
' Name Fieldno Len, Type, Row, Col
SCREENDATA:
R1FIELD = 1 : DATA 3, 2, 04, 18
AFIELD = 2 : DATA 4, 5, 05, 18
BFIELD = 3 : DATA 4, 5, 06, 18
XXFIELD = 4 : DATA 1, 2, 07, 18
YXFIELD = 5 : DATA 1, 2, 08, 18
ZXFIELD = 6 : DATA 1, 2, 09, 18
RADFIELD = 7 : DATA 2, 2, 10, 18
QTYFIELD = 8 : DATA 4, 2, 11, 18
AXISFIELD = 9 : DATA 1, 3, 12, 18
ALGOFIELD =10 : DATA 1, 2, 13, 18
ANGLEFIELD =11 : DATA 4, 4, 24, 50
RESTORE SCREENDATA
FOR I=1 TO MAXFIELD%
FOR J=0 TO 3
READ S(I,J)
NEXT J
NEXT I
' Read default values into DATA$ array
CALL SET.DATA.DEFAULTS (DATA$())
' Initialize labels for input fields
LABEL$(1) = " R Value = "
LABEL$(2) = " A Value = "
LABEL$(3) = " B Value = "
LABEL$(4) = " X-Exponent = "
LABEL$(5) = " Y-Exponent = "
LABEL$(6) = " Z-Exponent = "
LABEL$(7) = " Sphere Rad = "
LABEL$(8) = "# of Spheres = "
LABEL$(9) = "View (x,y,z) = "
LABEL$(10)= "Method (1-5) = "
LABEL$(11)= "Angle to rotate: "
'------------------------------------------------------------------------------
VIEWER = 300 ' FOR SCREEN PREVIEW ONLY (LOW VALUE="WIDE ANGLE" PERSPECTIVE)
PAINTFLAG%=TRUE%
BG% = 7 ' SCREEN BACKGROUND COLOR (7 = gray)
COLS% = 640 : ROWS% = 350 :XCENTER%=COLS%/2 : YCENTER%=ROWS%/2
WINTOP%=16: WINBOTTOM%=ROWS%-50: WINLEFT%=XCENTER%/2+20: WINRIGHT%=COLS%-10
WINXCENTER%=(WINRIGHT%-WINLEFT%)/2 : WINYCENTER%=(WINBOTTOM%-WINTOP%)/2
MAXCOLORS% = 15
GRMODE% = 9
ON ERROR GOTO NOT.EGA ' Trap errors before setting graphics mode
SCREEN GRMODE%,1,0,0 ' Initialize graphics mode, page
ON ERROR GOTO 0 ' Reset error trapping
' Create an GUI-looking window for the data entry fields.
CALL GUIPANEL (8%,WINTOP%,WINLEFT%-8,WINBOTTOM%,2%) ' RAISED PANEL
CALL GUIPANEL (16%,190%,WINLEFT%-16,WINBOTTOM%-8,1%) ' RAISED PANEL
' COLORED DOTS "LOGO"
CALL GUIBOLT( 65%, 240%, 10%, 1%)
CALL GUIBOLT( 90%, 240%, 10%, 1%)
CALL GUIBOLT(115%, 240%, 10%, 1%)
CIRCLE ( 65,240),8,2 : PAINT ( 65,240),2
CIRCLE ( 90,240),8,5 : PAINT ( 90,240),5
CIRCLE (115,240),8,9 : PAINT (115,240),9
' The sunken panel can be printed in from rows 15-20
' starting at column 4 for a length of 18 Characters.
' 123456789012345678
LOCATE 15,4: PRINT " 3-D Lissajous "
LOCATE 16,4: PRINT " Generator "
LOCATE 20,4: PRINT " By Dan Farmer "
CALL GUIBOLT(10%,8%,4%,1%) ' UPPER LEFT BOLT
CALL GUIBOLT(COLS%-10%,8%,4%,1%) ' UPPER RIGHT BOLT
' Create panel for messages at screen bottom
CALL GUIPANEL(8%,WINBOTTOM%+8%,WINRIGHT%,ROWS%-8%,2%)
CALL GUIBOLT(24%,ROWS%-24%,4%,1%)
CALL GUIBOLT(WINRIGHT%-24%,ROWS%-24%,4%,1%)
' Create a GUI-looking window for the image display
CALL GUIPANEL (WINLEFT%,WINTOP%,WINRIGHT%,WINBOTTOM%,-3%) 'SUNKEN PANEL
VIEW (WINLEFT%+8,WINTOP%+8)-(WINRIGHT%-8,WINBOTTOM%-8)
COLOR 8,BG% ' BRITE WHITE
'FIRST.TIME%=TRUE%
DO WHILE TRUE% ' GO RIGHT TO DISPLAY
TOP:
GOSUB EDIT.PARMS
FIRST.TIME%=FALSE% ' NOW USER HAS CONTROL
COUNTER%=0%
ON ERROR GOTO TOO.BIG
REDIM QUEUE(SPHERES%, 5) : REDIM INDEX%(SPHERES%)
ON ERROR GOTO 0
COLOR ,7 ' CHANGE BG COLOR
CALL DISPMSG("Generating...")
FOR T% = 1 TO SPHERES%
COUNTER%=COUNTER%+1%
INDEX%(COUNTER%) = COUNTER% ' INITIALIZE SORT ARRAY
ON ALGO GOSUB ALGO.ONE, ALGO.TWO,ALGO.THREE,ALGO.FOUR,ALGO.FIVE
CALL ORIENT.XYZ(X,Y,Z,AXIS%)
' Scale radius for display
SCALED.RADIUS=FNZSCALE(RADIUS,Z,VIEWER)
' Queue parameters for sorting for display (hidden line removal)
QUEUE(COUNTER%, 1) = X: QUEUE(COUNTER%, 2) = Y
QUEUE(COUNTER%, 3) = Z: QUEUE(COUNTER%, 4) = SCALED.RADIUS
NEXT T%
' --- INDEX THE QUEUE ARRAY ON THE 4TH ELEMENT (Z)
CALL DISPMSG("Sorting Array...")
CALL QUICKSORT(QUEUE(),4,INDEX%()) ' SORTS THE INDEX, NOT THE QUEUE
' --- DRAW THE GRAPHICS IMAGE
CALL DISPMSG("Drawing...")
COLOR ,BG% ' RESTORE BG COLOR
QTY%=SPHERES%
CALL DISPLAY(QUEUE(),INDEX%(),TRUE%,QTY%)
IF QTY% > 0 THEN SPHERES%=QTY%
A$=""
DO WHILE A$ <> ESC$ AND A$ <> CHR$(13)
CALL DISPMSG("Finished: [D]=DKB Script [R]=Rotate [CR]=More [Esc]=Quit")
A$="" : CALL KEYFLUSH : CALL GETKEY(A$) : CALL CLEARMSG
IF A$= ESC$ THEN EXIT DO
IF INSTR("Dd",A$) > 0 THEN GOSUB MAKE.DKB
IF INSTR("Rr",A$) > 0 THEN CALL ROTATE (QUEUE(),INDEX%(),SPHERES%)
LOOP
LOOP
ENDIT:
SCREEN 0: WIDTH 80: CLS
PRINT
PRINT "LISSAJOU.EXE Version 1.1"
PRINT "Copyright 1991 by Dan Farmer."
PRINT "All rights reserved."
PRINT
END
MAXALGO = 5 ' CHANGE IF ALGORITHM VARIATIONS ARE ADDED
ALGO.ONE:
X = R1*(SIN(A*T%)*COS(B*T%) ^EXPONENT.X)
Y = R1*(SIN(A*T%)*SIN(B*T%) ^EXPONENT.Y)
Z = R1*(COS(A*T%) ^EXPONENT.Z)
RETURN
ALGO.TWO:
X = R1*(SIN(A*T%)*COS(B*T%) ^EXPONENT.X)
Y = R1*(COS(A*T%)*COS(B*T%) ^EXPONENT.Y)
Z = R1*(SIN(A*T%) ^EXPONENT.Z)
RETURN
ALGO.THREE:
X = R1*(SIN(A*T%)*SIN(B*T%) ^EXPONENT.X)
Y = R1*(SIN(A*T%)*COS(B*T%) ^EXPONENT.Y)
Z = R1*(SIN(A*T%) ^EXPONENT.Z)
RETURN
ALGO.FOUR: ' THIS ONE'S A KEEPER
PI = 3.1415
X = R1/4 * (A*SIN(2*(T%-PI/13)) ^EXPONENT.X)
Y = R1/4 * (-B*COS(T%) ^EXPONENT.Y)
Z = R1 * ((SIN(A*T%)) ^EXPONENT.Z)
RETURN
ALGO.FIVE: ' THIS ONE'S A *KEEPER*!
X = R1*(SIN(A*T%)*COS(A*T%) ^EXPONENT.X)
Y = R1*(SIN(B*T%)*SIN(B*T%) ^EXPONENT.Y)
Z = R1*(SIN(T%) ^EXPONENT.Z)
RETURN
EDIT.PARMS:
' --- DISPLAY THE DATA FROM THE FILE
SHOW.DATA:
CALL KEYFLUSH
FOR FIELDPTR%=1 TO PARMFIELDS%
LOCATE S(FIELDPTR%,2),3
COLOR 14 ' YELLOW TEXT
PRINT LABEL$(FIELDPTR%)
COLOR 8 ' GRAY TEXT
FILL$= "_"
CALL DISPFIELD (FIELDPTR%,DATA$(FIELDPTR%),FILL$)
NEXT FIELDPTR%
CALL DISPMSG("Press F10 to reset default values.")
' --- DO THE EDITING OF THE FIELDS
FIELDPTR%=1
DONE% = FALSE%
IF FIRST.TIME% GOTO END.EDIT.LOOP ' OK, OK, C-BEES, YOU HAVE THEM, TOO!
WHILE NOT DONE%
EXIT$="":PEND$=""
PRINT
COLOR 15 ' BRITE WHITE TEXT
CALL FIELDINPUT(FIELDPTR%,DATA$(FIELDPTR%),PEND$,EXIT$)
COLOR 8 ' GRAY TEXT
CALL DISPFIELD (FIELDPTR%,DATA$(FIELDPTR%),FILL$)
IF EXIT$ = CU$ THEN
FIELDPTR% = FIELDPTR% -1
IF FIELDPTR% < 1 THEN FIELDPTR% = 1 'WRAP-AROUND
ELSEIF EXIT$ = PGDN$ THEN DONE% = TRUE%
ELSEIF EXIT$ = ESC$ THEN
MSG$ = " Quit now "
A$="Y"
CALL VERIFY (MSG$,A$)
IF A$ <>"" THEN
CLS
GOTO ENDIT
END IF
CALL DISPMSG("Press F10 to reset default values.")
ELSEIF EXIT$ = F10$ THEN ' RESET TO DEFAULT VALUES
CALL SET.DATA.DEFAULTS(DATA$())
FIELDPTR%=1
GOTO SHOW.DATA
ELSE ' ANY OTHER CASE
FIELDPTR%=FIELDPTR% + 1
IF FIELDPTR% >PARMFIELDS% THEN DONE% = TRUE%
END IF
WEND
END.EDIT.LOOP:
' Assign the data input string values to their related variables
R1 = VAL(DATA$(1))
A = VAL(DATA$(2))
B = VAL(DATA$(3))
EXPONENT.X = VAL(DATA$(4))
EXPONENT.Y = VAL(DATA$(5))
EXPONENT.Z = VAL(DATA$(6))
RADIUS = VAL(DATA$(7))
SPHERES% = VAL(DATA$(8))
ALGO = VAL(DATA$(10))
AXIS$= DATA$(9)
IF INSTR("Zz",AXIS$) > 0 THEN
AXIS% = 1
ELSEIF INSTR("Yy",AXIS$) > 0 THEN
AXIS% = 2
ELSEIF INSTR("Xx",AXIS$) > 0 THEN
AXIS% = 3
ELSE
AXIS% = 1 ' DEFAULT Z-AXIS VIEW
END IF
' Use default values if nothing entered
IF R1=0 THEN R1=100
IF A=0 THEN A=0.1
IF B=0 THEN B=0.25
IF EXPONENT.X = 0 THEN EXPONENT.X = 1
IF EXPONENT.Y = 0 THEN EXPONENT.Y = 1
IF EXPONENT.Z = 0 THEN EXPONENT.Z = 1
IF RADIUS=0 THEN RADIUS=5
IF SPHERES%=0 THEN SPHERES%=500
IF ALGO = 0 THEN ALGO = 1: IF ALGO > MAXALGO THEN ALGO=1
RETURN
SUB SET.DATA.DEFAULTS (DATA$(1)) STATIC ' takes a one-element array DATA$()
' SET DEFAULT VALUES
DATA$(1) = "100" ' R1
DATA$(2) = "0.10" ' A
DATA$(3) = "0.25" ' B
DATA$(4) = "1" ' X-EXPONENT
DATA$(5) = "1" ' Y-EXPONENT
DATA$(6) = "1" ' Z-EXPONENT
DATA$(7) = " 8" ' RADIUS
DATA$(8) = " 500" ' QTY SPHERES
DATA$(9) = "Z" ' AXIS
DATA$(10)= "1" ' ALGORITHM
DATA$(11) = " 45" ' ANGLE OF ROTATION
END SUB
' --- Perform a simple 90 degrees rotation by swapping axis on
' --- the object.
SUB ORIENT.XYZ (X,Y,Z,AXIS%) STATIC
STATIC X1,Y1,Z1
X1=X : Y1=Y: Z1=Z ' Work variables
IF AXIS% = 1 THEN ' AXIS$="Z"
ELSEIF AXIS% = 2 THEN ' AXIS$="Y"
X = Z1 : Z = X1 ' SWAP X & Z AXIS (ROTATE 90 ON Y AXIS)
ELSEIF AXIS% = 3 THEN AXIS$="X"
Y = Z1 : Z = Y1 ' SWAP Y & Z AXIS (ROTATE 90 ON X AXIS)
END IF
END SUB
'
SUB ROTATE (QUEUE(2),INDEX%(1),SPHERES%) STATIC
' Get input from user (angle to rotate)
LOCATE S(11,2),33,1 : PRINT LABEL$(11);
CALL DISPFIELD(11%,DATA$(11),"-")
CALL FIELDINPUT(11%,DATA$(11),"","")
ANGLE = VAL(DATA$(11))
FOR I% = 1 TO SPHERES%
X = QUEUE(I%, 1) : Y = QUEUE(I%, 2)
Z = QUEUE(I%, 3)
YY=Y*COS(ANGLE) - Z*SIN(ANGLE)
ZZ=Y*SIN(ANGLE) + Z*COS(ANGLE)
Y = YY
Z = ZZ
' Gotta rescale the radii now.
SCALED.RADIUS=FNZSCALE(RADIUS,Z,VIEWER)
' Queue parameters for sorting for display (hidden line removal)
QUEUE(I%, 1) = X: QUEUE(I%, 2) = Y
QUEUE(I%, 3) = Z: QUEUE(I%, 4) = SCALED.RADIUS
NEXT I%
' Sort the index (not the queue)
CALL QUICKSORT(QUEUE(),4,INDEX%())
QTY%=SPHERES%
' Show the new arrangement
CALL DISPLAY(QUEUE(),INDEX%(),TRUE%,QTY%)
END SUB
' ---
' --- Sort the circles on Z, from most distant to closest for simple
' "hidden line removal". Farthest will be drawn first and overlapped
' by the nearer circles.
' Parms: ARRAY(2) = two element array of values needed sorting.
' ELEMENT% = key element of ARRAY() to use for the sort.
' In this program the 4th element (z values) are
' used as the sort key.
' INDEX%(1)= single dimension array of integers indexing ARRAY().
' ---
SUB QUICKSORT (ARRAY(2),ELEMENT%,INDEX%(1)) STATIC
STATIC LEFT%,RIGHT%,I%,J%,MEDIAN,STACK%,MAXDATA%
DIM LSTACK%(50),RSTACK%(50)
MAXDATA% = UBOUND(INDEX%)
STACK.HEIGHT% =1 : LSTACK%(1) =1: RSTACK%(1) = MAXDATA%
DO
LEFT% = LSTACK%(STACK.HEIGHT%)
RIGHT% = RSTACK%(STACK.HEIGHT%)
STACK.HEIGHT% = STACK.HEIGHT%-1
DO
I% = LEFT% : J% = RIGHT%
MEDIAN = ARRAY(INDEX%((LEFT%+RIGHT%)\2), ELEMENT%)
DO
WHILE ARRAY(INDEX%(I%),ELEMENT%) < MEDIAN
I% = I% +1
WEND
WHILE MEDIAN < ARRAY(INDEX%(J%),ELEMENT%)
J% = J% -1
WEND
IF I% <= J% THEN
SWAP INDEX%(I%), INDEX%(J%)
I% = I% +1 : J% = J% -1
END IF
LOOP WHILE I% <= J%
IF I% < RIGHT% THEN
STACK.HEIGHT% = STACK.HEIGHT% +1
LSTACK%(STACK.HEIGHT%) = I%
RSTACK%(STACK.HEIGHT%) = RIGHT%
END IF
RIGHT% = J%
LOOP WHILE LEFT% < RIGHT%
LOOP WHILE STACK.HEIGHT% <> 0
END SUB
' ---
' --- Here is where we draw the image, using sorted index of Z elements
' to draw most distant circles first.
' ---
SUB DISPLAY (QUEUE(2),INDEX%(1),PAINTFLAG%, QTY.DRAWN%) STATIC
STATIC I%
CALL DISPMSG("Press any key to pause drawing")
CLS 1 ' CLEAR GRAPHICS WINDOW
FOR I% = 1 TO UBOUND (INDEX%) ' DISPLAY IN INDEXED ORDER
X = QUEUE(INDEX%(I%), 1) : Y = QUEUE(INDEX%(I%), 2)
Z = QUEUE(INDEX%(I%), 3) : R = QUEUE(INDEX%(I%), 4)
KOLOR% = I% MOD MAXCOLORS% +1
XPOINT = WINXCENTER% + X: YPOINT = WINYCENTER% + Y
CIRCLE (XPOINT, YPOINT), R+1, 8 ' GRAY OUTLINE
CIRCLE (XPOINT, YPOINT), R, KOLOR% ' BOUNDS FOR PAINT
IF PAINTFLAG% = TRUE% THEN
PAINT (XPOINT, YPOINT), KOLOR%
END IF
EXIT$=INKEY$
IF EXIT$ <> "" THEN
CALL VERIFY ("Paused: Stop at" + STR$(I%) + " spheres",EXIT$)
IF EXIT$<>"" THEN QTY.DRAWN%=I%: EXIT SUB
CALL CLEARMSG
END IF
NEXT I%
END SUB
' --- Write the DKB script
'
MAKE.DKB:
SCREEN GRMODE%,1,1,1 ' SWITCH SCREEN PAGES
COLOR ,7 ' LIGHT GRAY (WHITE) BACKGROUND
CLS
' --- Get Output filename
GET.OUTPUT.FILE:
CALL DISPMSG ("Press <ENTER> to cancel")
LOCATE 2,4
PRINT "Name of output file: [.DAT] "
LOCATE 2,32 :LINE INPUT OUTFILE$
IF OUTFILE$="" THEN GOTO END.MAKE.DKB
IF INSTR(OUTFILE$,".") = 0 THEN OUTFILE$=OUTFILE$ + ".DAT"
GETCOLORS:
' --- GET COLOR NAMES FROM USER
LOCATE 4,4: PRINT "How many colors would you like to use? ";
LINE INPUT KOLOR.COUNT$ : KOLOR.COUNT = VAL(KOLOR.COUNT$)
IF KOLOR.COUNT=0 THEN GOTO END.MAKE.DKB
GET.COLORS:
REDIM KOLOR$(KOLOR.COUNT)
REDIM COLORNAME$(KOLOR.COUNT)
LOCATE 5,4
PRINT "Enter either standard DKB RGB values or a DECLARED color name."
LOCATE 6,4: PRINT "(Leave a color blank to exit early)"
ACTUAL.COLOR.COUNT=0
ALINE% = 7
FOR I% = 1 TO KOLOR.COUNT
ALINE%=ALINE% + 1
IF ALINE% = 24 THEN
FOR J% = 6 TO 23
LOCATE J%,1 : PRINT SPACE$(80); ' CLEAR THE LINE
NEXT J%
ALINE% = 8
END IF
LOCATE ALINE%,8: PRINT "Color #"; I%; " = COLOR ";
LINE INPUT KOLOR$(I%)
IF KOLOR$(I%)="" THEN
GOTO EXIT.GET.COLORS ' LEAVE THE LOOP
END IF
ACTUAL.COLOR.COUNT=ACTUAL.COLOR.COUNT+1
NEXT I%
EXIT.GET.COLORS:
KOLOR.COUNT=ACTUAL.COLOR.COUNT
IF KOLOR.COUNT = 0 THEN GOTO END.MAKE.DKB
' --- Begin to write the data file
OPEN OUTFILE$ FOR OUTPUT AS #1
' --- Write the VIEW, LIGHT SOURCE, and info data
GOSUB WRITE.HEADER
PRINT #1,"COMPOSITE" ' FOR EASY POSITIONING
' --- Write one SPHERE at a time
LOW.X = VAL(X$) : HI.X = VAL(X$)
LOW.Y = VAL(Y$) : HI.Y = VAL(Y$)
LOW.Z = VAL(Z$) : HI.Z = VAL(Z$)
FOR I%=1 TO SPHERES%
X$ = FNFMT$(QUEUE(INDEX%(I%), 1))
Y$ = FNFMT$(QUEUE(INDEX%(I%), 2))
Z$ = FNFMT$(QUEUE(INDEX%(I%), 3))
' --- TRACK MINIMUM AND MAXIMUM VECTORS
THIS.X = VAL(X$) : THIS.Y = VAL(Y$) : THIS.Z = VAL(Z$)
IF THIS.X < LOW.X THEN LOW.X = THIS.X
IF THIS.Y < LOW.Y THEN LOW.Y = THIS.Y
IF THIS.Z < LOW.Z THEN LOW.Z = THIS.Z
IF THIS.X > HI.X THEN HI.X = THIS.X
IF THIS.Y > HI.Y THEN HI.Y = THIS.Y
IF THIS.Z > HI.Z THEN HI.Z = THIS.Z
RADIUS$=FNFMT$(RADIUS)
' AKOLOR$=KOLOR$(I% MOD KOLOR.COUNT) 'COLOR VALUES
COLORALIAS$=COLORNAME$(I% MOD KOLOR.COUNT+1) 'COLORNAME TO WRITE TO OBJECT
GOSUB WRITE.DATA
NEXT I%
' --- Write the end of the COMPOSITE
PRINT #1, ""
PRINT #1, "END_COMPOSITE"
PRINT #1, "{"
PRINT #1, " Parameters used for this generation:"
PRINT #1, " R1 =";R1; " A =";A;" B =";B
PRINT #1, " X-Exponent =";EXPONENT.X
PRINT #1, " Y-Exponent =";EXPONENT.Y
PRINT #1, " Z-Exponent =";EXPONENT.Z
PRINT #1, " Sphere Radius =";RADIUS
PRINT #1, " Number of Spheres generated: ";SPHERES%
PRINT #1, " Axis = "; AXIS$
PRINT #1, " Algorithm = #"; ALGO
PRINT #1, ""
PRINT #1, " Minimum X = ";LOW.X ; " Maximum X = ";HI.X
PRINT #1, " Minimum Y = ";LOW.Y ; " Maximum Y = ";HI.Y
PRINT #1, " Minimum Z = ";LOW.Z ; " Maximum Z = ";HI.Z
PRINT #1, ""
PRINT #1, " (Min/Max XYZs with RADIUS figured in:)"
PRINT #1, " Leftmost Point = ";LOW.X-RADIUS ; " Rightmost Point = ";HI.X+RADIUS
PRINT #1, " Lowest Point = ";LOW.Y-RADIUS ; " Highest Point = ";HI.Y+RADIUS
PRINT #1, " Nearest Point = ";LOW.Z-RADIUS ; " Farthest Point = ";HI.Z+RADIUS
PRINT #1, "}"
PRINT #1, "{ *** End of ";OUTFILE$;" *** }"
CLOSE #1
CALL DISPMSG("DKB Script written as "+OUTFILE$+". Press any key to resume." )
CALL KEYFLUSH
CALL GETKEY("")
CALL CLEARMSG
END.MAKE.DKB:
CLOSE
CLS 0
SCREEN GRMODE%,1,0,0 ' SWAP SCREEN PAGE
COLOR ,BG% ' RESTORE BACKGROUND COLOR
RETURN
WRITE.HEADER:
PRINT #1, "{ Lissajous figure DKB datafile "; OUTFILE$
PRINT #1, " Generated on ";DATE$;" at ";TIME$
PRINT #1, "}"
PRINT #1, ""
PRINT #1, "INCLUDE ";CHR$(34);"shapes.dat" ;CHR$(34)
PRINT #1, "INCLUDE ";CHR$(34);"colors.dat" ;CHR$(34)
PRINT #1, "INCLUDE ";CHR$(34);"textures.dat" ;CHR$(34)
PRINT #1, ""
PRINT #1, "DECLARE Atexture = TEXTURE"
PRINT #1, " Shiny"
PRINT #1, " {Put further texture mods as needed here}"
PRINT #1, "END_TEXTURE"
PRINT #1, ""
PRINT #1, "VIEW_POINT"
PRINT #1, " LOCATION <0.0 0.0 -250.0> {Modify as needed}"
PRINT #1, " DIRECTION <0.0 0.0 1.0>"
PRINT #1, " UP <0.0 1.0 0.0>"
PRINT #1, " RIGHT <1.33333 0.0 0.0>"
PRINT #1, " LOOK_AT <0.0 0.0 0.0>"
PRINT #1, "END_VIEW_POINT"
PRINT #1, ""
PRINT #1, "{ Basic Light source }"
PRINT #1, "OBJECT"
PRINT #1, " SPHERE <0.0 0.0 0.0> 2.0 END_SPHERE"
PRINT #1, " TRANSLATE <100.0 100.0 -500.0>"
PRINT #1, " TEXTURE"
PRINT #1, " COLOUR White"
PRINT #1, " AMBIENT 1.0"
PRINT #1, " DIFFUSE 0.0"
PRINT #1, " END_TEXTURE"
PRINT #1, " LIGHT_SOURCE"
PRINT #1, " COLOUR White"
PRINT #1, "END_OBJECT"
PRINT #1, ""
PRINT #1, "{ Put all colors into declarations for ease of changing }"
FOR K=1 TO KOLOR.COUNT
COLORNAME$(K)="Color" + FNUNPAD$(STR$(K))
PRINT #1, "DECLARE " + COLORNAME$(K) + " = COLOR " + KOLOR$(K)
NEXT K
PRINT #1, ""
FOR K=1 TO KOLOR.COUNT
COLORNAME$(K)="Color" + FNUNPAD$(STR$(K))
PRINT #1, "DECLARE " + COLORNAME$(K) + "_Tex = TEXTURE Atexture COLOR " + COLORNAME$(K) + " END_TEXTURE"
NEXT K
PRINT #1, ""
RETURN
WRITE.DATA:
PRINT #1," OBJECT"
PRINT #1," SPHERE <";X$;" ";Y$;" ";Z$;"> " RADIUS$;" END_SPHERE
PRINT #1," TEXTURE " + COLORALIAS$ + "_Tex END_TEXTURE"
PRINT #1," COLOR " + COLORALIAS$
PRINT #1," END_OBJECT"
RETURN
TOO.BIG:
LOCATE 24,1 : PRINT CHR$(7);
PRINT "OOPS! Unable to allocate memory for that many spheres.";
CALL DISPMSG("Press any key to continue")
WHILE INKEY$="":WEND
LOCATE 24,1: PRINT SPACE$(80);
CALL CLEARMSG
RESUME TOP ' TRY AGAIN
' *** ***
' *** DATA ENTRY SUBROUTINES ***
' *** ***
'
' *** INPUT A STRING ***
SUB FIELDINPUT(FIELDNO%,ST$,PEND$,EXIT$) STATIC
' ST$ := INPUT FIELD
' PEND$ := PENDING KEYSTROKE
IF PEND$="" THEN
A$=""
CALL KEYFLUSH
ELSE A$=PEND$
PEND$=""
END IF
FI1: ' HOME CURSOR IN FIELD
CALL DISPFIELD(FIELDNO%,ST$+STRING$(S(FIELDNO%,0)-LEN(ST$),P$),FILL$)
CALL HOMECURSOR(FIELDNO%)
ST=0
IF A$<>"" THEN GOTO FI4 ' PROCESS PENDING KEYSTROKE
PRESS=FALSE%
LOCATE ,,1 ' TURN ON CURSOR
CALL GETKEY(A$)
IF ASC(A$)>=32 THEN ST$=""
GOTO FI1
FI2:
LOCATE ,,1 ' TURN ON CURSOR
CALL GETKEY(A$)
FI4: ' FILTER CONTROL KEYS
IF ASC(A$)<32 THEN GOTO CONTROLINPUT ' CHECK CHR, PRINT IT, UPDATE
FI5:
IF ST=S(FIELDNO%,0) THEN
CALL KEYFLUSH
ELSE GOSUB CHECKCHAR
IF ERRMSG$<>"" THEN
GOTO FI4
ELSE PRINT A$;
ST=ST+1
PRESS=TRUE%
END IF
END IF
GOTO FI2
' --- HANDLE CONTROL AND FUNCTION KEYS
CONTROLINPUT:
IF A$=CR$ THEN ' CURSOR RIGHT
IF ST<S(FIELDNO%,0) THEN
A$=CHR$(SCREEN(CSRLIN,POS(0)))
IF A$<>P$ THEN
PRINT A$;
ST=ST+1
END IF
END IF
ELSEIF A$=CL$ THEN ' CURSOR LEFT
IF ST>0 THEN
PRINT CSRL$;
ST=ST-1
END IF
ELSEIF A$=BS$ THEN ' DESTRUCTIVE BACKSPACE
IF ST>0 AND (ST=S(FIELDNO%,0) _
OR CHR$(SCREEN(CSRLIN,POS(0)))=P$) THEN
PRINT CSRL$;P$;CSRL$;
ST=ST-1
PRESS=TRUE%
END IF
ELSEIF A$=ESC$ THEN ' ERASE FIELD
EXIT$=A$
EXIT SUB
'ST$="" : ST=0 : A$=""
'GOTO FI1
END IF
' --- VALIDATE FIELD END EXIT
IF PRESS THEN
GOSUB CHECKWORD
IF ERRMSG$<>"" THEN GOTO FI4
END IF
EXIT$=A$
LOCATE ,,0
EXIT SUB
' *** CHARACTER CHECKER ***
CHECKCHAR:
ERRMSG$=""
ON S(FIELDNO%,1) GOSUB_
CHECKCHARALPHAORNUM,_
CHECKCHARNUM,_
CHECKCHARALPHA,_
CHECKCHARSIGNED,_
CHECKCHARBUX
IF ERRMSG$<>"" THEN CALL DISPERR(ERRMSG$,A$)
RETURN
CHECKCHARALPHAORNUM: ' 1 := NUMERIC OR ALPHA
IF ST$<>"" THEN
IF VAL(ST$)>0 OR LEFT$(ST$,1)="0" THEN
GOTO CHECKCHARNUM ' FIELD ALREADY NUMERIC
ELSE GOTO CHECKCHARALPHA ' FIELD ALREADY ALPHA
END IF
ELSEIF INSTR(NUMBERS$,A$)=0 AND INSTR(ALPHAS$,A$)=0 THEN
ERRMSG$="Please press <A to Z> or <0 to 9>"
END IF
RETURN
CHECKCHARNUM: ' 2 := NUMERIC
IF INSTR(NUMBERS$,A$)=0 THEN_
ERRMSG$="Please press <0 to 9>"
RETURN
CHECKCHARAN: ' 3 := ALPHA/NUMERIC
IF A$="?" THEN_
ERRMSG$="Please press <A to Z> or <0 to 9>"
RETURN
CHECKCHARBUX: ' 4 := DOLLARS
IF INSTR(NUMBERS$,A$)=0 AND A$<>"." THEN _
IF NOT(A$="#" AND ST=0) THEN _
ERRMSG$="Please press <0 to 9> or a period"
RETURN
CHECKCHARALPHA: ' 6 := ALPHA
IF INSTR(ALPHAS$,A$)=0 THEN _
ERRMSG$="Please press <A to Z>"
RETURN
CHECKCHARSIGNED: ' 9 := SIGNED NUMERIC
IF INSTR("+-",A$)=0 OR ST>1 THEN _
GOTO CHECKCHARNUM
RETURN
'
' *** WORD CHECKER ***
' --- ENTER WORD
CHECKWORD:
CALL HOMECURSOR(FIELDNO%)
ST$="" : ST=0
FOR I=1 TO S(FIELDNO%,0) ' READ FIELD FROM SCREEN
AA$=CHR$(SCREEN(CSRLIN,POS(0)))
IF AA$<>P$ THEN
IF S(FIELDNO%,1)<>7 OR INSTR(NUMBERS$,AA$)<>0 THEN
ST$=ST$+AA$
ST=ST+1
END IF
PRINT AA$;
ELSE I=I+999
END IF
NEXT I
ST=0
CALL HOMECURSOR(FIELDNO%)
' --- VALIDATE WORD
ERRMSG$=""
IF ST$<>"" THEN_
ON S(FIELDNO%,1) GOSUB_
CHECKWORDTYPE,_
CHECKWORDTYPE,_
CHECKWORDTYPE,_
CHECKWORDTYPE,_
CHECKPRICETYPE
IF ERRMSG$<>"" THEN CALL DISPERR(ERRMSG$,A$)
RETURN
CHECKPRICETYPE:
' ST$=FNFORMAT$(VAL(ST$),RIGHT$("##########.##",S(FIELDNO%,0)))
RETURN
CHECKWORDTYPE:
RETURN
END SUB
' *** ***
' *** MISC. SUBROUTINES ***
' *** ***
'
' --- HOME CURSOR IN FIELD
SUB HOMECURSOR(FIELDNO%) STATIC
LOCATE S(FIELDNO%,2),S(FIELDNO%,3)
END SUB
'
' --- CLEAR DATA ENTRY FIELD
SUB CLEARFIELD(FIELDNO%) STATIC
CALL HOMECURSOR(FIELDNO%)
PRINT SPACE$(S(FIELDNO%,0));
END SUB
'
' --- DISPLAY DATA ENTRY FIELD
SUB DISPFIELD(FIELDNO%,A$,FILL$) STATIC
CALL CLEARFIELD(FIELDNO%)
CALL HOMECURSOR(FIELDNO%)
IF NOT FNISBLANK(A$) THEN ' DON'T BOTHER WITH BLANK
PRINT A$;
ELSE PRINT STRING$(LEN(A$),FILL$)
END IF
END SUB
' --- REMEMBER CURSOR POSITION
SUB SAVECURS(V,H) STATIC
V=CSRLIN
H=POS(0)
END SUB
'
' --- FLUSH KEYBOARD BUFFER
SUB KEYFLUSH STATIC
WHILE INKEY$<>""
WEND
END SUB
'
' --- GET KEYSTROKE
SUB GETKEY(A$) STATIC
A$=""
WHILE A$=""
A$=FNLOOKKEY$(0)
WEND
END SUB
'
' --- DISPLAY A MESSAGE
SUB DISPMSG(MSG$) STATIC
STATIC LEFT%,MAXLEN%
MAXLEN%=70%
LEFT%=(80-MAXLEN%)/2
MSG$=FNUNPAD$(MSG$)
IF LEN(MSG$) > MAXLEN% THEN MSG$=LEFT$(MSG$,MAXLEN%) ' TRUNCATE IF NEEDED
CALL SAVECURS(V,H) ' SAVE CURSOR POSITION
LOCATE 24,LEFT%
PRINT SPC(MAXLEN%);
LOCATE 24,40-LEN(MSG$)/2
PRINT MSG$;
LOCATE V,H,1
END SUB
'
' --- CLEAR MESSAGE AREA
SUB CLEARMSG STATIC
CALL DISPMSG("")
END SUB
' --- DISPLAY ERROR MESSAGE
SUB DISPERR(MSG$,A$) STATIC
' MSG$ := MESSAGE TO DISPLAY
' A$ := CARRYOVER KEYSTROKE
CALL DISPMSG(MSG$)
PRINT BELL$;
CALL KEYFLUSH
CALL GETKEY(A$)
CALL CLEARMSG
END SUB
'
' --- ASK OPERATOR A YES/NO QUESTION, RESET EXIT$ IF NO
SUB VERIFY(MSG$,EXIT$) STATIC
CALL DISPERR(MSG$+" (Y or N)?",B$)
IF B$<>"y" AND B$<>"Y" THEN EXIT$=""
END SUB
SUB GUIPANEL (WLEFT%,WTOP%,WRIGHT%,WBOTTOM%,TOGGLE%) STATIC
STATIC DEPTH, I,INSET
' Parameter TOGGLE := -1 FOR INSET, 1 FOR OUTSET
' -2 FOR INSET 2 DEEP, 3 TO OUTSET 3 DEEP, ETC.
DEPTH%=ABS(TOGGLE%)
INSET%=(TOGGLE% < 0)
FOR I% = 0 TO DEPTH% -1
IF INSET% THEN ' INSET PANEL
LINE (WLEFT%+I%, WTOP%+I%) - (WLEFT%+I%,WBOTTOM%-I%), 8 ' LEFT SIDE
LINE (WLEFT%+I%, WTOP%+I%) - (WRIGHT%-I%,WTOP%+I%), 8 ' TOP LINE
LINE (WLEFT%+I%, WBOTTOM%-I%) - (WRIGHT%-I%,WBOTTOM%-I%),15 ' BOTTOM LINE
LINE (WRIGHT%-I%, WTOP%+I%) - (WRIGHT%-I%,WBOTTOM%-I%),15 ' RIGHT SIDE
ELSE ' OUTSET PANEL
LINE (WLEFT%+I%, WTOP%+I%) - (WLEFT%+I%,WBOTTOM%-I%) ,15 ' LEFT SIDE
LINE (WLEFT%+I%, WTOP%+I%) - (WRIGHT%-I%,WTOP%+I%) ,15 ' TOP LINE
LINE (WLEFT%+I%, WBOTTOM%-I%) - (WRIGHT%-I%,WBOTTOM%-I%), 8 ' BOTTOM LINE
LINE (WRIGHT%-I%, WTOP%+I%) - (WRIGHT%-I%,WBOTTOM%-I%), 8 ' RIGHT SIDE
END IF
NEXT I%
END SUB
SUB GUIBOLT(X%,Y%,R%,TOGGLE%) STATIC
STATIC DEPTH, I,INSET
' Parameter TOGGLE := -1 FOR INSET, 1 FOR OUTSET
' -2 FOR INSET 2 DEEP, 3 TO OUTSET 3 DEEP, ETC.
DEPTH%=ABS(TOGGLE%)
INSET%=(TOGGLE% < 0)
PI#=4*ATN(1!)
FOR I% = 0 TO DEPTH% -1
IF INSET% THEN ' INSET BOLT
CIRCLE (X%,Y%),R%-I%, 15, 0.5*PI#, 1.5*PI#
CIRCLE (X%,Y%),R%-I%, 8, 1.5*PI#, 0
ELSE
CIRCLE (X%,Y%),R%-I%, 8, 0.5*PI#, 1.5*PI#
CIRCLE (X%,Y%),R%-I%, 15, 1.5*PI#, 0
END IF
NEXT I%
END SUB
NOT.EGA: ' ERROR TRAP
SCREEN 0 : WIDTH 80
PRINT ""
PRINT "Sorry, but Lissajou requires EGA minimum to run."
PRINT ""
END
RETURN
' --- END OF LISSAJUO.BAS