計算機圖形學——中點畫線演算法
中點畫線法根據直線的斜率(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,+∞)時:
delta1=2*(a+b)
delta2=2*b
當k∈[-1,0)時:
delta1=2*(a-b)
delta2=2*a
當k∈(-∞,-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 }