计算机图形学——中点画线算法

  中点画线法根据直线的斜率(k)分为四种情况:[0,1)、[1,+∞)、[-1,0)、(-∞,-1)

  首先输入直线的起点和终点,根据起点终点计算斜率:

    假设两端点为:(x0,y0)、(x1,y1)

    则直线方程为:(y-y1)/(y0-y1) = (x-x1)/(x0-x1)

    转化为一般式:(y0 - y1)x +(x1 - x0)y + x0y1 - x1y0=0,则令a=y0-y1,b=x1-x0,c=x0y1-x1y0

    则直线斜率:k=-a/b

    先只考虑第一种情况(k∈[0,1)):

      当F(xi+1,yi+0.5)>0时,点(xi+1,yi+0.5)在直线上方,点(xi+1,yi)距离直线更近,当F(xi+1,yi+0.5)<0时,点(xi+1,yi+0.5)在直线下方,点(xi+1,yi+1)距离直线更近,则构造判别式d=F(xi+1,yi+0.5),所以:

      当d>=0时,x增加1,y不变,则d1=F(xi+2,yi+0.5)=a(xi+2)+b(yi+0.5)+c=d+a,d的增量为a

      当d<0时,x增加1,y增加1,则d2=F(xi+2,yi+1.5)=a(xi+2)+b(yi+1.5)+c=d+a+b,d的增量为a+b

      d的初始值d0=F(x+1,y+0.5)=a+0.5b,因为使用的只是符号d,而且只有初始值有小数,所以用ad来表示,d0=2d0=2a+b

      则第一种情况的增量为:

        delta1=2*a

        delta2=2*(a+b)

    根据第一种情况,同理可以得出剩下的三种情况的增量:

      当k∈[1,+∞)时:

        以y为增量,判断(yi+1,xi+0.5)在直线的上方还是下方,当d>=0时,x增加1,y增加1,当d<0时,x增加1,y不变,增量为:

        delta1=2*(a+b)

        delta2=2*b

      当k∈[-1,0)时:

        当d>=0时,x增加1,y减少1,当d<0时,x增加1,y不变,增量为:

        delta1=2*(a-b)

        delta2=2*a

      当k∈(-∞,-1)时:

        当d>=0时,y减少1,x不变,当d>0时,x增加1,y减少1,增量为:

        delta1=2*(-b)

        delta2=2*(a-b)

    c#语言的完整画线算法如下:

  1         /// <summary>
  2         /// 中点画线算法
  3         /// </summary>
  4         /// <param name="x0"></param>起始点x坐标
  5         /// <param name="y0"></param>起始点y坐标
  6         /// <param name="x1"></param>终点x坐标
  7         /// <param name="y1"></param>终点y坐标
  8         /// <param name="color"></param>画线的颜色
  9         public void drawline(int x0, int y0, int x1, int y1, Color color)
 10         {
 11             //使用同一个bitmap时才可以获得相应的颜色 
 12             //Bitmap bitmap = new Bitmap(500, 500);
 13             int temp;
 14             //将输入的两个顶点进行排序,可以从x小的一侧进行画线
 15             if (x0 > x1)
 16             {
 17                 temp = x0;
 18                 x0 = x1;
 19                 x1 = temp;
 20                 temp = y0;
 21                 y0 = y1;
 22                 y1 = temp;
 23             }
 24             int x, y;
 25             float k, a, b, d, delta1, delta2;
 26             a = y0 - y1;
 27             b = x1 - x0;
 28             k = -1 * a / b;
 29             d = 2 * a + b;
 30             //k∈[0,+∞)
 31             if (k >= 0)
 32             {
 33                 //k∈[0,1)
 34                 if (k < 1)
 35                 {
 36                     delta1 = 2 * a;
 37                     delta2 = 2 * (a + b);
 38                     x = x0;
 39                     y = y0;
 40                     if (x > 0 && y > 0 && x < 500 && y < 500)
 41                     {
 42                         bitmap.SetPixel(x, y, color);
 43                     }
 44                     while (x < x1)
 45                     {
 46                         //d>=0,选择正右方的像素填充
 47                         if (d >= 0)
 48                         {
 49                             x++;
 50                             d += delta1;
 51                         }
 52                         //d<0,选择右上方的点进行填充
 53                         else
 54                         {
 55                             x++;
 56                             y++;
 57                             d += delta2;
 58                         }
 59                         //在进行对像素点的颜色填充时要先判断x,y的值是否有效
 60                         if (x > 0 && y > 0 && x < 500 && y < 500)
 61                         {
 62                             bitmap.SetPixel(x, y, color);
 63                         }
 64                     }
 65                 }
 66                 //k∈[1,+∞)
 67                 else
 68                 {
 69                     delta1 = 2 * b;
 70                     delta2 = 2 * (a + b);
 71                     x = x0;
 72                     y = y0;
 73                     if (x > 0 && y > 0 && x < 500 && y < 500)
 74                     {
 75                         bitmap.SetPixel(x, y, color);
 76                     }
 77                     while (x < x1)
 78                     {
 79                         //d>=0,选择右上方的像素进行填充
 80                         if (d >= 0)
 81                         {
 82                             x++;
 83                             y++;
 84                             d += delta2;
 85                         }
 86                         //d<0,选择正上方的像素进行填充
 87                         else
 88                         {
 89                             y++;
 90                             d += delta1;
 91                         }
 92                         if (x > 0 && y > 0 && x < 500 && y < 500)
 93                         {
 94                             bitmap.SetPixel(x, y, color);
 95                         }
 96                     }
 97                 }
 98             }
 99             //k属于(-∞,0)
100             else
101             {
102                 //k∈[-1,0)
103                 if (k >= -1)
104                 {
105                     delta1 = 2 * a;
106                     delta2 = 2 * (a - b);
107                     x = x0;
108                     y = y0;
109                     if (x > 0 && y > 0 && x < 500 && y < 500)
110                     {
111                         bitmap.SetPixel(x, y, color);
112                     }
113                     while (x < x1)
114                     {
115                         //d>=0,选择右下方像素进行填充
116                         if (d >= 0)
117                         {
118                             x++;
119                             y--;
120                             d += delta2;
121                         }
122                         //d<0,选择正右方的像素进行填充
123                         else
124                         {
125                             x++;
126                             d += delta1;
127                         }
128                         if (x > 0 && y > 0 && x < 500 && y < 500)
129                         {
130                             bitmap.SetPixel(x, y, color);
131                         }
132                     }
133                 }
134                 //斜率小于-1
135                 else
136                 {
137                     delta1 = 2 * (a - b);
138                     delta2 = 2 * (-b);
139                     x = x0;
140                     y = y0;
141                     if (x > 0 && y > 0 && x < 500 && y < 500)
142                     {
143                         bitmap.SetPixel(x, y, color);
144                     }
145                     while (x < x1)
146                     {
147                         //d>=0,选择正下方的像素进行填充
148                         if (d >= 0)
149                         {
150                             y--;
151                             d += delta2;
152                         }
153                         //d<0,选择右下方的像素进行填充
154                         else
155                         {
156                             x++;
157                             y--;
158                             d += delta1;
159                         }
160                         if (x > 0 && y > 0 && x < 500 && y < 500)
161                         {
162                             bitmap.SetPixel(x, y, color);
163                         }
164                     }
165                 }
166             }
167             //提供显示
168             Graphics g = this.CreateGraphics();
169             g.DrawImage(bitmap, new Rectangle(1, 1, 500, 500));
170         }
View Code

*注:点(x0,y0)与点(x1,y1)的顺序不能反,如果交换顺序的话对应的x,y的加减逻辑会发生变化,在这里(x0,y0)是开始画线的起点,虽然交换二者的顺序不会导致直线方程的改变,但是会导致判别式增量的改变

posted @ 2021-10-20 17:18  GIS开发训练营  阅读(1922)  评论(0编辑  收藏  举报