![]() |
Routines |
Prev: 2314 | Up: Map |
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:
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.
|
||||||||
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 |