1. 实验目标
实现 DDA、MidPoint 和 Bresenham 三种直线绘制算法,并从像素操作次数、耗时等维度比较三种算法的效率;同时,尝试实现线形设计与多边形构造功能,优化用户交互体验。
2. 基本原理
(1)DDA 扫描转换算法
DDA 是计算机图形学中最早用于把连续直线段离散化为像素点的算法之一,又称数值微分法。它的核心思想是:在主方向(x 或 y)上以固定的单位步长前进,利用直线斜率的增量来逐步计算另一坐标的近似值,从而得到一系列整数像素坐标。
(2)中点画线法
中点画线法是计算机图形学中用于把连续直线离散化为像素点的经典算法,属于基于隐式直线方程的增量判别法。它通过判断当前像素右侧两候选点(正右方 P₁ 和右上方 P₂)的中点 M 相对于理想直线的位置,决定下一步取哪个像素,从而一步步逼近真实直线。
(3)Bresenham 画线算法
Bresenham 算法是一种仅使用整数运算的光栅化方法,用来在离散像素网格上逼近一条连续直线。它通过决策参数(误差项)来判断下一像素是保持当前行(或列)还是向上(或右)跨一步,从而在每一步只做一次加法和一次比较,避免了浮点运算和乘除操作。
3. 代码实现
DDA 算法
// DDA 算法
void CDrawLineView::DDALine(CDC *pDC, int x1, int y1, int x2, int y2, COLORREF color) {
double dx, dy, e, x, y;
dx = x2 - x1;
dy = y2 - y1;
// 取绝对值大的 dx 或 dy 赋值给 e,需增加 math.h 头文件
e = (fabs(dx) > fabs(dy)) ? fabs(dx) : fabs(dy);
dx /= e;
dy /= e;
x = x1;
y = y1;
for(int i = 0; i <= e; i++) {
pDC->SetPixel((int)(x + 0.5), (int)(y + 0.5), color);
x += dx;
y += dy;
}
}
中点画线算法
// 中点画线算法
void CDrawLineView::MidLine(CDC *pDC, int x0, int y0, int x1, int y1, COLORREF color) {
a, b, delta1, delta2, d, x, y;
(x0 == x1) {
(y0 < y1) {
( i = y0; i <= y1; i++) pDC->(x0, i, color);
} {
( i = y1; i <= y0; i++) pDC->(x0, i, color);
}
;
}
m = ((y1 - y0) <= (x1 - x0));
(x0 > x1) {
d = x0; x0 = x1; x1 = d;
d = y0; y0 = y1; y1 = d;
}
a = y0 - y1;
b = x1 - x0;
x = x0;
y = y0;
pDC->(x, y, color);
(m) {
(y0 <= y1) {
d = * a + b;
delta1 = * a;
delta2 = * (a + b);
(x < x1) {
(d < ) {x++; y++; d += delta2;}
{x++; d += delta1;}
pDC->(x, y, color);
}
}
{
d = * a - b;
delta1 = * a;
delta2 = * (a - b);
(x < x1) {
(d < ) {x++; d += delta1;}
{x++; y--; d += delta2;}
pDC->(x, y, color);
}
}
}
{
(y0 <= y1) {
d = a + * b;
delta1 = * b;
delta2 = * (a + b);
(y < y1) {
(d < ) {y++; d += delta1;}
{y++; x++; d += delta2;}
pDC->(x, y, color);
}
}
{
d = a - * b;
delta1 = * b;
delta2 = * (a - b);
(y > y1) {
(d < ) {y--; x++; d += delta2;}
{y--; d += delta1;}
pDC->(x, y, color);
}
}
}
}


