Replace invalid characters with HTML entities

— with —
’ with ’
+ with +
× with x
ç with ç
“ with “
” with ”
‘ with ‘
• with •
– with -
µ with µ
† with †
Fix C++
θ with θ
Yen symbol instead of times
Fix broken apos
Bullet again
E-circumflex
This commit is contained in:
James Gregory 2013-12-30 12:50:32 +11:00
commit 500e7f5654
353 changed files with 5091 additions and 5091 deletions

View file

@ -36,9 +36,9 @@
</TABLE>
</CENTER>
<P><BR></P>
<P>Advancing the X coordinates is easy. For each edge, we&#146;ll store the current X coordinate and all required error term information, and we&#146;ll use that to advance the edge one scan line at a time; then, we&#146;ll resort the AET by X coordinate as needed. Removing edges as they end is also easy; we&#146;ll just count down the length of each active edge on each scan line and remove an edge when its count reaches zero. Adding edges as their tops are encountered is a tad more complex. While there are a number of ways to do this, one particularly efficient approach is to start out by putting all the edges of the polygon, sorted by increasing Y coordinate, into a single list, called the <I>global edge table</I> (GET). Then, as each scan line is encountered, all edges at the start of the GET that begin on the current scan line are moved to the AET; because the GET is Y-sorted, there&#146;s no need to search the entire GET. For still greater efficiency, edges in the GET that share common Y coordinates can be sorted by increasing X coordinate; this ensures that no more than one pass through the AET per scan line is ever needed when adding new edges from the GET in such a way as to keep the AET sorted in ascending X order.</P>
<P>What form should the GET and AET take? Linked lists of edge structures, as shown in Figure 40.3. With linked lists, all that&#146;s required to move edges from the GET to the AET as they become active, sort the AET, and remove edges that have been fully drawn is the exchanging of a few pointers.</P>
<P>In summary, we&#146;ll initially store all the polygon edges in Y-primary/X-secondary sort order in the GET, complete with initial X and Y coordinates, error terms and error term adjustments, lengths, and directions of X movement for each edge. Once the GET is built, we&#146;ll do the following:</P>
<P>Advancing the X coordinates is easy. For each edge, we&rsquo;ll store the current X coordinate and all required error term information, and we&rsquo;ll use that to advance the edge one scan line at a time; then, we&rsquo;ll resort the AET by X coordinate as needed. Removing edges as they end is also easy; we&rsquo;ll just count down the length of each active edge on each scan line and remove an edge when its count reaches zero. Adding edges as their tops are encountered is a tad more complex. While there are a number of ways to do this, one particularly efficient approach is to start out by putting all the edges of the polygon, sorted by increasing Y coordinate, into a single list, called the <I>global edge table</I> (GET). Then, as each scan line is encountered, all edges at the start of the GET that begin on the current scan line are moved to the AET; because the GET is Y-sorted, there&rsquo;s no need to search the entire GET. For still greater efficiency, edges in the GET that share common Y coordinates can be sorted by increasing X coordinate; this ensures that no more than one pass through the AET per scan line is ever needed when adding new edges from the GET in such a way as to keep the AET sorted in ascending X order.</P>
<P>What form should the GET and AET take? Linked lists of edge structures, as shown in Figure 40.3. With linked lists, all that&rsquo;s required to move edges from the GET to the AET as they become active, sort the AET, and remove edges that have been fully drawn is the exchanging of a few pointers.</P>
<P>In summary, we&rsquo;ll initially store all the polygon edges in Y-primary/X-secondary sort order in the GET, complete with initial X and Y coordinates, error terms and error term adjustments, lengths, and directions of X movement for each edge. Once the GET is built, we&rsquo;ll do the following:</P>
<DL>
<DD><B>1.</B>&nbsp;&nbsp;Set the current Y coordinate to the Y coordinate of the first edge in the GET.
<DD><B>2.</B>&nbsp;&nbsp;Move all edges with the current Y coordinate from the GET to the AET, removing them from the GET and maintaining the X-sorted order of the AET.
@ -46,12 +46,12 @@
<DD><B>4.</B>&nbsp;&nbsp;Count down the lengths of all edges in the AET, removing any edges that are done, and advancing the X coordinates of all remaining edges in the AET by one scan line.
<DD><B>5.</B>&nbsp;&nbsp;Sort the AET in order of ascending X coordinate.
<DD><B>6.</B>&nbsp;&nbsp;Advance the current Y coordinate by one scan line.
<DD><B>7.</B>&nbsp;&nbsp;If either the AET or GET isn&#146;t empty, go to step 2.
<DD><B>7.</B>&nbsp;&nbsp;If either the AET or GET isn&rsquo;t empty, go to step 2.
</DL>
<P><A NAME="Fig3"><!-- </A><A HREF="javascript:displayWindow('images/40-03.jpg',407,199 )"> --><IMG SRC="images/40-03.jpg"><BR><!-- </A>
<BR><A HREF="javascript:displayWindow('images/40-03.jpg',407,199)"> --><FONT COLOR="#000077"><B>Figure 40.3</B></FONT></A>&nbsp;&nbsp;<I>The global and active edge tables as linked lists.</I>
</P>
<P>That&#146;s really all there is to it. Compare Listing 40.1 to the fast convex polygon filling code from Chapter 39, and you&#146;ll see that, contrary to expectation, complex polygon filling is indeed one of the more sane and sensible corners of the universe.
<P>That&rsquo;s really all there is to it. Compare Listing 40.1 to the fast convex polygon filling code from Chapter 39, and you&rsquo;ll see that, contrary to expectation, complex polygon filling is indeed one of the more sane and sensible corners of the universe.
</P>
<P><B>LISTING 40.1 L40-1.C</B></P>
<!-- CODE //-->
@ -60,12 +60,12 @@
If the first and last points in VertexList are not the same, the path
around the polygon is automatically closed. All vertices are offset
by (XOffset, YOffset). Returns 1 for success, 0 if memory allocation
failed. All C code tested with Borland C&#43;&#43;.
failed. All C code tested with Borland C++.
If the polygon shape is known in advance, speedier processing may be
enabled by specifying the shape as follows: &#147;convex&#148; - a rubber band
enabled by specifying the shape as follows: &ldquo;convex&rdquo; - a rubber band
stretched around the polygon would touch every vertex in order;
&#147;nonconvex&#148; - the polygon is not self-intersecting, but need not be
convex; &#147;complex&#148; - the polygon may be self-intersecting, or, indeed,
&ldquo;nonconvex&rdquo; - the polygon is not self-intersecting, but need not be
convex; &ldquo;complex&rdquo; - the polygon may be self-intersecting, or, indeed,
any sort of polygon at all. Complex will work for all polygons; convex
is fastest. Undefined results will occur if convex is specified for a
nonconvex or complex polygon.
@ -82,7 +82,7 @@
#else /* MSC */
#include &lt;malloc.h&gt;
#endif
#include &#147;polygon.h&#148;
#include &ldquo;polygon.h&rdquo;
#define SWAP(a,b) {temp = a; a = b; b = temp;}
@ -129,7 +129,7 @@
if ((EdgeTableBuffer =
(struct EdgeState *) (malloc(sizeof(struct EdgeState) *
VertexList-&gt;Length))) == NULL)
return(0); /* couldn&#146;&#146;t get memory for the edge table */
return(0); /* couldn&rsquo;&rsquo;t get memory for the edge table */
/* Build the global edge table */
BuildGET(VertexList, EdgeTableBuffer, XOffset, YOffset);
/* Scan down through the polygon edges, one scan line at a time,
@ -141,9 +141,9 @@
ScanOutAET(CurrentY, Color); /* draw this scan line from AET */
AdvanceAET(); /* advance AET edges 1 scan line */
XSortAET(); /* resort on X */
CurrentY&#43;&#43;; /* advance to the next scan line */
CurrentY++; /* advance to the next scan line */
}
/* Release the memory we&#146;ve allocated and we&#146;re done */
/* Release the memory we&rsquo;ve allocated and we&rsquo;re done */
free(EdgeTableBuffer);
return(1);
}
@ -165,29 +165,29 @@
the GET, sorted by increasing Y start coordinate */
VertexPtr = VertexList-&gt;PointPtr; /* point to the vertex list */
GETPtr = NULL; /* initialize the global edge table to empty */
for (i = 0; i &lt; VertexList-&gt;Length; i&#43;&#43;) {
for (i = 0; i &lt; VertexList-&gt;Length; i++) {
/* Calculate the edge height and width */
StartX = VertexPtr[i].X &#43; XOffset;
StartY = VertexPtr[i].Y &#43; YOffset;
StartX = VertexPtr[i].X + XOffset;
StartY = VertexPtr[i].Y + YOffset;
/* The edge runs from the current point to the previous one */
if (i == 0) {
/* Wrap back around to the end of the list */
EndX = VertexPtr[VertexList-&gt;Length-1].X &#43; XOffset;
EndY = VertexPtr[VertexList-&gt;Length-1].Y &#43; YOffset;
EndX = VertexPtr[VertexList-&gt;Length-1].X + XOffset;
EndY = VertexPtr[VertexList-&gt;Length-1].Y + YOffset;
} else {
EndX = VertexPtr[i-1].X &#43; XOffset;
EndY = VertexPtr[i-1].Y &#43; YOffset;
EndX = VertexPtr[i-1].X + XOffset;
EndY = VertexPtr[i-1].Y + YOffset;
}
/* Make sure the edge runs top to bottom */
if (StartY &gt; EndY) {
SWAP(StartX, EndX);
SWAP(StartY, EndY);
}
/* Skip if this can&#146;t ever be an active edge (has 0 height) */
/* Skip if this can&rsquo;t ever be an active edge (has 0 height) */
if ((DeltaY = EndY - StartY) != 0) {
/* Allocate space for this edge&#146;s info, and fill in the
/* Allocate space for this edge&rsquo;s info, and fill in the
structure */
NewEdgePtr = NextFreeEdgeStruc&#43;&#43;;
NewEdgePtr = NextFreeEdgeStruc++;
NewEdgePtr-&gt;XDirection = /* direction in which X moves */
((DeltaX = EndX - StartX) &gt; 0) ? 1 : -1;
Width = abs(DeltaX);
@ -198,7 +198,7 @@
if (DeltaX &gt;= 0) /* initial error term going L-&gt;R */
NewEdgePtr-&gt;ErrorTerm = 0;
else /* initial error term going R-&gt;L */
NewEdgePtr-&gt;ErrorTerm = -DeltaY &#43; 1;
NewEdgePtr-&gt;ErrorTerm = -DeltaY + 1;
if (DeltaY &gt;= Width) { /* Y-major edge */
NewEdgePtr-&gt;WholePixelXMove = 0;
NewEdgePtr-&gt;ErrorTermAdjUp = Width;
@ -269,12 +269,12 @@
/* This edge is finished, so remove it from the AET */
*CurrentEdgePtr = CurrentEdge-&gt;NextEdge;
} else {
/* Advance the edge&#146;s X coordinate by minimum move */
CurrentEdge-&gt;X &#43;= CurrentEdge-&gt;WholePixelXMove;
/* Determine whether it&#146;s time for X to advance one extra */
if ((CurrentEdge-&gt;ErrorTerm &#43;=
/* Advance the edge&rsquo;s X coordinate by minimum move */
CurrentEdge-&gt;X += CurrentEdge-&gt;WholePixelXMove;
/* Determine whether it&rsquo;s time for X to advance one extra */
if ((CurrentEdge-&gt;ErrorTerm +=
CurrentEdge-&gt;ErrorTermAdjUp) &gt; 0) {
CurrentEdge-&gt;X &#43;= CurrentEdge-&gt;XDirection;
CurrentEdge-&gt;X += CurrentEdge-&gt;XDirection;
CurrentEdge-&gt;ErrorTerm -= CurrentEdge-&gt;ErrorTermAdjDown;
}
CurrentEdgePtr = &CurrentEdge-&gt;NextEdge;
@ -289,7 +289,7 @@
int CurrentX;
/* The GET is Y sorted. Any edges that start at the desired Y
coordinate will be first in the GET, so we&#146;ll move edges from
coordinate will be first in the GET, so we&rsquo;ll move edges from
the GET to AET until the first edge left in the GET is no longer
at the desired Y coordinate. Also, the GET is X sorted within
each Y coordinate, so each successive edge we add to the AET is