计算机图形学—DDA直线画法c#实现
DDA直线画法,即数值微分法,是计算机图形学中直线段扫描转换的经典算法之一,本篇文章将简单介绍DDA算法,并给出c#实现的代码。
一、DDA直线画法
设直线的斜截式方程为
y
i
=
k
i
x
+
b
y_i = k_ix + b
yi=kix+b。
根据微分的思想,可以得到
y
i
+
1
=
y
i
+
k
y_{i+1} = y_i + k
yi+1=yi+k。
这个式子的含义是:当前步的y值等于前一步的y值加上斜率。运用这个思想,算出每一步y的取值,并对y四舍五入得到像素值,即可得到直线段每个像素点的坐标并绘制。
下面是一个简单的举例:绘制直线段(0,0)–(5,2)。
x | y | 四舍五入 |
---|---|---|
0 | 0 | 0 |
1 | 0+0.4 | 0 |
2 | 0.4+0.4 | 1 |
3 | 0.8+0.4 | 1 |
4 | 1.2+0.4 | 2 |
5 | 1.6+0.4 | 2 |
以上例子仅讨论了k<=1的情况,k>1的情况可同理推出,在代码实现中有讨论,不再举例。
二、C#代码实现
像素点的绘制采用System.Drawing库中Graphics的FillRectangle方法填充单个像素。
public void DDAline(int x0, int y0, int x1, int y1, Graphics g, Brush brush) //DDA画线法。
{
float dx, dy, k;
dx = x1 - x0;
dy = y1 - y0;
if (dx == 0)//斜率不存在情况
{
int y;
for (y = y0; y <= y1; y++)
{
g.FillRectangle(brush, x0, y, 1, 1);
}
for (y = y1; y <= y0; y++)
{
g.FillRectangle(brush, x0, y, 1, 1);
}
}
else
{
k = dy / dx;
if (Math.Abs(k) <= 1)//斜率小于1情况。
{
int x;
float y = y0;
for (x = x0; x <= x1; x++)//x0小于x1情况。
{
g.FillRectangle(brush, x, (int)Math.Floor(y + 0.5), 1, 1);
y += k;
}
y = y1;
for (x = x1; x <= x0; x++)//x1小于x0情况。
{
g.FillRectangle(brush, x, (int)Math.Floor(y + 0.5), 1, 1);
y += k;
}
}
if (Math.Abs(k) > 1)//斜率大于1情况。
{
float x = x0;
int y;
for (y = y0; y <= y1; y++)//y0小于y1情况。
{
g.FillRectangle(brush, (int)Math.Floor(x + 0.5), y, 1, 1);
x += 1 / k;
}
x = x1;
for (y = y1; y <= y0; y++)//y1小于y0情况。
{
g.FillRectangle(brush, (int)Math.Floor(x + 0.5), y, 1, 1);
x += 1 / k;
}
}
}
}
总结
代码实现过程中,应考虑直线画法的多种情况,避免代码错误。例如考虑斜率不存在的情况,起点x0与终点x1的大小关系。