home *** CD-ROM | disk | FTP | other *** search
/ Outlet 51 / outlet-51.mgt / d6 < prev    next >
Text File  |  2021-04-18  |  20KB  |  1 lines

  1.         Nearly all the subroutine is concerned with calculating parameters to draw an arc, first for 247D CD PRMS1 - which      calculates an "arc counter" a and the turning angle for each    "arc" - and then for 2420 DRW STEPS, which actually draws the   "arcs". "Arc" in quotes means a short straight-line             approximation to a small arc.                                           CD PRMS1 requires as parameters only G, the turning     angle, which is given from BASIC, and the approximate diameter  of the circle of which the line to be drawn will form a part.   The true length of this diameter, by fairly simple trigonometry,is                                                                                SQR (X**2 + Y**2)/SIN (G/2)                    using absolute values for X, Y and G. The approximation uses X + Y instead of SQR (X**2 + Y**2), which is rather crude - it is always too big, and can be as much as 1.414d... (root two) timestoo big when X and Y are equal. But it is only used to calculatethe_number_of_"arcs" which will be drawn to approximate to the  curve, and this isn't at all a critical figure. The program     nearly always draws more and shorter "arcs" for a DRAW curve    than for a CIRCLE.                                                      DRW STEPS requires as input parameters                         - the PLOT coordinates X0, Y0 from which drawing is to   start; easy, these are safely in 5C7D COORDS                           - the PLOT coordinates X0 + X, Y0 + Y where it is to end;these are the start coordinates plus the X, Y input from BASIC, which are still on the stack                                           - the x and y displacements to draw the first straight-  line "arc", called U and V in the notes; these will be repeated a times turning through T = G/a each time.                              The only ones which are hard to figure are U and V. The calculation for them is also hard to explain - the notes do     their best, but without a diagram and without proper mathemati- cal typography it was impossible to be really clear. A little   spelling out may help:                                                  The_length of the first of the a steps will be longer   than it would be if you took a steps along the straight line    from start to finish positions. If the length of this straight  line is L, the length of the steps would be L/a, but the length of our circuitous steps comes out as L * W where W is more than 1/a, in fact                                                                   SIN (G/2a)                                                  W = ----------                                                      SIN (G/2)                                                                                                                       SIN (T/2)                                                     = --------- (using T = G/a as above).                             SIN (G/2)                                                The smaller G and T are, the nearer will W be to 1/a andthis length to L/a, but it will always be a little longer - a   straight line is after all the shortest distance between two    points.                                                                 The_direction of the first step will be somewhere to theright of the straight-line direction, assuming that the angle G represents a turn to the left, and vice versa. The angle of thisaiming off comes out as                                                              G/2 - G/2a = G/2 - T/2                             This is a small angle if G and a are small, not many    steps to turn through a small angle, and bigger if they are     bigger, more steps for a bigger angle; as you would expect.             To turn a direction whose coordinates are x, y through  an angle F without any change in the length, the standard       formulas for the new direction P, Q are                                              P = y SIN F + x COS F                                           Q = y COS F - x SIN F                              But of course U and V are reduced in length, compared   with the X and Y of the straight line step L, by the reduction  factor W. Putting XW, YW in the above equations, with G/2 - T/2 for F, you get the equations given in the notes,                         U = YW SIN (G/2 - G/2a) + XW COS (G/2 - G/2a)                   V = YW COS (G/2 - G/2a) - XW SIN (G/2 - G/2a)                  The program uses the calculator:                               - to get W, which is put in mem-1;                              - to get X*W, which goes in mem-2;                              - to get Y*W, which stays on the stack;                         - to get G/2 - T/2, which the notes call F; SIN F goes inmem-5 and COS F in mem-0;                                              - to put X*W in mem-2 again, because 37BF sin overwrote  mem-0 to mem-2, and now Y*W in mem-1;                                  - to calculate U as Y*W SIN F + X*W COS F and put it in  mem-1;                                                                 - to calculate V as Y*W COS F - X*W SIN F and put it in  mem-2.                                                                  Everything needed by DRW STEPS is now in place. If afterall this the first "arc" step comes out at less than one pixel  the subroutine again exits to LINE DRAW to draw a straight line.       Input parameters: 5C7D COORDS holds the last PLOT        position                                                                - HL points to the first byte of the second last value Xon the calculator stack, DE to the last value Y                         - the BASIC pointer in 5C5D CH ADD is on the character  after the Y parameter.                                                 Action: read the character at CH ADD                             - if it is 2C comma jump on to DR 3 PRMS                        - (there is no third operand) call 1BEE CHECK END, whichin syntax checking reports "Nonsense in BASIC" if this isn't theend of a statement or makes a double return to the statement    loop at 1B76 STMT RET if it is                                          - (run time) exit to 2477 LINE DRAW to draw a straight  line.                                                                  _238D_DR_3_PRMS (there is a third parameter): move on theBASIC pointer                                                           - call 1C82 EXPT 1NUM to read the next expression on to the calculator stack; the turning angle G                               - call 1BEE CHECK END; with effect as above                     - (run time; the stack holds, from the top, G, Y, X) usethe calculator to get SIN (G/2)                                         - if it isn't zero jump on to DR SIN NZ; see under 3501 not for the calculator equivalent of JR NZ,DR SIN NZ                    - (SIN G/2 is zero) delete it and exit to 2477 LINE DRAWto draw a straight line.                                               _23A3_DR_SIN_NZ (the stack holds, from the top, SIN G/2, Y and X): calculate the absolute value of                                          (ABS X + ABS Y)/SIN (G/2),                    the very approximate diameter of the circle; called Z in the   notes                                                                   - re-stack Z to ensure it is in full FP form; now the   stack holds Z, SIN G/2, Y, X; the first two are the required    initial parameters for CD PRMS1                                         - if the exponent of Z is 81h or more jump on to DR     PRMS; ie if Z is one or more                                            - (Z less than one) delete Z and SIN G/2 from the stack         - exit to 2477 LINE DRAW to draw a straight line.              _23C1_DR_PRMS: call 247D CD PRMS1; it returns the        calculator stack unchanged, Z, SIN G/2, Y, X, with                     the arc-count a in the B register                               mem-0 = the angle T = G/a through which each "arc" must  turn                                                                   mem-1 = SIN (T/2)                                               mem-3 = COS T                                                   mem-4 = SIN T                                                    - save the arc count on the machine stack                       - use the calculator again to figure the initial        displacements U and V explained above. The steps are                    - (down to st-mem-1) calculate W = SIN (T/2)/SIN (G/2)  and put it in mem-1                                                     - (down to st-mem-2; the stack holds W, Y, X) calculate X * W and put it in mem-2                                               - (down to multiply; the stack holds X * W, X, Y)       calculate Y * W                                                         - (down to st-mem-0; the stack holds Y * W, Y, X)       calculate F = G/2 - T/2, put SIN F in mem-5 and COS F in mem-0          - (down to st-mem-1; the stack holds COS F, X * W, Y *  W, Y, X) put X * W in mem-2 and Y * W in mem-1; this couldn't bedone before because 37BF sin and 37AA cos corrupt mem-0 to mem-2        - (down to st-mem-1; the stack holds Y * W, Y, X)       calculate U, the x displacement for the first "arc":                                U = YW SIN F + XW COS F                      and put it in mem-1                                                    - (down to st-mem-2; the stack holds U, Y * W, Y, X)    calculate V, the y displacement:                                                    V = YW COS F - XW SIN F                      and put it in mem-2                                                    - (to end-calc; the stack holds V, Y, X) calculate ABS U+ ABS V and immediately delete it! This leaves Y, X on the      stack, and ABS U + ABS V in the FP number location pointed to by5C65 STKEND                                                             - if the exponent of ABS U + ABS V is less than 81h exitto 2477 LINE DRAW; draw a straight line, the "arc" length is    less than one                                                           - use the calculator just to exchange X and Y on the    stack                                                                   - call 2D28 STACK A to put the x coordinate from 5C7D   COORDS of the last PLOT/DRAW on the calculator stack; now it    holds X0, X, Y                                                          - use the calculator to put X0 in mem-0                         - find X + X0, the x coordinate of the end of the curve         - call 2D28 STACK A to put Y0 from 5C7D COORDS on to thestack; now the stack holds Y0, Y, X0 + X                                - put it in mem-5                                               - find Y + Y0                                                   - exit from the calculator with Y0, X0, Y0 + Y, X0 + X  on the stack                                                            - recover the arc count.                                       Exit: to 2477 LINE DRAW if a straight line results,      otherwise into 2420 DRW STEPS.                                         Output parameters: for DRW STEPS, B holds the arc count          - HL and DE hold pointers to the second last and last   values on the stack                                                     - the stack holds, from the top, the start coordinates  of the line to be drawn Y0, X0, and its end coordinates Y + Y0, X + X0                                                                  - mem-1 holds U                                                 - mem-2 holds V                                                 - mem-3 still holds COS T from CD PRMS1                         - mem-4 still holds SIN T from CD PRMS1                        for LINE DRAW, 5C7D COORDS holds the coordinates of the  start of the line, the calculator stack holds the DRAW operands Y, X.                                                                  Rems:                                                            22DC PLOT main routine called as subroutine by DRAW                       (actually 24EC D L PLOT in 24B7 DRAW LINE)            2307 STK TO BC used in line drawing subroutine                                 (24B7 DRAW LINE)                                 2320 CIRCLE jumps into (actually 2420 DRW STEPS)                233B C R GRE 1 jumps into (actually 2420 DRW STEPS)             235A C ARC GE1 jumps into (actually 2420 DRW STEPS)             2420 DRW STEPS requires inputs as above                         2439 ARC START uses approximate value found by                  247D CD PRMS1 called by DR PRMS, set initial parameters         24B7 DRAW LINE called by                                                                                                    DRAW LINE subroutine 24B7                                           Draws a straight line on screen, starting at the last   PLOT position, with DRAW coordinates X and Y; either or both maybe negative.                                                            Each one-pixel_step is checked for_range, ie to ensure  that the line hasn't gone off the screen; the check of the y    coordinate is actually done in the 22E5 PLOT SUB subroutine     called from D L PLOT.                                                   The algorithm for plotting these pixels is one of the   most elegant in the Spectrum ROM; it was taken over from the oldZX80, see Appendix on pages 228-9 for BASIC representations.            Two unit steps are computed, a_diagonal_step - one pixelup or down and one left or right - and a_square_step, one pixel vertically or horizontally only. If Y, the vertical displacementin drawing the line, is greater in absolute value than X, the   horizontal one, the square step is made vertical, if X is       greater it is made horizontal. If Y is positive the step or     steps are made to go positive/upwards and if X is positive they are made to go to the positive/right, otherwise downwards and/orto the left.                                                            Each position is now looked at successively to see whichunit step, diagonal or square, will move closer to the end pointof the line, and a pixel is plotted accordingly. The total      number T of steps to be taken is the larger of the absolute     values of X and Y; because both the diagonal and the square stepmove in the "larger" direction. The number D of_diagonal steps  will be the smaller of these absolute values; because only the  diagonal steps move in the "smaller" direction. If T = D all thesteps will be diagonal.                                                 T steps are taken with a "step indicator", adjusted for each step, which signals whether a diagonal or square step is tobe taken. The step indicator:                                          - is set at T/2 initially                                       - is incremented on each step by D                              - if this makes it bigger than T, signals a diagonal     step; if not, a square step                                            - on each_diagonal step is decremented by T.                     After d diagonal and s square steps have been taken the indicator will hold                                                    T/2                        ; initial value                          plus D(d + s)          ; D added on every step                  minus T * d            ; T deducted on diagonal steps           = D(d + s) - T(d - 1/2)                               All these numbers are positive integers.                               If this result is more than T,                                ie if D(d + s) - T(d - 1/2) >= T, then                                             D(d + s) >= T(d + 1/2), so                                      D(d + s) > dT,                          or, dividing both sides by Dd,                                                                                                                               s     T                                                    1 + --- > ---                                                        d     D                                                                                                   But if the step indicator is less than T, a very similarcalculation will show that                                                                                                                                              s      T                               D(d + s) <= dT, or  1 + --- <= ---                                                       d      D                                                                                        T/D represents the slope of the line from its start to  its finish, and each plot must stay as close to this slope as   possible: in the first case we want to reduce s/d, so we        increase d by taking a diagonal step; in the second we want to  increase s/d, so we increase s by taking a square step. QED!            The routine could be called from m/c, but beware! the   registers are switched to alternates on every turn of the step- drawing loop; if there is an odd number of PLOTs they will be   switched on exit.                                                      Input parameters: 5C7D COORDS holds the coordinates X0,  Y0 of the last plot on screen                                           - the DRAW operands X, Y are the last two values on the calculator stack, their first bytes addressed by HL and DE      respectively.                                                          Action: call 2307 STK TO BC, which puts ABS Y (hi) and   ABS X (lo) in BC, and SGN Y (hi) and SGN X (lo) in DE; DE thus  represents a diagonal unit step in the correct directions               - if ABS X is greater than or equal to ABS Y jump on to DL X GE Y                                                               - (ABS Y is greater, so the square step is vertical) putABS X in L; this is the number of diagonal steps                        - stack the diagonal step                                       - put zero in E, making DE a vertical square step in thecorrect direction                                                       - jump on to DL LARGER.                                        _24C4_DL_X_GE_Y (ABS X >= ABS Y; the square step is      horizontal): if X and Y are both zero, return; there is no line         - put ABS Y in L (the number of diagonal steps) and ABS X in B (the number of all steps)                                        - stack the diagonal step; it couldn't have been done   before the jump, because of the RET                                     - put zero in D, making DE a horizontal square step in  the correct direction.                                                 _24CB_DL_LARGER: put B in H; now HL holds the total      number of steps T in H and the number of diagonal steps D in L          - make a byte from B shifted one bit to the right; the  step indicator INT (T/2).                                              _24CE_D_L_LOOP: add D to the step indicator                      - if there is carry jump on to D L DIAG; take a diagonalstep. The apparent complication of the increment producing carryis self-correcting: such an increment is certainly big enough tocall for a diagonal step, and then subtracting T, which is      bigger than D, comes out the same as if there had been no carry         - if the step indicator is now < T jump on to D L HR VT;take a square step.                                                    _24D4_D_L_DIAG: decrement the step indicator by T                - copy the diagonal step on the stack into B'C'                 - jump on to D L STEP with the alternate registers.            _24DB_D_L_HR_VT: save the step indicator as it is                - put the square step in B'C'.