Basic
1、Bresenham算法绘制三角形边框
- 使用Bresenham算法绘制三角形边框,我们先获得取值范围在-1.0f~1.0f的三个点坐标,分别乘500。将三个点两两配对,通过Bresenham算法获得绘制直线的所有点的坐标,除以500再存在数组中,最后通过
glDrawArrays(GL_POINTS, 0, length)
绘制直线,三条直线组合成为一个三角形边框。 - 绘制直线的Bresenham算法:
p 0 = 2 Δ y − Δ x p_0=2\Delta\ y -\Delta\ x p0=2Δ y−Δ x
p ≤ 0 p \leq\ 0 p≤ 0 p p pi+1 = p i + 2 Δ y p_i + 2\Delta\ y pi+2Δ y
y y yi+1 = y i = y_i =yi
p > 0 p > 0 p>0 p p pi+1 = p i + 2 Δ y − 2 Δ x p_i + 2\Delta\ y - 2\Delta\ x pi+2Δ y−2Δ x
y y yi+1 = y i + 1 = y_i+1 =yi+1 or y y yi+1 = y i − 1 = y_i-1 =yi−1
x x xi+1 = x i − 1 = x_i-1 =xi−1 or x x xi+1 = x i + 1 = x_i+1 =xi+1 - 代码实现
两点确定一条直线,首先我们要确定这条直线的斜率,根据斜率分为三种情况:
(1)斜率不存在
(2)斜率绝对值小于等于1
(3)斜率绝对值大于1-
Bresenham算法
void bresenham(int array[], int p, int i, int length, int dx, int dy, int flag) { if (i == length) return; int pnext; if (p <= 0) { array[i + 1] = array[i]; pnext = p + 2 * dy; } else { array[i + 1] = array[i] + flag; pnext = p + 2 * dy - 2 * dx; } bresenham(array, pnext, i + 1, length, dx, dy, flag); }
-
斜率不存在
if (x_begin == x_end) //如果斜率不存在 { if (y_begin > y_end) { flag = -1; //判断在y轴的增减性 } length = abs(y_end - y_begin) + 1; for (int i = 0; i < length; ++i) { vertices_x[i] = x_begin; vertices_y[i] = y_begin + i * flag; } }
-
斜率绝对值小于等于1
在这种情况下,x轴方向上的变化快于y轴方向上的变化,因此,我们在x轴上取样,取样间隔为1,在y轴上量化。float m = float(y_end - y_begin) / float(x_end - x_begin); if (fabs(m) <= 1) //如果斜率绝对值小于等于1,则在x坐标轴上采样 { flag = (x_begin > x_end) ? -1 : 1; //判断x的增减性 int dy = abs(y_end - y_begin); int dx = abs(x_end - x_begin); length = dx + 1; for (int i = 0; i < length; ++i) //x坐标轴上的采样点 { vertices_x[i] = x_begin + i * flag; } flag = (y_begin <= y_end) ? 1 : -1; //判断y的增减性 vertices_y[0] = y_begin; int p0 = 2 * dy - dx; bresenham(vertices_y, p0, 0, length, dx, dy, flag); }
-
斜率绝对值大于1
在这种情况下,y轴方向上的变化快于x轴方向上的变化,因此,我们在y轴上取样,取样间隔为1,在x轴上量化flag = (y_begin > y_end) ? -1 : 1; //判断在y轴上的增减性 int dy = abs(y_end - y_begin); int dx = abs(x_end - x_begin); length = dy + 1; for (int i = 0; i < length; ++i) //y坐标轴上的采样点 { vertices_y[i] = y_begin + i * flag; } flag = (x_begin <= x_end) ? 1 : -1; //判断在x轴上的增减性 vertices_x[0] = x_begin; int p0 = 2 * dx - dy; bresenham(vertices_x, p0, 0, length, dy, dx, flag);
-
- 运行结果
2、Bresenham算法绘制圆
- 使用Bresenham算法绘制圆的关键在于找对p的递归关系,这方面网上有好几种递归方式,我使用了其中一种。在寻找绘制圆的坐标点时,可以只计算从y轴正方向到x轴正方向转过的八分之一圆弧,其他圆弧都可以通过这八分之一圆弧上的坐标点变换得到。
- 绘制圆的Bresenham算法:
p 0 = 1 − r p_0=1-r p0=1−r
p ≤ 0 p \leq\ 0 p≤ 0 p p pi+1 = p i + 2 x + 3 =p_i + 2x + 3 =pi+2x+3
y y yi+1 = y i = y_i =yi
p > 0 p > 0 p>0 p p pi+1 = p i + 2 x − 2 y + 5 =p_i + 2x-2y+5 =pi+2x−2y+5
y y yi+1 = y i − 1 = y_i - 1 =yi−1
x = x + 1 x=x+1 x=x+1 - 代码实现
- Bresenham算法
void bresenham_circle(int array[], int p, int x, int y, int &index) { if (x >= y) return; int pnext; if (p <= 0) { pnext = p + 2 * x + 3; } else { pnext = p + 2 * (x - y) + 5; --y; } array[index] = y; ++x; ++index; bresenham_circle(array, pnext, x, y, index); }
- Bresenham算法
- 实验结果