直线的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();
本菜鸡的辣鸡代码

 

posted @ 2018-09-17 22:16  曰..曰  阅读(1617)  评论(0编辑  收藏  举报