計算機圖形學之畫線(DDA、Bresenham、中點畫線) 針對各種斜率
阿新 • • 發佈:2018-12-21
為什麼寫這篇文章?
博主開始也是到處參考研究了很多程式碼,發現要考慮任意斜率的話,很多程式碼都是用if語句來分別討論的,其實其中有很多重複的程式碼部分,我覺得不程式碼不簡潔,就到處查詢參考思考才總結出一些比較簡潔的程式碼,希望大家喜歡,也期待大家有更好的方法分享。
其中的程式碼我是用JavaScript寫的,但其中原理是相通的,基本改改語法就都能用。
進入正文:
- 數值微分法DDA: 其中看x的斜率來確定增加的方向,DrawPixel(x,y,color)為畫點個人函式。
function DDA(x0, y0, x1, y1, color) { var dx, dy, m, k; var incX, incY, x, y; dx = x1 - x0; dy = y1 - y0; //正則表示式:其中?前條件為true則m=Math.abs(dx) ,反之m=Math.abs(dy) m = (Math.abs(dx) > Math.abs(dy)) ? Math.abs(dx) : Math.abs(dy);//Math.abs取絕對值 incX = dx / m; incY = dy / m; x = x0; y = y0; for (k = 1; k < m; k++) { x += incX; y += incY; DrawPixel(Math.floor(x + 0.5), Math.floor(y + 0.5), color);//Math.floor向下取整 } }
- Bresenham畫線演算法:以dx來決定每次增加還是減少,這樣就把k<0的情況考慮進去,當 |k|>1時,就交換兩點的XY座標,再進行繪製,需要注意的是呼叫繪製點的函式時,要記得同時調換XY座標。
function Bresenham(x0, y0, x1, y1, color) { var x, y, dx, dy, e, m; dx = x1 - x0; dy = y1 - y0; var flag = Math.abs(dx) - Math.abs(dy);//判斷斜率是否大於1 if (flag < 0) {//斜率大於1則交換XY座標 m = y0; y0 = x0; x0 = m; m = y1; y1 = x1; x1 = m; } dx = x1 - x0; dy = y1 - y0; e = 2 * Math.abs(dy) - Math.abs(dx); x = x0; y = y0; incX = (dx > 0) ? 1 : -1; //每次增加步長,避免<0的情況 incY = dy / Math.abs(dy);//同上的另一種表達方式 for (var i = 0; i < (Math.abs(dx)-1) ; i++) { x += incX; if (e < 0) e += 2 * Math.abs(dy); else { y += incY; e = e + 2 * (Math.abs(dy) - Math.abs(dx)); } if (flag < 0)//斜率大於1則交換XY座標 DrawPixel(y, x, color); else DrawPixel(x, y, color); } }
- 中點畫線法:考慮方式大致同Bresenham演算法
function MiddlePiont(x0, y0, x1, y1, color) { var dx, dy, d1, d2, d, x, y, m; dy = y0 - y1; dx = x1 - x0; var flag = Math.abs(dx) - Math.abs(dy);//判斷斜率是否大於1 if (flag < 0) {//斜率大於1則交換XY座標 m = y0; y0 = x0; x0 = m; m = y1; y1 = x1; x1 = m; } dy = y0 - y1; dx = x1 - x0; d = 2 * dy + Math.abs(dx); d1 = 2 * dy; d2 = 2 * (Math.abs(dx) + dy); x = x0; y = y0; var incX = (dx > 0) ? 1 : -1;//每次增加步長,避免<0的情況 var incY = (dy > 0) ? -1 : 1; for (var i = 0; i < Math.abs(dx) ; i++) { x += incX; if (d < 0) { y += incY; d += d2; } else d += d1; if (flag < 0)//斜率大於1則交換XY座標 DrawPixel(y, x, color); else DrawPixel(x, y, color); }}