打算手动实现图形学中的绝大部分算法。 1.DDA算法 2.中点画线法 还是根据上述讨论分割四个部分,然后四个部分的参数都有些许不同,需要重新推导,具体每个方向的增量可以参考代码部分,代码的长度实际上是可以优化的,但是这样写容易理解一点。 3.bresenham算法,也是不同方向的参数不同,具体推导结果可以参照下面(建议每个方向都手动推导一遍,加深对算法的理解)
运行环境winform+c# (代码是通用的,如果在其他地方画图,只需要替换掉画点的函数即可)
我们的函数默认是按x坐标顺序递增传入的,因此在调用下面函数之前,需要保证p1.x Point pp = new Point();
if (p1.X > p2.X)
{
pp = p1;
p1 = p2;
p2 = pp;
}
根据-0.5,0,0.5分割斜率,可以把直线分成四个部分,这个算法本质比较简单,注意讨论好这四个方向的直线也没多大问题。void DDADrawLine(Point p1,Point p2)
{
Graphics g = this.CreateGraphics();
Brush p = new SolidBrush(Color.Red);
int dx = p2.X - p1.X;
int dy = p2.Y - p1.Y;
float x, y;
float k;
if (Math.Abs(dx) >= Math.Abs(dy))
{
k = (float)dy / dx;
x = p1.X;
y = p1.Y;
for (int i = 0; i <= Math.Abs(dx); i++)
{
g.FillRectangle(p, new RectangleF(x, (int)(y + 0.5), 1, 1));
y += k;
x++;
}
}
else if (Math.Abs(dx) < Math.Abs(dy))
{
k = (float)dx / dy;
x = p1.X;
y = p1.Y;
for (int i = 0; i <= Math.Abs(dy); i++)
{
g.FillRectangle(p, new RectangleF((int)(x + 0.5), y, 1, 1));
if (p1.Y < p2.Y)
{
y++;
x += k;
}
else
{
y--;
x -= k;
}
}
}
}
void MidPointDrawLine(Point p1, Point p2)
{
//分四种情况讨论
Graphics g = this.CreateGraphics();
Brush p = new SolidBrush(Color.Red);
int a = p1.Y - p2.Y;
int b = p2.X - p1.X;
int d;
int d1;
int d2;
int x = p1.X;
int y = p1.Y;
if (Math.Abs(b) > Math.Abs(a))
{
//case1
if (p1.Y < p2.Y)
{
d = 2 * a + b;
d1 = 2 * a;
d2 = 2 * a + 2 * b;
for (; x < p2.X; x++)
{
g.FillRectangle(p, new RectangleF(x, y, 1, 1));
if (d < 0)
{
y++;
d += d2;
}
else
d += d1;
}
}
//case2
else
{
a = -a;
b = -b;
d = 2 * a - b;
d1 = 2 * a;
d2 = 2 * a - 2 * b;
for (; x < p2.X; x++)
{
g.FillRectangle(p, new RectangleF(x, y, 1, 1));
if (d < 0)
{
y--;
d += d2;
}
else
d += d1;
}
}
}
else
{
//case3
if(y < p2.Y)
{
a = -a;
b = -b;
d = 2 * b + a;
d1 = 2 * b;
d2 = 2 * a + 2 * b;
for (; y < p2.Y; y++)
{
g.FillRectangle(p, new RectangleF(x, y, 1, 1));
if (d < 0)
{
d += d2;
x++;
}
else
{
d += d1;
}
}
}
else
{
d = a - 2 * b;
d1 = -2 * b;
d2 = 2 * a - 2 * b;
for (; y > p2.Y; y--)
{
g.FillRectangle(p, new RectangleF(x, y, 1, 1));
if (d < 0)
{
d += d2;
x++;
}
else
{
d += d1;
}
}
}
}
}
void BresenhamDrawLine(Point p1, Point p2)
{
//分四种情况讨论
Graphics g = this.CreateGraphics();
Brush p = new SolidBrush(Color.Red);
int dx = p2.X - p1.X;
int dy = p2.Y - p1.Y;
int e;
int x = p1.X;
int y = p1.Y;
//case 1:
if (Math.Abs(dx) >= Math.Abs(dy) && p1.Y <= p2.Y)
{
e = -dx;
for (int i = 0; i <= dx; i++)
{
g.FillRectangle(p, new RectangleF(x, y, 1, 1));
x++;
e += 2 * dy;
if (e > 0)
{
y++;
e -= 2 * dx;
}
}
}
//case2
if (Math.Abs(dx) < Math.Abs(dy) && p1.Y <= p2.Y)
{
e = -dy;
for (int i = 0; i <= dy; i++)
{
g.FillRectangle(p, new RectangleF(x, y, 1, 1));
y++;
e += 2 * dx;
if (e > 0)
{
x++;
e -= 2 * dy;
}
}
}
//case 3:
if (Math.Abs(dx) > Math.Abs(dy) && p1.Y > p2.Y)
{
e = dx;
for (int i = 0; i <= dx; i++)
{
g.FillRectangle(p, new RectangleF(x, y, 1, 1));
x++;
e += 2 * dy;
if (e < 0)
{
y--;
e += 2 * dx;
}
}
}
//case4
if (Math.Abs(dx) < Math.Abs(dy) && p1.Y > p2.Y)
{
e = dy;
for (int i = 0; i <= Math.Abs(dy); i++)
{
g.FillRectangle(p, new RectangleF(x, y, 1, 1));
y--;
e += 2 * dx;
if (e > 0)
{
x++;
e += 2 * dy;
}
}
}
}