home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 3 / RISC_DISC_3.iso / resources / etexts / gems / gemsv / ch6_3 / pclipper.c
Encoding:
C/C++ Source or Header  |  1995-03-04  |  5.2 KB  |  143 lines

  1. #define LEFT            1
  2. #define RIGHT           2
  3. #define BOTTOM          4
  4. #define TOP             8
  5.  
  6. #define SWAP(x, y)      { int _t = x; x = y; y = _t; }
  7.  
  8. #define OUTCODE(x, y, outcode, type)                                     \
  9. {                                                                        \
  10.   if (x < xl) outcode = LEFT, type = 1;                                  \
  11.   else if (x > xr) outcode = RIGHT, type = 1;                            \
  12.   else outcode = type = 0;                                               \
  13.   if (y < yb) outcode |= BOTTOM, type++;                                 \
  14.   else if (y > yt) outcode |= TOP, type++;                               \
  15. }
  16.  
  17. #define CLIP(a1, a2, b1, da, da2, db2, as, bs, sa, sb,                   \
  18.              amin, AMIN, amax, AMAX, bmin, BMIN, bmax, BMAX)             \
  19. {                                                                        \
  20.   if (out1) {                                                            \
  21.     if (out1 & AMIN) { ca = db2 * (amin - a1); as = amin; }              \
  22.     else if (out1 & AMAX) { ca = db2 * (a1 - amax); as = amax; }         \
  23.     if (out1 & BMIN) { cb = da2 * (bmin - b1); bs = bmin; }              \
  24.     else if (out1 & BMAX) { cb = da2 * (b1 - bmax); bs = bmax; }         \
  25.     if (type1 == 2)                                                      \
  26.       out1 &= (ca + da < cb + !dir) ? ~(AMIN | AMAX) : ~(BMAX | BMIN);   \
  27.     if (out1 & (AMIN | AMAX)) {                                          \
  28.       cb = (ca + da - !dir) / da2;                                       \
  29.       if (sb >= 0) { if ((bs = b1 + cb) > bmax) return; }                \
  30.       else { if ((bs = b1 - cb) < bmin) return; }                        \
  31.       r += ca - da2 * cb;                                                \
  32.     }                                                                    \
  33.     else {                                                               \
  34.       ca = (cb - da + db2 - dir) / db2;                                  \
  35.       if (sa >= 0) { if ((as = a1 + ca) > amax) return; }                \
  36.       else { if ((as = a1 - ca) < amin) return; }                        \
  37.       r += db2 * ca - cb;                                                \
  38.     }                                                                    \
  39.   }                                                                      \
  40.   else { as = a1; bs = b1; }                                             \
  41.   alt = 0;                                                               \
  42.   if (out2) {                                                            \
  43.     if (type2 == 2) {                                                    \
  44.       ca = db2 * ((out2 & AMIN) ? a1 - amin : amax - a1);                \
  45.       cb = da2 * ((out2 & BMIN) ? b1 - bmin : bmax - b1);                \
  46.       out2 &= (cb + da < ca + dir) ? ~(AMIN | AMAX) : ~(BMIN | BMAX);    \
  47.     }                                                                    \
  48.     if (out2 & (AMIN | AMAX)) n = (out2 & AMIN) ? as - amin : amax - as; \
  49.     else { n = (out2 & BMIN) ? bs - bmin : bmax - bs; alt = 1; }         \
  50.   }                                                                      \
  51.   else n = (a2 >= as) ? a2 - as : as - a2;                               \
  52. }
  53.  
  54.  
  55. void clip(int dir, int x1, int y1, int x2, int y2,
  56.           int xl, int yb, int xr, int yt)
  57. /*
  58.  *      If dir = 0, round towards (x1, y1)
  59.  *      If dir = 1, round towards (x2, y2)
  60.  */
  61. {
  62.   int adx, ady, adx2, ady2, sx, sy;
  63.   int out1, out2, type1, type2;
  64.   int ca, cb, r, diff, xs, ys, n, alt;
  65.  
  66.   OUTCODE(x1, y1, out1, type1);
  67.   OUTCODE(x2, y2, out2, type2);
  68.   if (out1 & out2) return;
  69.   if ((type1 != 0 && type2 == 0) || (type1 == 2 && type2 == 1)){
  70.     SWAP(out1, out2);
  71.     SWAP(type1, type2);
  72.     SWAP(x1, x2);
  73.     SWAP(y1, y2);
  74.     dir ^= 1;
  75.   }
  76.   xs = x1;
  77.   ys = y1;
  78.   sx = 1;
  79.   adx = x2 - x1;
  80.   if (adx < 0) { adx = -adx; sx = -1; }
  81.   sy = 1;
  82.   ady = y2 - y1;
  83.   if (ady < 0) { ady = -ady; sy = -1; }
  84.   adx2 = adx + adx;
  85.   ady2 = ady + ady;
  86.   if (adx >= ady) {
  87. /*
  88.  *      line is semi-horizontal
  89.  */
  90.     r = ady2 - adx - !dir;
  91.     CLIP(x1, x2, y1, adx, adx2, ady2, xs, ys, sx, sy,
  92.          xl, LEFT, xr, RIGHT, yb, BOTTOM, yt, TOP);
  93.     diff = ady2 - adx2;
  94.     if (alt) {
  95.       for (;; xs += sx) {       /* alternate Bresenham */
  96.         plot(xs, ys);
  97.         if (r >= 0 ) {
  98.           if (--n < 0) break;
  99.           r += diff;
  100.           ys += sy;
  101.         }
  102.         else r += ady2;
  103.       }
  104.     }
  105.     else{
  106.       for (;; xs += sx) {       /* standard Bresenham */
  107.         plot(xs, ys);
  108.         if (--n < 0) break;
  109.         if (r >= 0 ) { r += diff; ys += sy; }
  110.         else r += ady2;
  111.       }
  112.     }
  113.   }
  114.   else {
  115. /*
  116.  *      line is semi-vertical
  117.  */
  118.     r = adx2 - ady - !dir;
  119.     CLIP(y1, y2, x1, ady, ady2, adx2, ys, xs, sy, sx,
  120.          yb, BOTTOM, yt, TOP, xl, LEFT, xr, RIGHT);
  121.     diff = adx2 - ady2;
  122.     if (alt) {
  123.       for (;; ys += sy) {       /* alternate Bresenham */
  124.         plot(xs, ys);
  125.         if (r >= 0 ) {
  126.           if (--n < 0) break;
  127.           r += diff;
  128.           xs += sx;
  129.         }
  130.         else r += adx2;
  131.       }
  132.     }
  133.     else {
  134.       for (;; ys += sy) {       /* standard Bresenham */
  135.         plot(xs, ys);
  136.         if (--n < 0) break;
  137.         if (r >= 0 ) { r += diff; xs += sx; }
  138.         else r += adx2;
  139.       }
  140.     }
  141.   }
  142. }
  143.