@markheng
2016-03-12T12:42:01.000000Z
字数 3105
阅读 1686
计算机图形学
直线的笛卡尔斜率截距式方程为
给定两个端点,可以计算斜率和截距
数字微分分析仪(digital differential analyzer,DDA)方法
依照式(6.4),(6.5)进行递推计算。
算法过程如下:
1. 输入线段两个端点的位置
2. 端点位置间水平和垂直的插值赋给参数和。
3. 绝对值大的参数确定参数的值。该值是在即将划出的的这条线段的上的像素数目
4. 按照这个数值,沿线段路径计算每一步的下一个像素位置
#include<stdlib.h>
#include<math.h>
inline int round (const float a) {return int (a + 0.5); }
void lineDDA (int x0, int y0, int xEnd, int yEnd ){
int dx = xEnd - x0, dy = yEnd - y0 , steps, k;
float xIncrement, yIncrement, x = x0, y = y0;
if(fabs (dx) > fabs (dy))
steps = fabs (dx);
else
steps = fabs (dy);
xIncrement = float (dx) / float (steps);
yIncerment = float (dy) / float (steps);
setPixel (round (x), round (y));
for (k = 0; k < steps; k++){
x += xIncrement;
y += yIncrement;
setPixel (round(x), round(y));
}
}
DDA方法计算比直接使用方程(6.1)计算的速度快。它利用光栅特性消除了直线方程中的乘法,二在x或y方向使用合适的增量,从而沿线路径逐步得到个像素的位置。但在浮点增量的连续叠加中,取整误差的积累使得对于较长线段所计算的像素位置偏离实际线段。而且算法中所采用的浮点数计算和取整操作都较费时。我们可以将增量m和1/m分离成整数和小数部分,从而使所有的计算都化简为整数操作来改善DDA算法的性能。
Bresenham 算法仅使用增量整数计算。
Bresenham 算法思想描述。
从给定的 处开始,逐步处理每个后继列(x位置),并在其扫描线y值最接近线段的像素上绘出一点。假如已经决定要显示的像素在,那么下一步需要确定在列上绘制哪个像素,是在位置,还是在位置。
在取样位置x_k + 1, 我们使用和来标识两个像素与数学上线路径的垂直便宜,在像素列位置处的直线上的y坐标可计算为:
决策参数的递归计算从线段左端点开始的每个整数x位置进行。起始像素位置的第一个参数通过方程(6.14) 及计算得出
时的Bresenham画线算法:
1. 输入线段的两个端点,并将做端点存储在中
2. 将装入帧缓存,画出第一个点
3. 计算常量,并得到决策参数的第一个值:
4. 从 开始,在沿线段庐江的每个处,进行下列检测:
如果,下一个要绘制的点是,并且
否则,下个要绘制的点是,并且
5. 重复步骤4,共 次
上述算法第四步一共执行 次
下面程序给出了斜率为0 < m < 1.0 的 Bresenham 画线算法的实现。首先将线段的端点像素位置输入程序,然后从左到右端点绘制像素。
#include<stdlib.h>
#include<math.h>
/*Bresenham line_drawing procedure for |m| < 1.0 */
void lineBres(int x0, int y0, int xEnd, int yEnd){
int dx = fabs (xEnd - x0), dy = fabs (yEnd - y0);
int p = 2 * dy - dx;
int twoDy = 2 * dy , twoDyMinusDx = 2 * (dy - dx);
int x, y;
if ( x0 > xEnd) {
x = xEnd;
y = yEnd;
xEnd = x0;
}
else {
x = x0;
y = y0;
}
setPixel (x, y);
while(x < xEnd){
x++;
if (p < 0)
p += twoDy;
else{
y++;
p += twoDyMinusDx;
}
setPixel (x, y);
}
}
通过n-1次调用画线函数实现折线的显示。