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.
2357 JP PLOT Jump to plot X, Y.
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