Routines |
Prev: 2314 | Up: Map | Next: 2382 |
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 | Next: 2382 |