Prev: 2314 Up: Map Next: 2382
2320: THE 'CIRCLE' COMMAND ROUTINE
The address of this routine is found in the parameter table.
This routine draws an approximation to the circle with centre co-ordinates X and Y and radius Z. These numbers are rounded to the nearest integer before use. Thus Z must be less than 87.5, even when (X,Y) is in the centre of the screen. The method used is to draw a series of arcs approximated by straight lines.
CIRCLE has four parts:
• i. Tests the radius. If its modulus is less than 1, just plot X,Y.
• ii. Calls CD_PRMS1, which is used to set the initial parameters for both CIRCLE and DRAW.
• iii. Sets up the remaining parameters for CIRCLE, including the initial displacement for the first 'arc' (a straight line in fact).
• iv. Jumps to DRW_STEPS to use the arc-drawing loop.
Parts i. to iii. will now be explained in turn.
i. The radius, say Z', is obtained from the calculator stack. Its modulus Z is formed and used from now on. If Z is less than 1, it is deleted from the stack and the point X,Y is plotted by a jump to PLOT.
Input
Output
CIRCLE 2320 RST \$18 Get the present character.
2321 CP "," Test for comma.
2323 JP NZ,REPORT_C If not so, report the error.
2326 RST \$20 Get next character (the radius).
2327 CALL CLASS_06 Radius to calculator stack.
232A CALL CHECK_END Move to consider next statement if checking syntax.
232D RST \$28 Use calculator.
232E DEFB \$2A abs: X, Y, Z
232F DEFB \$3D re_stack: Z is re-stacked; its exponent is therefore available.
2330 DEFB \$38 end_calc
2331 LD A,(HL) Get exponent of radius.
2332 CP \$81 Test whether radius less than 1.
2334 JR NC,C_R_GRE_1 If not, jump.
2336 RST \$28 If less, delete it from the stack.
2337 DEFB \$02 delete: X, Y
2338 DEFB \$38 end_calc
2339 JR PLOT Just plot the point X, Y.
ii. 2π is stored in mem-5 and CD_PRMS1 is called. This subroutine stores in the B register the number of arcs required for the circle, viz. A=4*INT (π*SQR Z/4)+4, hence 4, 8, 12, etc., up to a maximum of 32. It also stores in mem-0 to mem-4 the quantities 2π/A, SIN(π/A), 0, COS (2π/A) and SIN (2π/A).
C_R_GRE_1 233B RST \$28
233C DEFB \$A3 stk_pi_2: X, Y, Z, π/2
233D DEFB \$38 end_calc
233E LD (HL),\$83 Now increase exponent to +83, changing π/2 into 2π.
2340 RST \$28 X, Y, Z, 2π.
2341 DEFB \$C5 st_mem_5: (2π is copied to mem-5)
2342 DEFB \$02 delete: X, Y, Z
2343 DEFB \$38 end_calc
2344 CALL CD_PRMS1 Set the initial parameters.
iii. A test is made to see whether the initial 'arc' length is less than 1. If it is, a jump is made simply to plot X, Y. Otherwise, the parameters are set: X+Z and X-Z*SIN (π/A) are stacked twice as start and end point, and copied to COORDS as well; zero and 2*Z*SIN (π/A) are stored in mem-1 and mem-2 as initial increments, giving as first 'arc' the vertical straight line joining X+Z, y-Z*SIN (π/A) and X+Z, Y+Z*SIN (π/A). The arc-drawing loop at DRW_STEPS will ensure that all subsequent points remain on the same circle as these two points, with incremental angle 2π/A. But it is clear that these 2 points in fact subtend this angle at the point X+Z*(1-COS (π/A)), Y not at X, Y. Hence the end points of each arc of the circle are displaced right by an amount 2*(1-COS (π/A)), which is less than half a pixel, and rounds to one pixel at most.
2347 PUSH BC Save the arc-count in B.
2348 RST \$28 X, Y, Z
2349 DEFB \$31 duplicate: X, Y, Z, Z
234A DEFB \$E1 get_mem_1: X, Y, Z, Z, SIN (π/A)
234B DEFB \$04 multiply: X, Y, Z, Z*SIN (π/A)
234C DEFB \$38 end_calc
234D LD A,(HL) Z*SIN (π/A) is half the initial 'arc' length; it is tested to see whether it is less than 0.5.
234E CP \$80
2350 JR NC,C_ARC_GE1 If not, the jump is made.
2352 RST \$28
2353 DEFB \$02 delete: X, Y, Z
2354 DEFB \$02 delete: X, Y
2355 DEFB \$38 end_calc
2356 POP BC Clear the machine stack.
C_ARC_GE1 235A RST \$28 X, Y, Z, Z*SIN (π/A)
235B DEFB \$C2 st_mem_2: (Z*SIN (π/A) to mem-2 for now)
235C DEFB \$01 exchange: X, Y, Z*SIN (π/A), Z
235D DEFB \$C0 st_mem_0: X, Y, Z*SIN (π/A), Z (Z is copied to mem-0)
235E DEFB \$02 delete: X, Y, Z*SIN (π/A)
235F DEFB \$03 subtract: X, Y-Z*SIN (π/A)
2360 DEFB \$01 exchange: Y-Z*SIN (π/A), X
2361 DEFB \$E0 get_mem_0: Y-Z*SIN (π/A), X, Z
2362 DEFB \$0F addition: Y-Z*SIN (π/A), X+Z
2363 DEFB \$C0 st_mem_0: (X+Z is copied to mem-0)
2364 DEFB \$01 exchange: X+Z, Y-Z*SIN (π/A)
2365 DEFB \$31 duplicate: X+Z, Y-Z*SIN (π/A), Y-Z*SIN (π/A)
2366 DEFB \$E0 get_mem_0: sa, sb, sb, sa
2367 DEFB \$01 exchange: sa, sb, sa, sb
2368 DEFB \$31 duplicate: sa, sb, sa, sb, sb
2369 DEFB \$E0 get_mem_0: sa, sb, sa, sb, sb, sa
236A DEFB \$A0 stk_zero: sa, sb, sa, sb, sb, sa, 0
236B DEFB \$C1 st_mem_1: (mem-1 is set to zero)
236C DEFB \$02 delete: sa, sb, sa, sb, sb, sa
236D DEFB \$38 end_calc
(Here sa denotes X+Z and sb denotes Y-Z*SIN (π/A).)
236E INC (IY+\$62) Incrementing the exponent byte of mem-2 sets mem-2 to 2*Z*SIN(π/A).
2371 CALL FIND_INT1 The last value X+Z is moved from the stack to A and copied to L.
2374 LD L,A
2375 PUSH HL It is saved in HL.
2376 CALL FIND_INT1 Y-Z*SIN (π/A) goes from the stack to A and is copied to H. HL now holds the initial point.
2379 POP HL
237A LD H,A
237B LD (\$5C7D),HL It is copied to COORDS.
237E POP BC The arc-count is restored.
237F JP DRW_STEPS The jump is made to DRW_STEPS.
(The stack now holds X+Z, Y-Z*SIN (π/A), Y-Z*SIN (π/A), X+Z.)
 Prev: 2314 Up: Map Next: 2382