home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 3 / RISC_DISC_3.iso / resources / etexts / gems / gemsiii / scallops8.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-14  |  8.6 KB  |  236 lines

  1. /*----------------------   main() - test_scallops.c   ------------------------
  2. * This main program tests the scallop (i.e. an envelope of circles) generating
  3. *  function by drawing filled circles with a "fill_circle" function and then
  4. *  using an "erode" function to reduce them to their outlines or scallops.
  5. *  It allocates a small frame buffer and asks the user to choose the number
  6. *  of circles desired, their centers, and their radii.  The circles are drawn
  7. *  and filled in sequence.  A simple "printf" to the standard output displays
  8. *  the upper left corner of the frame buffer.  The "erode" function is then
  9. *  applied to the frame buffer, leaving only the outlines of the filled
  10. *  circles (scallops) with their interiors refilled by an erosion replacement
  11. *  value.  Again the upper left corner of the frame buffer is displayed with
  12. *  the results of the eroding the filled circles to scallops.
  13. * When the erosion replacement value is the same as the background, only the
  14. *  outlines (the value used for circle filling) will be shown.
  15. *
  16. *    Author:        Eric Furman
  17. *            General Dynamics/ Convair Division
  18. *            San Diego, California
  19. */
  20.  
  21. #include <stdio.h>
  22.  
  23. #define  XMIN        0        /* limits of the frame buffer */
  24. #define  XMAX        63
  25. #define  YMIN        0
  26. #define  YMAX        63
  27. #define  STRIDE        64     /* width of frame buffer (XMAX - XMIN + 1) */
  28.  
  29. #define  MIN(j,k)  (j)<(k) ? (j) : (k)
  30. #define  MAX(j,k)  (j)>(k) ? (j) : (k)
  31.  
  32. unsigned char  *Pt_Frame;      /* Global pointer to start of frame buffer */
  33.  
  34.  
  35. main()
  36. {
  37.   int  xc, yc, r, ny, nc, k, j;
  38.   unsigned char  val_fill, val_erode;
  39.   void  fill_circle(), erode();
  40.  
  41.  
  42. /* Values (i.e. VLT index) for filling the circles and erosion replacement. */
  43.   val_fill = 8;
  44.   val_erode = 1;
  45.  
  46. /* Allocate space initialized to zero for the test frame buffer:  */
  47.   ny = YMAX - YMIN + 1;            /* number of rasters */
  48.   Pt_Frame = (unsigned char *)calloc(STRIDE * ny, sizeof(unsigned char));
  49.  
  50. /* Obtain user input and loop through circles filling each one. */
  51.   printf(" Number of circles: ");
  52.   scanf("%d", &nc);                /* try:  3 */
  53.    for(k=0; k<nc; k++) {
  54.     printf(" center (x,y) and radius:  ");
  55.     scanf("%d%d%d", &xc, &yc, &r);       /* try:  5 5 6,  15 12 7,  28 6 5 */
  56.  
  57. /* Check for total clipping before filling circle:  */
  58.      if(xc+r < XMIN || xc-r > XMAX || yc+r < YMIN || yc-r > YMAX) {
  59.       printf("Circle x,y,r:  %d  %d  %d  total clip.\n", xc, yc, r);
  60.      }
  61.      else {
  62.       fill_circle(xc, yc, r, val_fill);
  63.      }
  64.    }            /* end for loop through circles */
  65.  
  66. /* Print the Upper Left corner of the buffer after filling circles:  */
  67.   printf("UL corner of filled buffer.\n");
  68.    for(k=0; k<23; k++) {
  69.     printf("%2d: ",k);
  70.      for(j=0; j<35; j++) {
  71.       printf("%2d", *(Pt_Frame + j + k * STRIDE));
  72.      }
  73.     printf("\n");
  74.    }
  75.  
  76.   erode(val_fill, val_erode);        /* erode the filled circles */
  77.  
  78. /* Print the Upper Left corner of the buffer after eroding filled circles:  */
  79.   printf("UL corner of eroded buffer.\n");
  80.    for(k=0; k<23; k++) {
  81.     printf("%2d: ",k);
  82.      for(j=0; j<35; j++) {
  83.       printf("%2d", *(Pt_Frame + j + k * STRIDE));
  84.      }
  85.     printf("\n");
  86.    }
  87.  
  88.   free((char*) Pt_Frame);        /* free the frame buffer memory */
  89. }
  90. /*---------------------------   fill_circle()   ----------------------------
  91. * A midpoint circle generating/filling algorithm using second order partial
  92. *   differences to compute cartesian increments.  Given a circles center
  93. *   point (xc,yc), its radius (r), and a fill value (value);  this will
  94. *   draw the filled circle.
  95. */
  96.  
  97. void fill_circle(xc, yc, r, value)
  98.   int  xc, yc, r;                /* center & radius */
  99.   unsigned char  value;                /* filling value */
  100. {
  101.   int x, y, d, de, dse ;
  102.   void  raster_fill();
  103.  
  104.   x = 0;
  105.   y = r;            /* initialization */
  106.   d = 1 - r;
  107.   de = 3;
  108.   dse = -2 * r + 5;
  109.    while(y >= x)  {    /* thru 2nd octant, others handled in raster_fill() */
  110.      if(d < 0) {        /* only move +x in octant 2 */
  111.       d += de;
  112.       dse += 2;
  113.       raster_fill(xc, yc, y, x, value);     /* rasters in octants 1-4 & 5-8 */
  114.      }
  115.      else {            /* move +x and -y in octant 2 */
  116.       d += dse;
  117.       dse += 4;
  118.       raster_fill(xc, yc, y, x, value);     /* rasters in octants 1-4 & 5-8 */
  119.       raster_fill(xc, yc, x, y, value);     /* rasters in octants 2-3 & 6-7 */
  120.       y --;
  121.      }
  122.     de += 2;
  123.     x++;
  124.    }                    /* end while(y >= x) */
  125. }
  126. /*------------------------   raster_fill()   ---------------------------------
  127. * Rasters filling for octants 2 to 3 and 6 to 7.  x and y will be reversed in
  128. *   the calling sequence for octants 1 to 4 and 5 to 8.
  129. * Requires the global pointer to a frame buffer (Pt_Frame), the defined
  130. *   parameters for the frame extents (XMIN, XMAX, YMIN, YMAX), and the defined
  131. *   parameter for the frame width (STRIDE).
  132. * Called by the fill_circle function.    
  133. */
  134.  
  135. void raster_fill(xc, yc, x, y, value)
  136.   int  xc, yc, x, y;
  137.   unsigned char  value;
  138. {
  139.   int  xl, xr, yt, yb;
  140.   register int  k;
  141.   register unsigned char  *ptb;
  142.  
  143.   xr = MAX(xc + x, XMIN);             /* raster(s) x limits */
  144.   xl = MIN(xc - x, XMAX);
  145.  
  146. /* if raster segment on frame in x, get y values of top and bottom raster */
  147.    if(xr >= xl) {
  148.     yt = yc + y;
  149.     yb = yc - y;
  150.  
  151. /* if raster segment on frame in y, point to its start and fill segment */
  152.      if(yt <= YMAX && yt >= YMIN) {
  153.       ptb = Pt_Frame + yt * STRIDE + xl;
  154.        for(k=xl; k<=xr; k++)  *ptb++ = value;
  155.      }
  156.      if(yb != yt && yb <= YMAX && yb >= YMIN) { /* if on & not same raster */
  157.       ptb = Pt_Frame + yb * STRIDE + xl;
  158.        for(k=xl; k<=xr; k++)  *ptb++ = value;
  159.      }
  160.    }                /* end of if(xr >= xl) */
  161. }
  162. /*--------------------------   erode()   ------------------------------------
  163. * Erode the filled circles to their envelope (scallops) only.  Erases existing
  164. *   val_filled pixels to val_erode when all 4 nearest neighbor pixels are also 
  165. *   set to val_filled.
  166. * Requires the value used to fill the circles (val_filled) and a value to
  167. *   which their interiors will be eroded (val_erode).
  168. * Also requires the global pointer to a frame buffer (Pt_Frame), the defined
  169. *   parameters for the frame extents (XMIN, XMAX, YMIN, YMAX), and the defined
  170. *   parameter for the frame width (STRIDE).
  171. */
  172.  
  173. void erode(val_filled, val_erode)
  174.   unsigned char  val_filled, val_erode;    /* filled and erode to values */
  175. {
  176.   int  k, j;
  177.   unsigned char  *buf0, *buf1, *buf2, *b0, *b1, *b2;
  178.   int  n;
  179.   unsigned char  val4, *ptl, *ptr, *ptb, *ptt, *ptc, *ptf;
  180.  
  181.   val4 = val_filled * 4;        /* for nearest neighbor sum test below */
  182.  
  183. /* Allocate space for working raster buffers were erosion test/evaluation will
  184. *  be performed.  These include a one pixel border beyond the frame buffer. */
  185.   buf0 = b0 = (unsigned char*)malloc((STRIDE+2) * sizeof(unsigned char));
  186.   buf1 = b1 = (unsigned char*)malloc((STRIDE+2) * sizeof(unsigned char));
  187.   buf2 = b2 = (unsigned char*)malloc((STRIDE+2) * sizeof(unsigned char));
  188.   ptt = buf0;
  189.   ptc = buf1;            /* set center, top, and bottom buffer pointers */
  190.   ptb = buf2;
  191.  
  192. /* Initial buffer values to drawing value for one pixel border at top: */
  193.    for(k=0; k<STRIDE+2; k++)  *ptt++ = *ptc++ = *ptb++ = val_filled;
  194.  
  195. /* Initialize first working raster buffer from the Frame buffer */
  196.   ptf = Pt_Frame;
  197.   ptb = buf2 + 1;
  198.    for(k=0; k<STRIDE; k++)  *ptb++ = *ptf++;
  199.  
  200. /* Working through the Frame buffer raster by raster with line counter n:  */
  201.    for(k=YMIN, n=0; k<=YMAX; k++, n++) {
  202.     ptf = buf0;
  203.     buf0 = buf1;
  204.     buf1 = buf2;        /* roll pointers for circular buffering */
  205.     buf2 = ptf;
  206.     ptb = buf2 + 1;                /* "new" buffer line to fill */
  207.      if(k == YMAX) {             /* if below frame, use filled values */
  208.       for(j=0; j<STRIDE+2; j++)  *ptb++ = val_filled;
  209.      }
  210.      else {             /* else on frame buffer, so load from frame */
  211.       ptf = Pt_Frame + (n+1) * STRIDE;
  212.       for(j=0; j<STRIDE; j++)  *ptb++ = *ptf++;      /* add next raster */
  213.      }
  214.  
  215. /* Doing erosion by moving across the three raster buffers by pointers to
  216. * the nearest four neighbors, the center pixel, and the output raster:  */
  217.     ptl = buf1;                    /* left of test point */
  218.     ptr = buf1 + 2;                /* right */
  219.     ptt = buf0 + 1;                /* top */
  220.     ptb = buf2 + 1;                /* bottom */
  221.     ptc = buf1 + 1;                /* center */
  222.     ptf = Pt_Frame + n * STRIDE;        /* output */
  223.      for(j=0; j<STRIDE; j++)  {        /* across buffers pixel by pixel */
  224.        if(*ptc++ == val_filled) {        /* is center pixel value filled */
  225.          if((*ptl + *ptr + *ptt + *ptb) == val4)  *ptf = val_erode;
  226.        }
  227.       ptl++;  ptr++;   ptt++;   ptb++;   ptf++;     /* increment pointers */
  228.      }                   /* end for j loop across raster buffers */
  229.    }                /* end for k loop thru frame buffer rasters */
  230.  
  231.   free((char*)b0);
  232.   free((char*)b1);
  233.   free((char*)b2);
  234. }
  235. /*------------------------------------------------------------------------*/
  236.