Prev: 08992 Up: Map Next: 09341
09090: THE 'DRAW' COMMAND ROUTINE
The address of this routine is found in the parameter table.
This routine is entered with the co-ordinates of a point X0, Y0, say, in COORDS. If only two parameters X, Y are given with the DRAW command, it draws an approximation to a straight line from the point X0, Y0 to X0+X, Y0+Y. If a third parameter G is given, it draws an approximation to a circular arc from X0, Y0 to X0+X, Y0+Y turning anti-clockwise through an angle G radians.
The routine has four parts:
  • i. Just draws a line if only 2 parameters are given or if the diameter of the implied circle is less than 1.
  • ii. Calls CD_PRMS1 to set the first parameters.
  • iii. Sets up the remaining parameters, including the initial displacements for the first arc.
  • iv. Enters the arc-drawing loop and draws the arc as a series of smaller arcs approximated by straight lines, calling the line-drawing subroutine at DRAW_LINE as necessary.
Two subroutines, CD_PRMS1 and DRAW_LINE, follow the main routine. The above 4 parts of the main routine will now be treated in turn.
i. If there are only 2 parameters, a jump is made to LINE_DRAW. A line is also drawn if the quantity Z=(ABS X+ABS Y)/ABS SIN(G/2) is less than 1. Z lies between 1 and 1.5 times the diameter of the implied circle. In this section mem-0 is set to SIN (G/2), mem-1 to Y, and mem-5 to G.
DRAW 09090 RST 24 Get the current character.
09091 CP "," If it is a comma, then jump.
09093 JR Z,DR_3_PRMS
09095 CALL CHECK_END Move on to next statement if checking syntax.
09098 JP LINE_DRAW Jump to just draw the line.
DR_3_PRMS 09101 RST 32 Get next character (the angle).
09102 CALL CLASS_06 Angle to calculator stack.
09105 CALL CHECK_END Move on to next statement if checking syntax.
09108 RST 40 X, Y, G are on the stack.
09109 DEFB 197 st_mem_5: (G is copied to mem-5)
09110 DEFB 162 stk_half: X, Y, G, 0.5
09111 DEFB 4 multiply: X, Y, G/2
09112 DEFB 31 sin: X, Y, SIN (G/2)
09113 DEFB 49 duplicate: X, Y, SIN (G/2), SIN (G/2)
09114 DEFB 48 f_not: X, Y, SIN (G/2), (0/1)
09115 DEFB 48 f_not: X, Y, SIN (G/2), (1/0)
09116 DEFB 0 jump_true: X, Y, SIN (G/2)
09117 DEFB 6 to DR_SIN_NZ (if SIN (G/2)=0 i.e. G=2πN just draw a straight line).
09118 DEFB 2 delete: X, Y
09119 DEFB 56 end_calc
09120 JP LINE_DRAW Line X0, Y0 to X0+X, Y0+Y.
DR_SIN_NZ 09123 DEFB 192 st_mem_0: (SIN (G/2) is copied to mem-0)
09124 DEFB 2 delete: X, Y are now on the stack.
09125 DEFB 193 st_mem_1: (Y is copied to mem-1).
09126 DEFB 2 delete: X
09127 DEFB 49 duplicate: X, X
09128 DEFB 42 abs: X, X' (X'=ABS X)
09129 DEFB 225 get_mem_1: X, X', Y
09130 DEFB 1 exchange: X, Y, X'
09131 DEFB 225 get_mem_1: X, Y, X', Y
09132 DEFB 42 abs: X, Y, X', Y' (Y'=ABS Y)
09133 DEFB 15 addition: X, Y, X'+Y'
09134 DEFB 224 get_mem_0: X, Y, X'+Y', SIN (G/2)
09135 DEFB 5 division: X, Y, (X'+Y')/SIN (G/2)=Z', say
09136 DEFB 42 abs: X, Y, Z (Z=ABS Z')
09137 DEFB 224 get_mem_0: X, Y, Z, SIN (G/2)
09138 DEFB 1 exchange: X, Y, SIN (G/2), Z
09139 DEFB 61 re_stack: (Z is re-stacked to make sure that its exponent is available).
09140 DEFB 56 end_calc
09141 LD A,(HL) Get exponent of Z.
09142 CP 129 If Z is greater than or equal to 1, jump.
09144 JR NC,DR_PRMS
09146 RST 40 X, Y, SIN (G/2), Z
09147 DEFB 2 delete: X, Y, SIN (G/2)
09148 DEFB 2 delete: X, Y
09149 DEFB 56 end_calc
09150 JP LINE_DRAW Just draw the line from X0, Y0 to X0+X, Y0+Y.
ii. Just calls CD_PRMS1. This subroutine saves in the B register the number of shorter arcs required for the complete arc, viz. A=4*INT (G'*SQR Z/8)+4 (where G'=ABS G), or 252 if this expression exceeds 252 (as can happen with a large chord and a small angle). So A is a multiple of 4 from 4 to 252. The subroutine also stores in mem-0 to mem-4 the quantities G/A, SIN (G/2*A), 0, COS (G/A), SIN (G/A).
DR_PRMS 09153 CALL CD_PRMS1 The subroutine is called.
iii. Sets up the rest of the parameters as follow. The stack will hold these 4 items, reading up to the top: X0+X and Y0+Y as end of last arc; then X0 and Y0 as beginning of first arc. Mem-0 will hold X0 and mem-5 Y0. Mem-1 and mem-2 will hold the initial displacements for the first arc, U and V; and mem-3 and mem-4 will hold COS (G/A) and SIN (G/A) for use in the arc-drawing loop.
The formulae for U and V can be explained as follows. Instead of stepping along the final chord, of length L, say, with displacements X and Y, we want to step along an initial chord (which may be longer) of length L*W, where W=SIN (G/2*A)/SIN (G/2), with displacements X*W and Y*W, but turned through an angle (G/2-G/2*A), hence with true displacements:
  • U=Y*W*SIN (G/2-G/2*A)+X*W*COS (G/2-G/2*A)
  • Y=Y*W*COS (G/2-G/2*A)-X*W*SIN (G/2-G/2*A)
These formulae can be checked from a diagram, using the normal expansion of COS (P-Q) and SIN (P-Q), where Q=G/2-G/2*A.
09156 PUSH BC Save the arc-counter in B.
09157 RST 40 X, Y, SIN(G/2), Z
09158 DEFB 2 delete: X, Y, SIN(G/2)
09159 DEFB 225 get_mem_1: X, Y, SIN(G/2), SIN(G/2*A)
09160 DEFB 1 exchange: X, Y, SIN(G/2*A), SIN(G/2)
09161 DEFB 5 division: X, Y, SIN(G/2*A)/SIN(G/2)=W
09162 DEFB 193 st_mem_1: (W is copied to mem-1).
09163 DEFB 2 delete: X, Y
09164 DEFB 1 exchange: Y, X
09165 DEFB 49 duplicate: Y, X, X
09166 DEFB 225 get_mem_1: Y, X, X, W
09167 DEFB 4 multiply: Y, X, X*W
09168 DEFB 194 st_mem_2: (X*W is copied to mem-2).
09169 DEFB 2 delete: Y, X
09170 DEFB 1 exchange: X, Y
09171 DEFB 49 duplicate: X, Y, Y
09172 DEFB 225 get_mem_1: X, Y, Y, W
09173 DEFB 4 multiply: X, Y, Y*W
09174 DEFB 226 get_mem_2: X, Y, Y*W, X*W
09175 DEFB 229 get_mem_5: X, Y, Y*W, X*W,G
09176 DEFB 224 get_mem_0: X, Y, Y*W, X*W, G, G/A
09177 DEFB 3 subtract: X, Y, Y*W, X*W, G-G/A
09178 DEFB 162 stk_half: X, Y, Y*W, X*W, G-G/A, 1/2
09179 DEFB 4 multiply: X, Y, Y*W, X*W, G/2-G/2*A=F
09180 DEFB 49 duplicate: X, Y, Y*W, X*W, F, F
09181 DEFB 31 sin: X, Y, Y*W, X*W, F, SIN F
09182 DEFB 197 st_mem_5: (SIN F is copied to mem-5).
09183 DEFB 2 delete: X, Y, Y*W, X*W,F
09184 DEFB 32 cos: X, Y, Y*W, X*W, COS F
09185 DEFB 192 st_mem_0: (COS F is copied to mem-0).
09186 DEFB 2 delete: X, Y, Y*W, X*W
09187 DEFB 194 st_mem_2: (X*W is copied to mem-2).
09188 DEFB 2 delete: X, Y, Y*W
09189 DEFB 193 st_mem_1: (Y*W is copied to mem-1).
09190 DEFB 229 get_mem_5: X, Y, Y*W, SIN F
09191 DEFB 4 multiply: X, Y, Y*W*SIN F
09192 DEFB 224 get_mem_0: X, Y, Y*W*SIN F, X*W
09193 DEFB 226 get_mem_2: X, Y, Y*W*SIN F, X*W, COS F
09194 DEFB 4 multiply: X, Y, Y*W*SIN F, X*W*COS F
09195 DEFB 15 addition: X, Y, Y*W*SIN F+X*W*COS F=U
09196 DEFB 225 get_mem_1: X, Y, U, Y*W
09197 DEFB 1 exchange: X, Y, Y*W, U
09198 DEFB 193 st_mem_1: (U is copied to mem-1)
09199 DEFB 2 delete: X, Y, Y*W
09200 DEFB 224 get_mem_0: X, Y, Y*W, COS F
09201 DEFB 4 multiply: X, Y, Y*W*COS F
09202 DEFB 226 get_mem_2: X, Y, Y*W*COS F, X*W
09203 DEFB 229 get_mem_5: X, Y, Y*W*COS F, X*W, SIN F
09204 DEFB 4 multiply: X, Y, Y*W*COS F, X*W*SIN F
09205 DEFB 3 subtract: X, Y, Y*W*COS F-X*W*SIN F=V
09206 DEFB 194 st_mem_2: (V is copied to mem-2).
09207 DEFB 42 abs: X, Y, V' (V'=ABS V)
09208 DEFB 225 get_mem_1: X, Y, V', U
09209 DEFB 42 abs: X, Y, V', U' (U'=ABS U)
09210 DEFB 15 addition: X, Y, U'+V'
09211 DEFB 2 delete: X, Y
09212 DEFB 56 end_calc: (DE now points to U'+V').
09213 LD A,(DE) Get exponent of U'+V'.
09214 CP 129 If U'+V' is less than 1, just tidy the stack and draw the line from X0, Y0 to X0+X, Y0+Y.
09216 POP BC
09217 JP C,LINE_DRAW
09220 PUSH BC Otherwise, continue with the parameters: X, Y, on the stack.
09221 RST 40
09222 DEFB 1 exchange: Y, X
09223 DEFB 56 end_calc
09224 LD A,(23677) Get X0 from COORDS into A and so on to the stack.
09227 CALL STACK_A
09230 RST 40 Y, X, X0
09231 DEFB 192 st_mem_0: (X0 is copied to mem-0).
09232 DEFB 15 addition: Y, X0+X
09233 DEFB 1 exchange: X0+X, Y
09234 DEFB 56 end_calc
09235 LD A,(23678) Get Y0 from COORDS into A and so on to the stack.
09238 CALL STACK_A
09241 RST 40 X0+X, Y, Y0
09242 DEFB 197 st_mem_5: (Y0 is copied to mem-5).
09243 DEFB 15 addition: X0+X, Y0+Y
09244 DEFB 224 get_mem_0: X0+X, Y0+Y, X0
09245 DEFB 229 get_mem_5: X0+X, Y0+Y, X0, Y0
09246 DEFB 56 end_calc
09247 POP BC Restore the arc-counter in B.
This entry point is used by the routine at CIRCLE.
iv. The arc-drawing loop. This is entered at ARC_START with the co-ordinates of the starting point on top of the stack, and the initial displacements for the first arc in mem-1 and mem-2. It uses simple trigonometry to ensure that all subsequent arcs will be drawn to points that lie on the same circle as the first two, subtending the same angle at the centre. It can be shown that if 2 points X1, Y1 and X2, Y2 lie on a circle and subtend an angle N at the centre, which is also the origin of co-ordinates, then X2=X1*COS N-Y1*SIN N, and Y2=X1*SIN N+Y1*COS N. But because the origin is here at the increments, say Un=Xn+1-Xn and Vn=Yn+1-Yn, thus achieving the desired result. The stack is shown below on the (n+1)th pass through the loop, as Xn and Yn are incremented by Un and Vn, after these are obtained from Un-1 and Vn-1. The 4 values on the top of the stack at ARC_LOOP are, in DRAW, reading upwards, X0+X, Y0+Y, Xn and Yn but to save space these are not shown until ARC_START. For the initial values in CIRCLE, see the end of CIRCLE, above. In CIRCLE too, the angle G must be taken to be 2π.
DRW_STEPS 09248 DEC B B counts the passes through the loop.
09249 JR Z,ARC_END Jump when B has reached zero.
09251 JR ARC_START Jump into the loop to start.
ARC_LOOP 09253 RST 40 (See text above for the stack).
09254 DEFB 225 get_mem_1: Un-1
09255 DEFB 49 duplicate: Un-1, Un-1
09256 DEFB 227 get_mem_3: Un-1, Un-1, COS(G/A)
09257 DEFB 4 multiply: Un-1, Un-1*COS(G/A)
09258 DEFB 226 get_mem_2: Un-1, Un-1*COS(G/A), Vn-1
09259 DEFB 228 get_mem_4: Un-1, Un-1*COS(G/A), Vn-1, SIN(G/A)
09260 DEFB 4 multiply: Un-1, Un-1*COS(G/A), Vn-1*SIN(G/A)
09261 DEFB 3 subtract: Un-1, Un-1*COS(G/A)-Vn-1*SIN(G/A)=Un
09262 DEFB 193 st_mem_1: (Un is copied to mem-1).
09263 DEFB 2 delete: Un-1
09264 DEFB 228 get_mem_4: Un-1, SIN(G/A)
09265 DEFB 4 multiply: Un-1*SIN(G/A)
09266 DEFB 226 get_mem_2: Un-1*SIN(G/A), Vn-1
09267 DEFB 227 get_mem_3: Un-1*SIN(G/A), Vn-1, COS(G/A)
09268 DEFB 4 multiply: Un-1*SIN(G/A), Vn-1*COS(G/A)
09269 DEFB 15 addition: Un-1*SIN(G/A)+Vn-1*COS(G/A)=Vn
09270 DEFB 194 st_mem_2: (Vn is copied to mem-2).
09271 DEFB 2 delete: (As noted in the text, the stack in fact holds X0+X, Y0+Y, Xn and Yn).
09272 DEFB 56 end_calc
ARC_START 09273 PUSH BC Save the arc-counter.
09274 RST 40 X0+X, Y0+y, Xn, Yn
09275 DEFB 192 st_mem_0: (Yn is copied to mem-0).
09276 DEFB 2 delete: X0+X, Y0+Y, Xn
09277 DEFB 225 get_mem_1: X0+X, Y0+Y, Xn, Un
09278 DEFB 15 addition: X0+X, Y0+Y, Xn+Un=Xn+1
09279 DEFB 49 duplicate: X0+X, Y0+Y, Xn+1, Xn+1
09280 DEFB 56 end_calc
09281 LD A,(23677) Next Xn', the approximate value of Xn reached by the line-drawing subroutine is copied from COORDS to A and hence to the stack.
09284 CALL STACK_A
09287 RST 40 X0+X, Y0+Y, Xn+1, Xn'
09288 DEFB 3 subtract: X0+X, Y0+Y, Xn+1, Xn+1, Xn'-Xn'=Un'
09289 DEFB 224 get_mem_0: X0+X, Y0+Y, Xn+1, Un', Yn
09290 DEFB 226 get_mem_2: X0+X, Y0+Y, Xn+1, Un', Yn, Vn
09291 DEFB 15 addition: X0+X, Y0+Y, Xn+1, Un', Yn+Vn=Yn+1
09292 DEFB 192 st_mem_0: (Yn+1 is copied to mem-0).
09293 DEFB 1 exchange: X0+X, Y0+Y, Xn+1, Yn+1, Un'
09294 DEFB 224 get_mem_0: X0+X, Y0+Y, Xn+1, Yn+1, Un', Yn+1
09295 DEFB 56 end_calc
09296 LD A,(23678) Yn', approximate like Xn', is copied from COORDS to A and hence to the stack.
09299 CALL STACK_A
09302 RST 40 X0+X, Y0+Y, Xn+1, Yn+1, Un', Yn+1, Yn'
09303 DEFB 3 subtract: X0+X, Y0+Y, Xn+1, Yn+1, Un', Vn'
09304 DEFB 56 end_calc
09305 CALL DRAW_LINE The next 'arc' is drawn.
09308 POP BC The arc-counter is restored.
09309 DJNZ ARC_LOOP Jump if more arcs to draw.
ARC_END 09311 RST 40
09312 DEFB 2 delete: The co-ordinates of the end of the last arc that was drawn are now deleted from the stack.
09313 DEFB 2
09314 DEFB 1 exchange: Y0+Y, X0+X
09315 DEFB 56 end_calc
09316 LD A,(23677) The X-co-ordinate of the end of the last arc that was drawn, say Xz', is copied from COORDS to the stack.
09319 CALL STACK_A
09322 RST 40
09323 DEFB 3 subtract: Y0+Y, X0+X-Xz'
09324 DEFB 1 exchange: X0+X-Xz', Y0+Y
09325 DEFB 56 end_calc
09326 LD A,(23678) The Y-co-ordinate is obtained from COORDS and stacked.
09329 CALL STACK_A
09332 RST 40 X0+X-Xz', Y0+Y, Yz'
09333 DEFB 3 subtract: X0+X-Xz', Y0+Y-Yz'
09334 DEFB 56 end_calc
LINE_DRAW 09335 CALL DRAW_LINE The final arc is drawn to reach X0+X, Y0+Y (or close the circle).
09338 JP TEMPS Exit, setting temporary colours.
Prev: 08992 Up: Map Next: 09341