2025-04-27 07:49:33 -04:00

355 lines
8.1 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.