功能:由鼠标单击给定初末点位置作出相应直线。
1,打开VS2019 选择新建项目 Windows 窗体应用(.NET framework)
2,此处项目名称命名为“Computer_Graphics”,项目建立后出现如下视图
3,在左侧工具箱选中“MenuStrip”将其拖入“Form1”窗体中
键入想要设计的功能,这里设计了如图所示三种画直线的算法
窗体设计完成,开始写代码。现在代码区插入如下代码
Color BackColor1 = Color.White; //指定窗体背景色
Color ForeColor1 = Color.Black; //指定线的颜色
public int MenuID = 0, PressNum = 0; //pressnum = 1时画直线
public Point Firstpoint = new Point(0, 0); //定义第一个点
public Point Secondpoint = new Point(0, 0); //定义第二个点
public int Ways = 1; //记录在窗体中的操作
由于直线初末位置由鼠标单击窗体给出,所以要先定义窗体的鼠标单击响应函数。先单击选中窗体,在界面右下角找到属性框,点击“事件”(小闪电图标)在下面给出的事件中找到“MouseClick”,双击进入代码窗口
进入代码区后,键入如下代码
Graphics g = CreateGraphics();
Pen Mypen = new Pen(Color.Red, 1);
if (MenuID == 1)
{
if (PressNum == 0)
{
Firstpoint.X = e.X; Firstpoint.Y = e.Y;
Secondpoint.X = e.X; Secondpoint.Y = e.Y;
}
else
{
if (Ways == 1)
{
DDLline(Firstpoint.X, Firstpoint.Y, Secondpoint.X, Secondpoint.Y);//------调用DDA画直线
}
if (Ways == 2)
{
Midpoint(Firstpoint.X, Firstpoint.Y, Secondpoint.X, Secondpoint.Y);//------调用中点画线法
}
if (Ways == 3)
{
Bresenham(Firstpoint.X, Firstpoint.Y, Secondpoint.X, Secondpoint.Y);//-----调用bresenham算法
}
}
PressNum++;
if (PressNum >= 2)
PressNum = 0;
}
此时还需要一个鼠标移动函数记录鼠标在窗体中的移动位置,同样选中窗体,在界面右下角找到属性框,点击“事件”(小闪电图标)在下面给出的事件中找到“MouseMove”,双击进入代码窗口
进入代码区后键入如下代码
Graphics g = CreateGraphics();
Pen Backpen = new Pen(BackColor1, 1);
Pen Mypen = new Pen(ForeColor1, 1);
if (MenuID == 1 && PressNum == 1)
{
if (!(e.X == Secondpoint.X && e.Y == Secondpoint.Y))
{
g.DrawLine(Backpen, Firstpoint.X, Firstpoint.Y, Secondpoint.X, Secondpoint.Y);//底层白线,可不要
g.DrawLine(Mypen, Firstpoint.X, Firstpoint.Y, e.X, e.Y);//中间线黑线,可不要
Secondpoint.X = e.X;
Secondpoint.Y = e.Y;
}
}
接下来完善功能代码,回到“Form1” 窗口,找到之前设计的“DDA画线法”,双击进入代码区域,键入如下代码
Ways = 1;
MenuID = 1;插入代码片
同样的方式创立“中点画线法”,“Bresenham画线法”单击响应函数
划重点:三种直线算法函数的设计
1.DDA画线法
代码区键入如下代码
Graphics g = CreateGraphics();
Pen b = new Pen(Color.Red, 1);
if (x0 == x1 && y0 == y1)
return;
double x, y; //记录即时坐标
double dx, dy; //记录起点和终点的坐标差值
double delta_x, delta_y; //记录划线过程中的坐标增量
double steps; //记录步长
dx = x1 - x0;
dy = y1 - y0;
if (Math.Abs(dx) > Math.Abs(dy)) //比较横纵坐标增量的大小
steps = dx;
else
steps = dy; //确保每次的增量不超过一个单位长度
x = x0;
y = y0; //记录画线起点
delta_x = (double)(dx * 1.0) / Math.Abs(steps);
delta_y = (double)(dy * 1.0) / Math.Abs(steps); //计算相邻两个点的增量
for (int i = 0; i < Math.Abs(steps); i++)
{
x = x + delta_x;
y = y + delta_y;
g.DrawRectangle(b, (int)x, (int)(y + 0.5), 1, 1);
放个图
2,中点画线法
代码区键入如下代码
private void Midpoint(int x0, int y0, int x1, int y1)//------------中点画线法
{
Graphics g = CreateGraphics();
Pen p = new Pen(Color.Green, 1);
if (x0 == x1 && y0 == y1)
return;
double a = y0 - y1;
double b = x1 - x0;
double c = x0 * y1 - x1 * y0;
double x, y, k, d;
k = -a / b;
//--------------------------------------
if (k > 0 && k < 1)
{
if (x1 > x0)
{
y = y0;
for (x = x0; x < x1;)
{
d = a * (x + 1) + b * (y + 0.5) + c;
if (d < 0)
{ x++; y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
else
{ x++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
}
}
if (x1 < x0)
{
y = y1;
for (x = x1; x < x0;)
{
d = a * (x + 1) + b * (y + 0.5) + c;
if (d > 0)
{ x++; y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
else
{ x++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
}
}
}
//-------------------------
if (k >= 1)
{
if (y1 > y0)
{
x = x0;
for (y = y0; y < y1;)
{
d = a * (x + 1) + b * (y + 0.5) + c;
if (d > 0)
{ x++; y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
else
{ y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
}
}
if (y1 < y0)
{
x = x1;
for (y = y1; y < y0;)
{
d = a * (x + 1) + b * (y + 0.5) + c;
if (d < 0)
{ x++; y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
else
{ y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
}
}
}
//------------------------------------
if (k <= 0 && k > -1)
{
if (x1 > x0)
{
y = y1;
for (x = x1; x > x0;)
{
d = a * (x - 1) + b * (y + 0.5) + c;
if (d < 0)
{ x--; y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
else
{ x--; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
}
}
if (x0 > x1)
{
y = y0;
for (x = x0; x > x1;)
{
d = a * (x - 1) + b * (y + 0.5) + c;
if (d > 0)
{ x--; y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
else
{ x--; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
}
}
}
//---------------------------------------
if (k <= -1)
{
if (y1 > y0)
{
x = x0;
for (y = y0; y < y1;)
{
d = a * (x + 1) + b * (y + 0.5) + c;
if (d < 0)
{ x--; y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
else
{ y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
}
}
if (y1 < y0)
{
x = x1;
for (y = y1; y < y0;)
{
d = a * (x + 1) + b * (y + 0.5) + c;
if (d > 0)
{ x--; y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
else
{ y++; g.DrawRectangle(p, (int)x, (int)y, 1, 1); }
}
}
}
//---------------------------------------
if (x1 == x0)
{
x = x0;
if (y1 < y0)
{
y = y0;
y0 = y1;
y1 = (int)y;
x = x1;
}
for (y = y0; y <= y1; y++)
{
g.DrawRectangle(p, (int)x, (int)y, 1, 1);
}
}
}
3,Bresenham画线法
代码区键入如下代码
private void Bresenham(int x0, int y0, int x1, int y1)//--------------------------Bresenham算法
{
Graphics g = CreateGraphics();
Pen p = new Pen(Color.Blue, 1);
if (x0 == x1 && y0 == y1)
return;
double dx = x1 - x0;
double dy = y1 - y0;
double k = dy / dx;
double e = -0.5;
int x = x0;
int y = y0;
int i;
if (k > 0 && k <= 1)
{
if (x1 < x0)
{
x = x1;
y = y1;
dx = x0 - x1;
dy = y0 - y1;
}
for (i = 0; i <= dx; i++)
{
g.DrawRectangle(p, x, y, 1, 1);
x = x + 1;
e = e + k;
if (e >= 0)
{
y++;
e = e - 1;
}
}
}
//-----------------------------------------
if (k > 1)
{
if (y1 < y0)
{
x = x1;
y = y1;
dx = x0 - x1;
dy = y0 - y1;
}
for (i = 0; i <= dy; i++)
{
g.DrawRectangle(p, x, y, 1, 1);
y = y + 1;
e = e + 1 / k;
if (e >= 0)
{
x++;
e = e - 1;
}
}
}
//--------------------------------------------
if (k <= -1)
{
if (y1 < y0)
{
x = x1;
y = y1;
dx = x0 - x1;
dy = y0 - y1;
}
for (i = 0; i <= dy; i++)
{
g.DrawRectangle(p, x, y, 1, 1);
y = y + 1;
e = e - 1 / k;
if (e >= 0)
{
x--;
e = e - 1;
}
}
}
//--------------------------------------
if (k < 0 && k > -1)
{
if (x1 < x0)
{
x = x1;
y = y1;
dx = x0 - x1;
dy = y0 - y1;
}
for (i = 0; i <= dx; i++)
{
g.DrawRectangle(p, x, y, 1, 1);
x = x + 1;
e = e - k;
if (e >= 0)
{
y--;
e = e - 1;
}
}
}
//---------------------------------------
if (x1 == x0)
{
if (y1 < y0)
{
y = y0;
y0 = y1;
y1 = y;
x = x1;
}
for (y = y0; y <= y1; y++)
{
g.DrawRectangle(p, x, y, 1, 1);
}
}
//--------------------------
if (k == 0)
{
if (x1 < x0)
{
x = x0;
x0 = x1;
x1 = x;
y = y1;
}
for (x = x0; x < x1; x++)
{
g.DrawRectangle(p, x, y, 1, 1);
}
}
}
画直线功能大功告成
运行结果
设计一个清除画线功能,点击清除进入代码区
键入如下代码
Graphics g = CreateGraphics();
g.Clear(Color.White);
MenuID = 0;