计算机图形学——中点画线算法
中点画线法根据直线的斜率(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 }
*注:点(x0,y0)与点(x1,y1)的顺序不能反,如果交换顺序的话对应的x,y的加减逻辑会发生变化,在这里(x0,y0)是开始画线的起点,虽然交换二者的顺序不会导致直线方程的改变,但是会导致判别式增量的改变