直線的Bresenham算法


在實驗課上用自己的算法畫直線被diss效率低

花了半天時間看了下Bresenham算法真🐮🍺

總結一下其中的精妙之處

Bresebham直線生成算法的基本原理是,每次在最大位移方向上走一步,而另一個方向是走步還是不走步取決於誤差項的判別。

聲明k為斜率

在0≤k<1的情況下,假設當前點是P(x1,y1),則下一個點在Pu(x1+1,y1+1)與Pd(x1+1,y1)中選一。

以M表示Pu與Pd的中點,即M(x1+1,y1+0.5)。設Q是理想直線與x=xi+1的交點;

顯然,若M在Q的下方,則Pu(x1+1,y1+1)離直線較近,應取為下一個像素;否則應取Pd(x1+1,y1)。

理解並不難 主要在於實現

依據該算法的原理基本能夠實現

窩先試着自己寫了一會

如果要實現各個方向的二維直線繪制

需要考慮多種情況 寫出來很不美觀

教材上給出了更好的解決方案:

同樣以0≤k<1為例

每次選取下個點時理想直線的y坐標都步進k個單位長度

累加值即為誤差項di

當di大於0.5時選取Pu否則選取Pd並使di-1

令ei=di-0.5

則ei>0時選取Pu否則選取Pd

經過改進,算法的效率大幅提升

但其中在計算斜率與誤差項時會用到小數和除法

並且下一步的選擇只與誤差項的符號有關

因此可以進一步改進:

可知ei的值由三種值組成:ei=-1/2(初始值)+(n個)y/x(步進值)-(m個)1(調整值)...

同乘2x即得2*x*ei=-x+(n個)2*y-(m個)2*x....

這樣即可得到僅由整數構成的算法

以上僅為對0≤k<1情況下的討論

其余的情況類似

附一段雜亂無章的代碼

 1 point<Type> now_point = start;
 2   point<Type> e_step, point_step;
 3   e_step.x = abs(step.x);
 4   e_step.y = abs(step.y);
 5   glBegin(GL_POINTS);
 6   if (step.x == 0 && step.y == 0) //No Step
 7     return;
 8   point_step.x = (step.x == 0) ? 1 : step.x / e_step.x;
 9   point_step.y = (step.y == 0) ? 1 : step.y / e_step.y;
10   if (step.x == 0) {   // k is endless
11     do{
12       glVertex2i(now_point.x, now_point.y);
13       now_point.y += point_step.y;
14     } while (now_point.y != end.y);
15   }
16   else if (step.y == 0) {   //k is zero
17     do {
18       glVertex2i(now_point.x, now_point.y);
19       now_point.x += point_step.x;
20     } while (now_point.x != end.x);
21   }
22   else if (abs(step.y / step.x) == 0) {   // |k| < 1
23     Type e = -e_step.x;
24     do {
25       glVertex2i(now_point.x, now_point.y);
26       e += 2 * e_step.y;
27       now_point.x += point_step.x;
28       if (e > 0) {
29         now_point.y += point_step.y;
30         e -= 2 * e_step.x;
31       }
32     } while (now_point.x != end.x);
33   }
34   else {    // |k| >= 1
35     Type e = -e_step.y;
36     do {
37       glVertex2i(now_point.x, now_point.y);
38       e += 2 * e_step.x;
39       now_point.y += point_step.y;
40       if (e > 0) {
41         now_point.x += point_step.x;
42         e -= 2 * e_step.y;
43       }
44     } while (now_point.y != end.y);
45   }
46   glEnd();
47   glFlush();
本菜雞的辣雞代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM