Advertisement
AuroraFinn

C code: Bresenham line drawing algorithm, simplified, with screen boundary clipping

Oct 2nd, 2022
1,344
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.14 KB | None | 0 0
  1. #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  2. #define MAX(a,b) (((a) > (b)) ? (a) : (b))
  3. #define SIGN(x)  (((x) < 0) ? -1 : (((x) > 0) ? 1 : 0))
  4. #define ABS(x)   (((x) < 0) ? -(x) : (x))
  5.  
  6. #define DONT_INTERSECT 0
  7. #define DO_INTERSECT   1
  8. #define OUTCODE_INSIDE 0
  9. #define OUTCODE_LEFT   0x1
  10. #define OUTCODE_RIGHT  0x2
  11. #define OUTCODE_TOP    0x4
  12. #define OUTCODE_BOTTOM 0x8
  13.  
  14. void drawRectFill(int x, int y, int w, int h, unsigned char color)
  15. {
  16.     unsigned char far* pix;
  17.  
  18.     if (x < SCREEN_WIDTH && y < SCREEN_HEIGHT)
  19.     {
  20.         if (y < 0)
  21.         {
  22.             h += y;
  23.             y = 0;
  24.         }
  25.         if (h > 0)
  26.         {
  27.             if (x < 0)
  28.             {
  29.                 w += x;
  30.                 x = 0;
  31.             }
  32.             if (w > 0)
  33.             {
  34.                 if (x+w > SCREEN_WIDTH)
  35.                     w = SCREEN_WIDTH - x;
  36.                 if (y+h > SCREEN_HEIGHT)
  37.                     h = SCREEN_HEIGHT - y;
  38.                 pix = off_screen + Y_OFFSET(y) + x;
  39.                 for (; (h--); pix += SCREEN_WIDTH)
  40.                     _fmemset(pix, color, w);
  41.             }
  42.         }
  43.     }
  44. }
  45.  
  46. void setPixel(int x, int y, unsigned char color)
  47. {
  48.     *(off_screen+x + Y_OFFSET(y)) = color;
  49. }
  50.  
  51. unsigned char pointInScreen(int x, int y)
  52. {
  53.     unsigned char outcode = OUTCODE_INSIDE;
  54.  
  55.     if      (x < 0)              outcode |= OUTCODE_LEFT;
  56.     else if (x >= SCREEN_WIDTH)  outcode |= OUTCODE_RIGHT;
  57.     if      (y < 0)              outcode |= OUTCODE_TOP;
  58.     else if (y >= SCREEN_HEIGHT) outcode |= OUTCODE_BOTTOM;
  59.  
  60.     return outcode;
  61. }
  62.  
  63. int clipLineToScreen(struct Vec2* p0, struct Vec2* p1)
  64. {
  65.     int x, y, dx, dy;
  66.     int ax = p0->x;
  67.     int ay = p0->y;
  68.     int bx = p1->x;
  69.     int by = p1->y;
  70.     unsigned char outcode;
  71.     unsigned char outcode0 = pointInScreen(ax, ay);
  72.     unsigned char outcode1 = pointInScreen(bx, by);
  73.  
  74.     while (1)
  75.     {
  76.         if ((outcode0 | outcode1) == OUTCODE_INSIDE)
  77.             return DO_INTERSECT;
  78.         else if ((outcode0 & outcode1) != OUTCODE_INSIDE)
  79.             return DONT_INTERSECT;
  80.         else
  81.         {
  82.             outcode = MAX(outcode0, outcode1);
  83.             dx = bx-ax;
  84.             dy = by-ay;
  85.  
  86.             if (outcode & OUTCODE_LEFT)
  87.             {
  88.                 y = ay + (-ax*dy + dx/2) / dx;
  89.                 x = 0;
  90.             }
  91.             else if (outcode & OUTCODE_RIGHT)
  92.             {
  93.                 y = ay + ((SCREEN_WIDTH-ax)*dy + dx/2) / dx;
  94.                 x = SCREEN_WIDTH-1;
  95.             }
  96.             else if (outcode & OUTCODE_TOP)
  97.             {
  98.                 x = ax + (-ay*dx + dy/2) / dy;
  99.                 y = 0;
  100.             }
  101.             else if (outcode & OUTCODE_BOTTOM)
  102.             {
  103.                 x = ax + ((SCREEN_HEIGHT-ay)*dx + dy/2) / dy;
  104.                 y = SCREEN_HEIGHT-1;
  105.             }
  106.  
  107.             if (outcode == outcode0)
  108.             {
  109.                 p0->x = ax = x;
  110.                 p0->y = ay = y;
  111.                 outcode0 = pointInScreen(ax, ay);
  112.             }
  113.             else
  114.             {
  115.                 p1->x = bx = x;
  116.                 p1->y = by = y;
  117.                 outcode1 = pointInScreen(bx, by);
  118.             }
  119.         }
  120.     }
  121. }
  122.  
  123. void drawLineSlope(int ax, int ay, int bx, int by, unsigned char color)
  124. {
  125.     int i, x, y, px, py;
  126.    
  127.     const int dx = bx - ax;
  128.     const int dy = by - ay;
  129.     const int dx_abs = ABS(dx);
  130.     const int dy_abs = ABS(dy);
  131.     const int x_sign = SIGN(dx);
  132.     const int y_sign = SIGN(dy);
  133.    
  134.     x = dy_abs >> 1;
  135.     y = dx_abs >> 1;
  136.    
  137.     // Starting point
  138.     px = ax;
  139.     py = ay;
  140.  
  141.     if (dx_abs > dy_abs)
  142.     {
  143.         for (i = 0; i <= dx_abs; i++)
  144.         {
  145.             setPixel(px, py, color);
  146.             y += dy_abs;
  147.             if (y >= dx_abs)
  148.             {
  149.                 y -= dx_abs;
  150.                 py += y_sign;
  151.             }
  152.             px += x_sign;
  153.         }
  154.     }
  155.     else
  156.     {
  157.         for (i = 0; i <= dy_abs; i++)
  158.         {
  159.             setPixel(px, py, color);
  160.             x += dx_abs;
  161.             if (x >= dy_abs)
  162.             {
  163.                 x -= dy_abs;
  164.                 px += x_sign;
  165.             }
  166.             py += y_sign;
  167.         }
  168.     }
  169. }
  170.  
  171. void drawLine(struct Vec2 p0, struct Vec2 p1, unsigned char color)
  172. {
  173.     if (clipLineToScreen(&p0, &p1) == DO_INTERSECT)
  174.     {
  175.         drawLineSlope(p0.x, p0.y, p1.x, p1.y, color);
  176.     }
  177. }
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement