一、 Bresenham算法简要分析
初始值:两个点坐标
需要解决三个分类问题:
- 处理斜率的绝对值大于还是小于1的问题(决定x轴导向还是y轴导向)
- 处理从右向左画还是从左向右画的问题(决定起点位于何处)
- 处理斜率为正还是负的问题
解决方式:
- 由于x轴与y轴具有对称性,考虑到代码复用,直接设立变量steep区分这两种情况,steep=1,说明|m|>1;steep=0,说明0<|m|<1。默认方式采用实验报告中代码,0<|m|<1。
- 起始两个点,利用xs和xe差值比较,确定起点,默认从右向左画线。
- 起始两个点,确定好起点后,利用ye和ys的差值比较,确定斜率正负。
二、具体代码
void swap(int* x, int* y) {
int temp = *y;
*y = *x;
*x = temp;
}
// Bresenham line algorithm
void MyLine(int xs, int ys, int xe, int ye){
//问题1
bool steep = abs(ye - ys) > abs(xe - xs);
if (steep){
swap(xe, ye);
swap(xs, ys);
}
//问题2
if (xs > xe){
swap(xe, xs);
swap(ye, ys);
}
int dx = xe - xs;
int dy = abs(ye - ys);
int p = 2 * dy - dx;
int stepy;
//问题3
ye < ys ? stepy = -1 : stepy = 1;
//具体开始画线
int y = ys;
for (int x = xs; x <= xe; ++x){
if (steep) {
glBegin(GL_POINTS);
glVertex2i(y, x);
glEnd();
}else {
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
p += 2 * dy;
if (p > 0){
y += stepy;
p -= 2 * dx;
}
}
}
三、代码反思
原来写代码的时候,对于Bresenham算法分类的层次结构并不清晰,导致很多情况都漏掉了,且代码冗长复杂,过多的使用了if…else if….else,并在其中进行选择的嵌套,这种结构尤其增加阅读难度,容易出错。
因此改进后使用了更符合并列结构的标志steep等等,分情况解决了问题。