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


#include 
#include "graphics.h"

#ifndef ROUND
#define ROUND(a) ((int)(a+0.5))
#endif


PhigsState pState = { SOLID, 1, 0, 0, 0, 1, 0, 0, 0, 1 };


/* ============================================================ */
/* Basic graphics primtives */ 
/* ============================================================ */

/* ============================================================
   lineDDA
*/
void lineDDA (int xa, int ya, int xb, int yb)
{
  int dx = xb - xa, dy = yb - ya, steps, k;
  float xIncrement, yIncrement, x = xa, y = ya;

  if (abs (dx) > abs (dy)) 
    steps = abs (dx);
  else 
    steps = abs (dy);
  xIncrement = dx / (float) steps;
  yIncrement = dy / (float) steps;
    
  setPixel (ROUND(x), ROUND(y));
  for (k=0; k 0) {
    y--;
    py -= twoRx2;
    if (p > 0) 
      p += Rx2 - py;
    else {
      x++;
      px += twoRy2;
      p += Rx2 - py + px;
    }
    ellipsePlotPoints (xCenter, yCenter, x, y);
  }
}

void ellipsePlotPoints (int xCenter, int yCenter, int x, int y)
{
   setPixel (xCenter + x, yCenter + y);
   setPixel (xCenter - x, yCenter + y);
   setPixel (xCenter + x, yCenter - y);
   setPixel (xCenter - x, yCenter - y);
}



/* ============================================================
   scanFill
*/
typedef struct tEdge {
  int yUpper;
  float xIntersect;
  float dxPerScan;
  struct tEdge * next;
} Edge;

/* Inserts edge into list in order of increasing xIntersect field. */
void insertEdge (Edge * list, Edge * edge)
{
  Edge * q = list;
  Edge * 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;
}

/* Given an index, return the 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);
}

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;
  int yPrev = pts[cnt - 2].y;
  
  v1.x = pts[cnt-1].x; v1.y = pts[cnt-1].y;
  for (i = 0; i < cnt; i++) {
    v2 = pts[i];
    if (v1.y != v2.y) {  /* a nonhorizontal line */
      edge = (Edge *) malloc (sizeof (Edge));
      if (v1.y < v2.y)
	makeEdgeRec (v1, v2, yNext (i, cnt, pts), edge, edges);
      else
	makeEdgeRec (v2, v1, yPrev, edge, edges);
    }
    yPrev = v1.y;
    v1 = v2;
  }
}

void buildActiveList (int scan, Edge * active, Edge * edges[])
{
  Edge * p, * q;
  p = edges[scan]->next;
  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; i < p2->xIntersect; i++)
      setPixel ((int) i, scan);
    /* Advance to next pair of intersections */
    p1 = p2->next;
  }
}

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

void updateActiveList (int scan, Edge * active)
{
  Edge * p = active->next;
  Edge * q = active;
  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 * p = active->next;
  Edge * q;
  active->next = NULL;
  while (p) {
    q = p->next;
    insertEdge (active, p);
    p = q;
  }
}

void scanFill (int cnt, dcPt * pts)
{
  Edge * edges[WINDOW_HEIGHT];
  Edge * active;
  int i, scan;
  active = (Edge *) malloc (sizeof (Edge));
  for (i = 0; i < WINDOW_HEIGHT; i++) {
    edges[i] = (Edge *) malloc (sizeof (Edge));
    edges[i]->next = NULL;
  }
  active->next = NULL;
  buildEdgeList (cnt, pts, edges);
  for (scan = 0; scan < WINDOW_HEIGHT; scan++) {
    buildActiveList (scan, active, edges);
    if (active->next) {
      fillScan (scan, active);
      updateActiveList (scan, active);
      resortActiveList (active);
    }
  }
}



/* ============================================================ */
/* Data structure convenience functions */
/* ============================================================ */

void setWcPt2 (wcPt2 * pt, float x, float y)
{
  pt->x = x; pt->y = y;
}

void setWcPt3 (wcPt3 * pt, float x, float y, float z)
{
  pt->x = x; pt->y = y; pt->z = z;
}

void wcPt2Show (wcPt2 pt)
{
  printf ("(%6.3f, %6.3f)\n", pt.x, pt.y);
}

void wcPt3Show (wcPt3 pt)
{
  printf ("(%6.3f, %6.3f, %6.3f)\n", pt.x, pt.y, pt.z);
}

void matrix3x3Show (pMatrix3 m)
{
  int i, j;

  printf ("\n");
  for (i=0; i<3; i++) {
    for (j=0; j<3; j++)
      printf ("%6.3f\t", m[i][j]);
    printf ("\n");
  }
}

void matrix4x4Show (pMatrix4 m)
{
  int i, j;

  printf ("\n");
  for (i=0; i<4; i++) {
    for (j=0; j<4; j++)
      printf ("%6.3f\t", m[i][j]);
    printf ("\n");
  }
}



/* ============================================================ */
/* PHIGS-like graphics primitives */ 
/* ============================================================ */

void pPoint (float x, float y)
{
  setPixel (ROUND(x), ROUND(y));
}


void pSetLineType (pLineType typ)
{
  pState.lineType = typ;
}


void pPolyline (int nPts, wcPt2 * pts)
{
  int line;
  int dx, dy, steps, k;
  double xIncrement, yIncrement, x, y;
  int on = 0, off = 0;

  if (pState.lineType == SOLID) {
    /* We'll round the points and rely on the device-level line
       drawing routine. */
    for (line=0; line abs (dy)) 
	steps = abs (dx);
      else
	steps = abs (dy);
      xIncrement = dx / (float) steps;
      yIncrement = dy / (float) steps;
      setPixel ((int) x, (int) y);
      on++;

      switch (pState.lineType) {
      case DASHED: 
	for (k=0; k