ͻ
RUNNING THE WALL OF THE TRAPEZOID
ͼ


This file contains an explanation of how to run the wall of a
trapezoid.  If there are any questions please feel free to ask

    Kirk




INTRODUCTION:

A FIX point number is a 28.4 representation of a real number.  Thus
the real number associated with a FIX point number Q is


                             Q
                        q = 
                             F


The radix shift factor  F is has the form


                        F = 2^L .


In NT Windows the radix shift factor is


                        L = 4


and

                        F = 2^4 = 16 .


The real values of the endpoints of the line are:



                                 M0     N0  
                P0 = (x0,y0) =   ,   ,
                                 F      F   


                                 M1     M1  
                P1 = (x1,y1) =   ,   .
                                 F      F   



The equation of the wall line is


                        (x1 - x0)
                x(y) =   (y - y0)  +   x0 .
                        (y1 - y0)



I can use the FIX point representation of the real coordiantes to
provide an alternative expression of the equation of the wall line.



                        (M1 - M0)       N0        M0
                x(y) =    y -    +   .
                        (N1 - N0)       F          F



At this point I shall introduce some convenient notation.



                DM = M1 - M0        ,


                DN = N1 - N0 > 0    ,


                m0 = floor(x0) = M0 >> L  ,


                n0 = floor(y0) = N0 >> L  ,


                qx = floor(F * frac(x0)) = M0 - (m0 << L) ,

                0 <= qx < F


                qy = floor(F * frac(y0)) = N0 - (n0 << L) ,


                0 <= qx < F


                Rsup = F DN         .



Note that m0, n0, qx, and qy are integers.

This leads to the following form for the equation of the line:



                        DM             qy            qx
                x(y) =   y - n0 -    +  m0 + 
                        DN             F             F



Note that x and y are real numbers while the offsets m0 and n0 are
integers.


According to the filling conventions of Windows, the position of the
wall at y = j is given by:



         i(j) =  ceil ( x(j) )


                        DM             qy           qx 
              =  ceil    j - n0 -    + m0 +  
                        DN             F            F  


                               DM             qy      qx 
              =  m0  +  ceil    j - n0 -    +  
                               DN             F       F  


                               DM [ F(j - n0) - qy ] + DN qx  
              =  m0  +  ceil   
                                             F DN             


                              DM [ F(j - n0) - qy ] + DN (F + qx) - 1 
              =  m0  +  floor  
                                            F DN                      




The quotient and remainder is calculated just once for the initial value
of j = j0.



            DM [ F(j0 - n0) - qy ] + DN (F + qx) - 1        R
             = Q +  ,
                          F DN                             F DN


  where 0 <= R < F DN.

  Ŀ
    CAUTION                                                         
                                                                    
    The programer must be cautions in the case where the numerator  
    is negative.  The C standard does not spcecify how the quotient 
    should be rounded in this case.  Just make sure that you adjust 
    things so that R is positive! See Appendix I.                   
  


Having done the division properly we are left with the answer



                                   R   
         i(j) =  m0  +  floor Q +  
                                  F DN 


                                     R   
              =  m0  +  Q  +  floor  
                                    F DN 



              =  m0  +  Q



Now upon traversal the value of j changes by dj = +1 or -1.  This will
affect the value of i(j) as follows:


           i(j+dj) =


                                 R             dR  
              =  m0 + floor Q +  + di +  ĳ
                                F DN          F DN 


                                      R + dR  
              =  m0 + Q + di + floor  
                                       F DN   


                                    R + dR  
              =  i(j) + di + floor  
                                     F DN   



Where we have introduced di and dR defined as follows:



                                dR      F DM dj
                        di +    =   ,
                               F DN      F DN



where 0 <= dR < F DN . [ Be careful about negative numerators. See Appendix I].

/************************************************************************/

ALGORITHM 0: <initialize: i, di, R, dR>

INPUT:

    (i)     (x0,y0) = (M0/16,N0/16) and (x1,y1) = (M1/16,N1/16) with y1 > y0.

    (ii)    j0 such that y0 <= j0 <= y1.

    (iii)   dj = +1 or -1.

OUTPUT:
    i, di, R, dR, Rsup

{
    DM = M1 - M0;
    DN = N1 - N0;
    m0 = M0 >> 4;           // signed shifts work for all numbers!
    n0 = N0 >> 4;
    qx = M0 - (m0 << 4);    // 0 <= qx < 16
    qy = N0 - (n0 << 4);    // 0 <= qy < 16
    Rsup = DN << 4;

// Find the quotient and remainder 0 <= R < Rsup.
// Be careful about using '/' and '%' they do funny things when
// the numerator is negative

// Calculating i and R



         R     DM*[16*(j0 - n0) - qy] + DN*(16 + qx) - 1
    i +  =  ;
        Rsup                 Rsup

    i += m0;



// Calculating di and dR:

// Similarly, be cautious about the next step. It must satisfy
// 0 <= dR < 16 * DN



           dR        16*DM*dj
    di +   =   ;
          Rsup         Rsup

}

/*********************************************************************/

ALGORITHM 1: <Run the wall of the trapezoid>

INPUT:

    (i)     (x0,y0) = (M0/16,N0/16) and (x1,y1) = (M1/16,N1/16) with y1 > y0.

    (ii)    j0 such that y0 <= j0 <= y1.

    (iii)   dj = +1 or -1.

OUTPUT:

    An array of integers i0, i1, i2, ... that represent the position
    of the trapezoid wall at the rows with y-coordinates:
    j0, j1 = j0 + dj, j2 = j1 + dj, ...

{
    <initialize: i, di, R, dR, Rsup>;
    <process row i>;
    while (<not done>)
    {
        i += di;
        j += dj;
        R += dR;
        if (R >= Rsup)
        {
            R -= Rsup;
            i++;
        }
        <process row i>;
    }
}

**********************************************************************

APPENDIX I

Q: How do I handle those negative numerators anyway?

A: Easy, consider the following division with a negative numerator
   and positive denominator.


                     R          -A
                Q +     =     ,       A>0, B>0
                     B           B

    First we convert the problem to one with positive numerator and
    denominator. Let


                                   A-1
                    Q'  =   floor(  ) ,
                                    B

                    R'  =  A - 1 - Q'B = (A - 1) mod B .


    Then the desired result is ...


                    Q = - (Q'+ 1) ,


                    R = B - R'- 1 .


    It is a useful exercise to prove this result.
