'============================================================================ ' ** CIRCLE3.BAS ** **>> (c) 1991, 1998 G.H. George <<** ' Draws images of a superluminal circle (fish-eye lens view). ' Details are in the SUBprogram InfoPage . '============================================================================ ' Procedures: ' InfoPage: print welcome message. ' Initialize: set default values for the parameters. ' DrawCircle: draw the images of the current circle. ' Menu1: allow the user to change any parameter. DECLARE SUB InfoPage () DECLARE SUB Initialize (beta!, b!, h!, r!, tau!, dtau!, nPoint AS INTEGER, First AS INTEGER, Done AS INTEGER) DECLARE SUB DrawCircle (beta!, b!, h!, r!, tau!, dtau!, nPoint AS INTEGER) DECLARE SUB Images (beta!, b!, h!, r!, tau!, phi!, xTrue!, xf!, xb!, yTrue!, yf!, yb!) DECLARE SUB Scale (x!, y!, h!) DECLARE SUB Menu1 (beta!, b!, h!, r!, tau!, dtau!, nPoint AS INTEGER, Done AS INTEGER) DECLARE SUB Menu2 (beta!, b!, h!, r!, tau!, dtau!, nPoint AS INTEGER, Done AS INTEGER) DECLARE SUB NewRadius (r!) DECLARE SUB NewNumPoints (nPoint AS INTEGER) DECLARE SUB NewTime (tau!, b!, h!, r!) DECLARE SUB NewTimeStep (dtau!, b!, h!, r!) DECLARE SUB NewImpactParameter (d!) DECLARE SUB NewHeight (h!) DECLARE SUB NewVelocity (beta!) DECLARE SUB ResetTime (beta!, b!, h!, r!, tau!, dtau!) DECLARE FUNCTION TauMin! (beta!, b!, h!, r!) DECLARE SUB ClearLines (Lower AS INTEGER, Upper AS INTEGER) DECLARE SUB PressAnyKey () DECLARE SUB WaitForKey (KeyPressed AS STRING) ' Global constants: ' False: logical false (= 0) ' True: logical true (= -1) ' Pi: pi DEFINT F, T CONST False = 0, True = NOT False CONST Pi = 3.141593 ' Variables: ' beta: true velocity of circle (as multiple of speed of light) ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle ' tau: time (in kilometres) after closest approach ' dtau: time step (km) between consecutive plots ' nPoint: number of points on the circle to plot ' Done: logical variable governing exit from the program DIM nPoint AS INTEGER, Done AS INTEGER, tau AS SINGLE LET Done = False CALL InfoPage CALL Initialize(beta, b, h, r, tau, dtau, nPoint, (True), Done) DO UNTIL Done CALL DrawCircle(beta, b, h, r, tau, dtau, nPoint) CALL Menu1(beta, b, h, r, tau, dtau, nPoint, Done) LOOP CALL DrawCircle(beta, b, h, r, tau, dtau, nPoint) END DEFSNG F, T SUB ClearLines (Lower AS INTEGER, Upper AS INTEGER) '---------------------------------------------------------------------------- ' Clear all text from part of the screen, from row (Lower) to row (Upper). '---------------------------------------------------------------------------- ' Procedures: ' ' Parameters: [as shown above] ' Local Variables: ' OldRow: remembers the row number where the cursor was. ' OldCol: remembers the column number where the cursor was. ' Row: loop counter = current row on screen DIM OldRow AS INTEGER, OldCol AS INTEGER, Row AS INTEGER LET OldRow = CSRLIN LET OldCol = POS(0) LOCATE Lower, 1 FOR Row = Lower TO Upper ' Blank only the chosen rows. PRINT SPC(78); " " NEXT Row LOCATE OldRow, OldCol ' Restore the cursor to its former location. END SUB SUB DrawCircle (beta, b, h, r, tau, dtau, nPoint AS INTEGER) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Draw the images of the current circle.. '============================================================================ ' Procedures: ' Images: find the coordinates of current point on both images ' Parameters: ' beta: true velocity of circle (as multiple of speed of light) ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle ' tau: time (in kilometres) after closest approach ' dtau: time step (km) between consecutive plots ' nPoint: number of points on the circle to plot ' Local variables: ' horizon: pixel distance to the horizon ' phi: angle on the true circle ' xTrue: x coordinate of the current point on the true circle ' xf41: x coordinate of the forward image of the current point ' xb41: x coordinate of the backward image of the current point ' xf32: x coordinate of the forward image of the current point ' xb32: x coordinate of the backward image of the current point ' yTrue: y coordinate of the current point on the true circle ' yf41: y coordinate of the forward image of the current point ' yb41: y coordinate of the backward image of the current point ' yf32: y coordinate of the forward image of the current point ' yb32: y coordinate of the backward image of the current point ' xfOld41: x coordinate of previous point on forward image (Q 4 & 1) ' xbOld41: x coordinate of previous point on backward image ' xtOld41: x coordinate of previous point on the true circle ' xfOld32: x coordinate of previous point on forward image (Q 3 & 2) ' xbOld32: x coordinate of previous point on backward image ' xtOld32: x coordinate of previous point on the true circle ' yfOld41: y coordinate of previous point on forward image (Q 4 & 1) ' ybOld41: y coordinate of previous point on backward image ' ytOld41: y coordinate of previous point on the true circle ' yfOld32: y coordinate of previous point on forward image (Q 3 & 2) ' ybOld32: y coordinate of previous point on backward image ' ytOld32: y coordinate of previous point on the true circle ' cf: colour setting for current point on forward image ' cb: colour setting for current point on backward image DIM cf AS INTEGER, cb AS INTEGER CLS ' Rescale coordinates on graphics screen. LET horizon = h * Pi / 2 WINDOW (-2.2 * horizon, horizon)-(horizon, -horizon) ' - Print the title LOCATE 1, 1: COLOR 15, 0 PRINT " Visual images of a superluminal circle moving at speed "; PRINT USING "v =##.### c"; beta COLOR 11, 0: PRINT "Forward"; COLOR 7, 0: PRINT " and "; COLOR 12, 0: PRINT "backward"; COLOR 7, 0: PRINT " images separate from the line of "; COLOR 14, 0: PRINT "first appearance"; COLOR 7, 0: PRINT "." PRINT USING "Radius of circle = ###.## km"; r PRINT USING "### points plotted on each circle."; nPoint PRINT USING "Impact parameter of centre = ###.### km"; b PRINT USING "Observer's height = ###.### km"; h PRINT USING "Time step =###.### microseconds"; dtau / .299792; ' - Other information. ' LINE (-horizon, 0)-(horizon, 0) ' Draw line along b = 0 . ' Draw short 10 pixel perpendicular through point of closest approach (x = 0) LINE (0, -horizon / 20)-(0, horizon / 20) CIRCLE (0, 0), horizon, 13 ' Draw horizon (magenta circle) CIRCLE (0, 0), horizon / 2, 13 ' Draw inner magenta circle LOCATE 10, 1 COLOR 13, 0: PRINT "Outer circle"; : COLOR 7, 0 PRINT " is the horizon." LOCATE 12, 1 COLOR 13, 0: PRINT "Inner circle"; : COLOR 7, 0 PRINT " is 45 deg. down" PRINT "and is"; h; "km away" PRINT "from the central point." LOCATE 16, 1 PRINT "Time after "; COLOR 15, 0: PRINT "apparent": COLOR 7, 0 PRINT " closest approach of centre:" PRINT USING " t = ####.### km"; tau; ' print clock time in km. PRINT USING " = ####.## &"; tau / .299792; CHR$(230) + "s" ' & in microsec. ' LET phi = -Pi / 2 ' Begin circle at due south. CALL Images(beta, b, h, r, tau, phi, xTrue, xf41, xb41, yTrue, yf41, yb41) LET xf32 = xf41 LET xb32 = xb41 LET xfOld41 = xf41 ' keep record of coordinates of these LET xbOld41 = xb41 ' image points. LET xtOld41 = xTrue LET xfOld32 = xf32 LET xbOld32 = xb32 LET xtOld32 = xTrue LET yf32 = yf41 LET yb32 = yb41 LET yfOld41 = yf41 LET ybOld41 = yb41 LET ytOld41 = yTrue LET yfOld32 = yf32 LET ybOld32 = yb32 LET ytOld32 = yTrue LET phi = phi + 2 * Pi / nPoint ' go to next point anticlockwise on circle. DO ' Right half of circle: IF xf41 = xb41 THEN ' Image not appeared yet. LET cf = 8: LET cb = 8 ' Plot dark grey on black ELSE LET cf = 11: LET cb = 12 ' Forward bright cyan, backward br red END IF CALL Images(beta, b, h, r, tau, phi, xTrue, xf41, xb41, yTrue, yf41, yb41) LINE (xfOld41, yfOld41)-(xf41, yf41), cf ' connect old & new fwd image pts. LINE (xbOld41, ybOld41)-(xb41, yb41), cb ' connect old & new bwd image pts. LINE (xtOld41, ytOld41)-(xTrue, yTrue), 7 ' connect old and new true pts. LET xfOld41 = xf41 ' keep record of coordinates of the LET xbOld41 = xb41 ' new image points. LET xtOld41 = xTrue LET yfOld41 = yf41 LET ybOld41 = yb41 LET ytOld41 = yTrue ' Left half of circle: IF cf = 11 THEN ' Images of right half have appeared. IF xf32 = xb32 THEN ' BUT Images of left half not appeared yet. LET cf = 14: LET cb = 14 ' Plot yellow on black ELSE LET cf = 11: LET cb = 12 ' Forward bright cyan, backward br red END IF END IF CALL Images(beta, b, h, r, tau, (Pi - phi), xTrue, xf32, xb32, yTrue, yf32, yb32) LINE (xfOld32, yfOld32)-(xf32, yf32), cf ' connect old & new fwd image pts. LINE (xbOld32, ybOld32)-(xb32, yb32), cb ' connect old & new bwd image pts. LINE (xtOld32, ytOld32)-(xTrue, yTrue), 7 ' connect old and new true pts. LET xfOld32 = xf32 ' keep record of coordinates of the LET xbOld32 = xb32 ' new image points. LET xtOld32 = xTrue LET yfOld32 = yf32 LET ybOld32 = yb32 LET ytOld32 = yTrue LET phi = phi + 2 * Pi / nPoint ' go to next point anticlockwise. LOOP UNTIL phi > Pi / 2 ' continue anticlockwise until due north. ' - Finally: plot images of centre of circle. ' calculate position of images of centre (r=0). CALL Images(beta, b, h, 0, tau, 0, xTrue, xf41, xb41, yTrue, yf41, yb41) PSET (xTrue, yTrue), 15 ' plot true centre of circle. PSET (xf41, yf41), 11 ' plot forward image of centre. PSET (xb41, yb41), 12 ' plot backward image of centre. END SUB SUB Images (beta, b, h, r, tau, phi, xTrue, xf, xb, yTrue, yf, yb) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Returns the x & y coordinates of the true circle and both images for ' the current point on the true circle. '============================================================================ ' Procedures: ' Scale: adjust (x,y) using a spherical projection. ' Parameters: ' beta: true velocity of circle (as multiple of speed of light) ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle ' tau: time (in kilometres) after closest approach ' phi: angle on the true circle ' xTrue: x coordinate of the current point on the true circle ' xf: x coordinate of the forward image of the current point ' xb: x coordinate of the backward image of the current point ' yTrue: y coordinate of the current point on the true circle ' yf: y coordinate of the forward image of the current point ' yb: y coordinate of the backward image of the current point ' Local variables: ' d: min. distance of centre of circle from observer ' y: y coordinate of current point before projection ' y2: distance offset due to y & z coordinates of current point ' TimeOffset: time offset (km) due to x coordinate of current point ' tt: adjusted time for the current point ' b2: square of the true velocity beta. ' Disc: discriminant in the expression for xf and xb LET d = SQR(b * b + h * h) LET y = b + r * SIN(phi) LET y2 = d * d + (r * SIN(phi)) ^ 2 + (2 * r * SIN(phi) * b) LET TimeOffset = ABS(d) + ABS(r) * COS(phi) / beta LET tt = tau + TimeOffset ' N.B. time measured in kilometres (c = 1). LET b2 = beta * beta LET Disc = b2 * tt * tt - (b2 - 1) * (y2) LET xTrue = beta * (tau + d) + r * COS(phi) ' true position of point. IF tt < SQR(b2 - 1) / beta * ABS(y) OR Disc < 0 THEN LET xf = -SQR(y2 / (b2 - 1)) ' images have not yet appeared. LET xb = xf ELSE LET xf = beta * (-tt + SQR(Disc)) / (b2 - 1) LET xb = beta * (-tt - SQR(Disc)) / (b2 - 1) END IF LET yTrue = y LET yf = y LET yb = y ' Apply the spherical projection. CALL Scale(xTrue, yTrue, h) CALL Scale(xf, yf, h) CALL Scale(xb, yb, h) END SUB SUB InfoPage '---------------------------------------------------------------------------- ' Print a welcome message, explaining the purpose of this program. '---------------------------------------------------------------------------- ' No parameters or local variables. ' Procedures: ' ClearLines: clear all text from part of the screen ' PressAnyKey: prompt the user to press any key in order to continue. SCREEN 0 ' Text screen (default mode) CLS COLOR 15, 1 ' bright white on blue CALL ClearLines(2, 4) LOCATE 3, 9 PRINT "SIMULATION FOR THE APPEARANCE OF HIGH SPEED VIRTUAL OBJECTS." COLOR 7, 0 ' default: white on black LOCATE 5, 1 PRINT "Imagine a projector is sweeping the image of a circle of radius r" PRINT "along a flat surface with constant true velocity _v_ . " PRINT "Imagine that an observer is placed b units away from (the closest" PRINT "point of approach on) the path of the centre of the circle and is" PRINT "then elevated h units above the surface." PRINT "What would that observer see of the circle?" PRINT PRINT "There is NO Lorentz contraction and the true speed can exceed the "; PRINT "speed " PRINT "of light, because the circle is only a projection, not a real object." PRINT "The only distortions are due to the finite speed of light and the" PRINT "consequent light travel time delay effects." PRINT "A spherical (fish-eye lens) projection is used, so that the large" PRINT "magenta circle represents the horizon." PRINT PRINT "You have control of the true speed and size of the circle and of the" PRINT "observer's distance from the path (within certain limits). The scale" PRINT "is one pixel to (h.pi/400) kilometres, or (h.pi) km = one screen"; PRINT " height. " PRINT PRINT "The true position of the circle and its image as seen by the observer" PRINT "will be plotted on the screen at each time." CALL PressAnyKey END SUB SUB Initialize (beta, b, h, r, tau, dtau, nPoint AS INTEGER, First AS INTEGER, Done AS INTEGER) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Set default values for the parameters. '============================================================================ ' Procedures: ' TauMin: find the time of first appearance of the images ' Menu2: ask the user for any changes to the defaults ' WaitForKey: pause until any key is pressed ' Parameters: ' beta: true velocity of circle (as multiple of speed of light) ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle ' tau: time (in kilometres) after closest approach ' dtau: time step (km) between consecutive plots ' nPoint: number of points on the circle to plot ' First: logical variable = true iff this is the SUB's first call ' Done: logical variable governing exit from the program ' Local variables: ' LET beta = SQR(2) ' velocity = Sqr(2) times light speed. LET b = 50 ' impact parameter set to 50 kilometres. LET h = 200 ' observer's height set to 200 kilometres. LET r = 100 ' radius of circle set to 100 kilometres. LET tau = TauMin(beta, b, h, r) ' start at first appearance of images. LET dtau = ABS(tau) / 10 ' ten time steps from first appearance to ' closest approach. LET nPoint = 72 ' 72 points plotted on each circle. IF First THEN ' On first call only, go to menu 2. SCREEN 8 CLS CALL Menu2(beta, b, h, r, tau, dtau, nPoint, Done) END IF END SUB SUB Menu1 (beta, b, h, r, tau, dtau, nPoint AS INTEGER, Done AS INTEGER) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Present options to the user just after the current plot is complete. '============================================================================ ' Procedures: ' WaitForKey: pause until any key is pressed ' Menu2: ask the user for any changes to the parameters ' Parameters: ' beta: true velocity of circle (as multiple of speed of light) ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle ' tau: time (in kilometres) after closest approach ' dtau: time step (km) between consecutive plots ' nPoint: number of points on the circle to plot ' Done: logical variable governing exit from the program ' Local variables: ' KeyPressed: the upper case version of the key pressed by the user DIM KeyPressed AS STRING COLOR 7, 0 LOCATE 22, 5 PRINT "Select option:" LOCATE 23, 1 PRINT " = next time "; COLOR 12, 0: PRINT "-"; : COLOR 7, 0 ' highlight keys in bright red. PRINT " = prior time "; COLOR 12, 0: PRINT "E"; : COLOR 7, 0 PRINT " = else"; CALL WaitForKey(KeyPressed) SELECT CASE KeyPressed CASE "Y", "N", "F" ' default option to go to next time. LET tau = tau + dtau CASE "-", "B" ' option to backtrack one time step. LET tau = tau - dtau CASE "E", "Q", "X" ' option to change values or quit. CALL Menu2(beta, b, h, r, tau, dtau, nPoint, Done) CASE ELSE ' Invalid selection. ' do nothing: repeat present plot. END SELECT END SUB SUB Menu2 (beta, b, h, r, tau, dtau, nPoint AS INTEGER, Done AS INTEGER) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Allow the user to change a parameter value or to quit. '============================================================================ ' Procedures: ' WaitForKey: pause until any key is pressed ' NewVelocity: allow user to set new value for velocity beta ' NewImpactParameter: allow user to set new value for impact parameter b ' NewHeight: allow user to set new value for observer's height h ' NewTime: allow user to set new value for time tau ' NewTimeStep: allow user to set new value for time step dtau ' NewRadius: allow user to set new value for radius r ' NewNumPoints: allow user to set new value for # points nPoint ' ResetTime: reset time and time step to default values ' Initialize: reset all parameters to their starting values ' Parameters: ' beta: true velocity of circle (as multiple of speed of light) ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle ' tau: time (in kilometres) after closest approach ' dtau: time step (km) between consecutive plots ' nPoint: number of points on the circle to plot ' Done: logical variable governing exit from the program ' Local variables: ' KeyPressed: the upper case version of the key pressed by the user DIM KeyPressed AS STRING ' Present menu choices: ------------------------------------------------ SCREEN 0 DO CLS COLOR 15, 1 ' bright white on blue. CALL ClearLines(1, 3) LOCATE 2, 5 PRINT "Select an option"; COLOR 31, 1 ' blinking bright white colon. PRINT ":" LOCATE 6, 5 COLOR 7, 1: PRINT "T"; : COLOR 7, 0 PRINT ": change time on clock ( = "; tau; "km = "; PRINT USING "#.######### s)."; tau / 299792 LOCATE 7, 5 COLOR 7, 1: PRINT "S"; : COLOR 7, 0 PRINT ": change time step (dt = "; dtau; " km)." LOCATE 9, 5 COLOR 7, 1: PRINT "V"; : COLOR 7, 0 PRINT ": change velocity (now ="; beta; "c )." LOCATE 10, 5 COLOR 7, 1: PRINT "B"; : COLOR 7, 0 PRINT ": change impact parameter ( = "; b; " km)." LOCATE 11, 5 COLOR 7, 1: PRINT "H"; : COLOR 7, 0 PRINT ": change observer's height ( = "; h; " km)." LOCATE 13, 5 COLOR 7, 1: PRINT "R"; : COLOR 7, 0 PRINT ": change radius of circle (="; r; " km)." LOCATE 15, 5 COLOR 7, 1: PRINT "N"; : COLOR 7, 0 PRINT ": change number of points plotted on circle (="; nPoint; ")." LOCATE 17, 5 COLOR 11, 2: PRINT "P"; : COLOR 7, 0 PRINT ": reset time and time step to default values." LOCATE 18, 5 COLOR 15, 2: PRINT "Z"; : COLOR 7, 0 PRINT ": reset all parameters to their starting [default] values." LOCATE 20, 5 COLOR 26, 4: PRINT "Y"; : COLOR 7, 0 PRINT ": YES, accept all options as they are now." LOCATE 22, 5 COLOR 12, 1: PRINT "X"; : COLOR 7, 0 PRINT ": eXit from this program." LOCATE 2, 1 CALL WaitForKey(KeyPressed) ' Take the selected action: ---------------------------------------------- SELECT CASE KeyPressed CASE "X", "Q" ' raise exit flag. LET Done = True CASE "T" CALL NewTime(tau, b, h, r) CASE "S" CALL NewTimeStep(dtau, b, h, r) CASE "V" CALL NewVelocity(beta) CASE "B" CALL NewImpactParameter(b) CASE "H" CALL NewHeight(h) CASE "R" CALL NewRadius(r) CASE "N" CALL NewNumPoints(nPoint) CASE "P" CALL ResetTime(beta, b, h, r, tau, dtau) CASE "Z", "A" CALL Initialize(beta, b, h, r, tau, dtau, nPoint, (False), Done) END SELECT LOOP UNTIL KeyPressed = "Y" OR Done ' redisplay menu until user is satisfied. SCREEN 8 END SUB SUB NewHeight (h) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Allow the user to set a new value for the height of the observer. '============================================================================ ' Procedures: ' ClearLines: Clear all text from part of the screen ' Local Variable: ' NewH: value entered by the user ' Parameters: ' h: height of observer above the plane of the circle COLOR 15, 1 DO CALL ClearLines(1, 4) ' Clear previous entry. LOCATE 1, 10 PRINT "Enter observer's height h (1 < h <= 500 km)" PRINT TAB(10); "(number only, do not type "; CHR$(34); "km"; CHR$(34); INPUT "): ", NewH LET NewH = ABS(NewH) LOOP WHILE NewH > 500 ' Validate input. IF NewH > 1 THEN LET h = NewH ' Don't update h if null (or <1) entered. COLOR 7, 0 END SUB SUB NewImpactParameter (b) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Allow the user to set a new value for the impact parameter. '============================================================================ ' Procedures: ' ClearLines: Clear all text from part of the screen ' No local variables. ' Parameters: ' b: impact parameter of the centre of the circle COLOR 15, 1 DO CALL ClearLines(1, 4) ' Clear previous entry. LOCATE 1, 10 PRINT "Enter impact parameter b (0 <= b <= 250 km)" PRINT TAB(10); "(number only, do not type "; CHR$(34); "km"; CHR$(34); INPUT "): ", b LET b = ABS(b) LOOP WHILE b > 250 ' Validate input. COLOR 7, 0 END SUB SUB NewNumPoints (nPoint AS INTEGER) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Allow the user to set a new value for the number of points to be ' plotted on the circle. '============================================================================ ' Procedures: ' ClearLines: Clear all text from part of the screen ' No local variables. ' Parameters: ' nPoint: number of points on the circle to plot COLOR 15, 1 DO CALL ClearLines(1, 4) ' Clear previous entry. LOCATE 1, 10 PRINT "Enter the number of points to be plotted on each circle." LOCATE 2, 10 INPUT "(as an integer between 6 and 360): "; nPoint LOOP WHILE nPoint < 6 OR nPoint > 360 ' Validate input. COLOR 7, 0 END SUB SUB NewRadius (r) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Allow the user to set a new value for the radius of the circle. '============================================================================ ' Procedures: ' ClearLines: Clear all text from part of the screen ' Local Variable: ' NewR: ' Parameters: ' r: radius of the circle COLOR 15, 1 DO CALL ClearLines(1, 4) ' Clear previous entry. LOCATE 1, 10 PRINT "Enter the radius r of the circle (0 < r < 250 km)" PRINT TAB(10); "(number only, do not type "; CHR$(34); "km"; CHR$(34); INPUT "): ", NewR LOOP WHILE NewR < 0 OR NewR > 250 ' Validate input. IF NewR > .01 THEN LET r = NewR ' Update radius only if positive. COLOR 7, 0 END SUB SUB NewTime (tau, b, h, r) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Allow the user to set a new value for the time. '============================================================================ ' Procedures: ' ClearLines: Clear all text from part of the screen ' Local Variable: ' d: minimum distance of centre of circle from observer ' Parameters: ' tau: time (in kilometres) after closest approach ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle COLOR 15, 1 LET d = SQR(b * b + h * h) DO CALL ClearLines(1, 4) ' Clear previous entry. LOCATE 1, 10 PRINT "The time (in kilometres!) must be in the interval "; PRINT -100 * (d + r); "< t <"; 50 * (d + r); "." PRINT TAB(10); INPUT "Enter the new time: ", tau LOOP WHILE tau <= -100 * (d + r) OR tau > 50 * (d + r) ' Validate input. COLOR 7, 0 END SUB SUB NewTimeStep (dtau, b, h, r) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Allow the user to set a new value for the time increment dtau . '============================================================================ ' Procedures: ' ClearLines: Clear all text from part of the screen ' Local Variable: ' d: minimum distance of centre of circle from observer ' Parameters: ' dtau: time step (in kilometres) ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle COLOR 15, 1 LET d = SQR(b * b + h * h) DO CALL ClearLines(1, 4) ' Clear previous entry. LOCATE 1, 10 PRINT "The time step (in kilometres!) must be less than "; PRINT 2 * (d + r); "." PRINT TAB(10); INPUT "Enter the new value for the time step: ", dtau LOOP WHILE ABS(dtau) > 2 * (d + r) ' Validate input. COLOR 7, 0 END SUB SUB NewVelocity (beta) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Allow the user to set a new value for the velocity. '============================================================================ ' Procedures: ' ClearLines: Clear all text from part of the screen ' No local variables. ' Parameters: ' beta: true velocity of circle (as multiple of speed of light) COLOR 15, 1 DO CALL ClearLines(1, 4) ' Clear previous entry. LOCATE 1, 10 PRINT "Enter velocity as a multiple of the speed of light, c < v < 10 c" PRINT TAB(10); "(number only, do not type "; CHR$(34); "c"; CHR$(34); INPUT "): ", beta LOOP WHILE beta <= 1 OR beta > 10 ' Validate input. COLOR 7, 0 END SUB SUB PressAnyKey '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Prompts the user to press a key -- program pauses until user complies. '============================================================================ ' Procedures: ' WaitForKey: pause until any key is pressed ' Parameters: ' ' Local variables: ' KeyPressed: the key pressed by the user (not needed here) DIM KeyPressed AS STRING LOCATE 25, 1 PRINT "Press any key to continue: "; CALL WaitForKey(KeyPressed) LOCATE 24, 1 END SUB SUB ResetTime (beta, b, h, r, tau, dtau) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Reset time and time step to default values [for the other parameters]. '============================================================================ ' Procedures: ' TauMin: find the time of first appearance of the images ' WaitForKey: pause until any key is pressed ' Parameters: ' beta: true velocity of circle (as multiple of speed of light) ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle ' tau: time (in kilometres) after closest approach ' dtau: time step (km) between consecutive plots ' Local variables: ' LET tau = TauMin(beta, b, h, r) ' start at first appearance of images. LET dtau = ABS(tau) / 10 ' ten time steps from first appearance to ' closest approach. END SUB SUB Scale (x, y, h) '============================================================================ ' **>> (c) 1998 G.H. George <<** ' Adjusts the x & y coordinates according to a projection onto a sphere, ' radius h, centered on the observer at the origin. '============================================================================ ' Procedures: ' ' Parameters: ' h: height of observer above the plane of the circle ' x: x coordinate of the current point ' y: y coordinate of the current point ' Local variables: ' Factor: scale factor by which to multiply both coordinates ' r: distance of (x, y) from the origin LET r = SQR(x * x + y * y) IF r < h / 1000 THEN LET Factor = 1 ' No distortion near origin 'ELSEIF r > h * 10000 THEN ' LET Factor = (h / r) * (Pi / 2) ' Near the horizon ELSE LET Factor = (h / r) * ATN(r / h) END IF LET x = x * Factor LET y = y * Factor * 5 / 6 ' Include aspect ratio. END SUB FUNCTION TauMin (beta, b, h, r) '============================================================================ ' **>> (c) 1991, 1998 G.H. George <<** ' Returns the time (in km) of the first appearance of the images. '============================================================================ ' Procedures: ' ' Parameters: ' beta: true velocity of circle (as multiple of speed of light) ' b: impact parameter of the centre of the circle ' h: height of observer above the plane of the circle ' r: radius of the circle ' Local variables: ' b2: square of the true velocity beta. ' d: min. distance of centre of circle from observer LET b2 = beta * beta LET d = SQR(b * b + h * h) LET TauMin = ((SQR(b2 - 1) / beta) - 1) * d - r END FUNCTION SUB WaitForKey (KeyPressed AS STRING) '============================================================================= ' ** SUBprogram ** **>> (c) 1991, 1998 G.H. George <<** ' - cause program to pause until a key is pressed. '============================================================================= ' No procedures or local variables. ' Parameter: ' KeyPressed: the upper case version of the key pressed by the user. DO LET KeyPressed = UCASE$(INKEY$) LOOP UNTIL KeyPressed <> "" ' Pause until any key is pressed. IF ASC(KeyPressed) = 13 OR ASC(KeyPressed) = 32 THEN LET KeyPressed = "Y" ' ^-- treat and as a "YES" response. END SUB