www.pudn.com > CG2Programs.rar > scanFill.c


/* scanFill, Chapter 3, pp. 122-125 */

/* EXAMPLE STARTS HERE */
#include "device.h"

typedef struct tEdge {
  int yUpper;
  float xIntersect, dxPerScan;
  struct tEdge * next;
} Edge;

/* Inserts edge into list in order of increasing xIntersect field. */
void insertEdge (Edge * list, Edge * edge)
{
  Edge * p, * q = list;

  p = q->next;
  while (p != NULL) {
    if (edge->xIntersect < p->xIntersect)
      p = NULL;
    else {
      q = p;
      p = p->next;
    }
  }
  edge->next = q->next;
  q->next = edge;
}

/* For an index, return y-coordinate of next nonhorizontal line */
int yNext (int k, int cnt, dcPt * pts)
{
  int j;

  if ((k+1) > (cnt-1))
    j = 0;
  else
    j = k + 1;
  while (pts[k].y == pts[j].y)
    if ((j+1) > (cnt-1))
      j = 0;
    else
      j++;
  return (pts[j].y);
}

/* Store lower-y coordinate and inverse slope for each edge.  Adjust
   and store upper-y coordinate for edges that are the lower member
   of a monotically increasing or decreasing pair of edges */
void makeEdgeRec
  (dcPt lower, dcPt upper, int yComp, Edge * edge, Edge * edges[])
{
  edge->dxPerScan =
    (float) (upper.x - lower.x) / (upper.y - lower.y);
  edge->xIntersect = lower.x;
  if (upper.y < yComp)
    edge->yUpper = upper.y - 1;
  else
    edge->yUpper = upper.y;
  insertEdge (edges[lower.y], edge);
}

void buildEdgeList (int cnt, dcPt * pts, Edge * edges[])
{
  Edge * edge;
  dcPt v1, v2;
  int i, yPrev = pts[cnt - 2].y;
  
  v1.x = pts[cnt-1].x; v1.y = pts[cnt-1].y;
  for (i=0; inext;
  while (p) {
    q = p->next;
    insertEdge (active, p);
    p = q;
  }
}

void fillScan (int scan, Edge * active)
{
  Edge * p1, * p2;
  int i;
  
  p1 = active->next;
  while (p1) {
    p2 = p1->next;
    for (i=p1->xIntersect; ixIntersect; i++)
      setPixel ((int) i, scan);
    p1 = p2->next;
  }
}

void deleteAfter (Edge * q)
{
  Edge * p = q->next;

  q->next = p->next;
  free (p);
}

/* Delete completed edges. Update 'xIntersect' field for others */
void updateActiveList (int scan, Edge * active)
{
  Edge * q = active, * p = active->next;

  while (p) 
    if (scan >= p->yUpper) {
      p = p->next;
      deleteAfter (q);
    }
    else {
      p->xIntersect = p->xIntersect + p->dxPerScan;
      q = p;
      p = p->next;
    }
}

void resortActiveList (Edge * active)
{
  Edge * q, * p = active->next;

  active->next = NULL;
  while (p) {
    q = p->next;
    insertEdge (active, p);
    p = q;
  }
}

void scanFill (int cnt, dcPt * pts)
{
  Edge * edges[WINDOW_HEIGHT], * active;
  int i, scan;

  for (i=0; inext = NULL;
  }
  buildEdgeList (cnt, pts, edges);
  active = (Edge *) malloc (sizeof (Edge));
  active->next = NULL;

  for (scan=0; scannext) {
      fillScan (scan, active);
      updateActiveList (scan, active);
      resortActiveList (active);
    }
  }
  /* Free edge records that have been malloc'ed ... */
}
/* EXAMPLE ENDS HERE */


void main (int argc, char ** argv)
{
  /* A bow-tie polygon */
  dcPt pts[] = {
    WINDOW_WIDTH/4, WINDOW_HEIGHT/4,
    3*WINDOW_WIDTH/4, 3*WINDOW_HEIGHT/4,
    3*WINDOW_WIDTH/4, WINDOW_HEIGHT/4,
    WINDOW_WIDTH/4, 3*WINDOW_HEIGHT/4
    };
  
  long windowID = openGraphics (*argv, WINDOW_WIDTH, WINDOW_HEIGHT);
  
  setBackground (WHITE);
  setColor (BLACK);
  scanFill (4, pts);
  sleep (20);
  closeGraphics (windowID);
}