355 lines
8.1 KiB
Plaintext
355 lines
8.1 KiB
Plaintext
Copyright (c) 1994-1999 Microsoft Corporation
|
||
|
||
ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
|
||
º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 + ÄÄÄÄÄij
|
||
À 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.
|