欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

实现直线的生成算法

程序员文章站 2022-07-01 21:00:46
...

利用VisualC++6.0设计一个简易画直线绘图板,验证直线生成算法

启动Visual C++6.0后,打开【File】(文件)菜单下的【New】(新建)菜单项,选择Project(工程)项。然后选择“MFC AppWizard(exe)”选项,在右边的对话框Project name(工程名称)中输入“Draw_Line”(工程名不要打错了),在接下来的步骤中依次选择“多重文档”,然后单击【Finish】(完成)按钮
后面的一些步骤看前面的:
Visual C++ MFC的图形绘制
(ID当时我没写,按道理要写但是没写问题也不大)
实现直线的生成算法
加完后就是这样的
实现直线的生成算法
然后为这几个建立类向导(因为我没写ID,所以就系统自己取的,也蛮好找。。。)
函数名字分别是:OnDad OnMid OnBre (word文档名字就是这样的,你自己随便取的话就自己改)
实现直线的生成算法
ok,全都添加好了之后,点确定

找到这个,往下滑到最底端就会出现刚刚建的三个函数
代码复制粘贴就OK了。
实现直线的生成算法
数值微分算法

void CDraw_LineView::OnDad() 
{
	// TODO: Add your command handler code here
	CDC*pDC=GetDC();//得到绘图类指针
	RedrawWindow();//重绘窗口
    int x,x0,y0,x1,y1;//(x0,y0)为直线的起点,(x1,y1)为直线的终点
	float dx,dy,k,y;
	x0=100,y0=100,x1=300,y1=300;
	dx=x1-x0;
	dy=y1-y0;
	k=dy/dx;
	y=y0;
	for(x=x0;x<=x1;x++)
	  {
		 pDC->SetPixel(x,int(y+0.5),RGB(255,0,0));
		 y=y+k;
	  }
}

中点画线算法

void CDraw_LineView::OnMid() 
{
	   // TODO: Add your command handler code here
	   CDC*pDC=GetDC();//得到绘图类指针
	   //RedrawWindow();//重绘窗口
	   int x0,y0,x1,y1;//(x0,y0)为直线的起点,(x1,y1)为直线的终点
	   int a,b,delta1,delta2,d,x,y;
	   x0=100,y0=100,x1=300,y1=200;
	   a=y0-y1;
	   b=x1-x0;
	   d=2*a+b;
	   delta1=2*a;
	   delta2=2*(a+b);
	   x=x0;
	   y=y0;
	   pDC->SetPixel(x,y,RGB(0,0,255));//SetPixel为CDC类里面的画点函数,具体参数
       while(x<x1)                  // 有3个,分别是点的坐标和画点所用的颜色。   
			{
			 if(d<0)
			   {
				x++;
				y++;
				d+=delta2;
			   }
			 else
			   {
				x++;
				d+=delta1;
			   }
			 pDC->SetPixel(x,y,RGB(0,255,0));
			}
}

Bresenham画线算法

void CDraw_LineView::OnBre() 
{
	  // TODO: Add your command handler code here
	   CDC*pDC=GetDC();//得到绘图类指针
	   //RedrawWindow();//重绘窗口
	   int x,y,x0,y0,x1,y1;//(x0,y0)为直线的起点,(x1,y1)为直线的终点
	   int dx,dy;
	   float k,e;
	   x0=100,y0=100,x1=300,y1=250;
	   dx=x1-x0;
	   dy=y1-y0;
	   k=float(dy)/dx;
	      e=-0.5;
	   x=x0;
	   y=y0;
	   for(int i=0;i<=dx;i++)
		  {
		   pDC->SetPixel(x,y,RGB(0,0,255));
		   x++;
		   e=e+k;
		   if(e>=0)
			 {
			  y++;
			  e--;
			 }
		  }
}

ok,可以编译运行了,如果认为做完了那就大错特错了,哪有简单,上面几步几分钟就做完了,会给你两节课做???
下面这个才是重点:
(4)以上的内容为本次实验的基本部分,给出的示例代码只能解决直线斜率的绝对值不超过1的情形(|k|≤1)。当直线的斜率不满足这个条件的时候,如何处理,请同学们根据相关算法的思想,完成任意斜率直线的生成,上机调试通过。
数值微分算法(代码报错的地方自己填整数(怕大家画出来的图都一样。。),左上角是原点)

int round(float x){                               //原整操作
	return (int)(x>0?x-0.5:x+0.5);
}
void CDraw_LineView::OnDad() 
{
	// TODO: Add your command handler code here
	CDC*pDC=GetDC();//得到绘图类指针
	RedrawWindow();//重绘窗口
    int x0,y0,x1,y1;//(x0,y0)为直线的起点,(x1,y1)为直线的终点
	x0=,y0=,x1=,y1=;
	float x,y,cx,cy;
	int s=abs(x1-x0)>abs(y1-y0)?abs(x1-x0):abs(y1-y0);
	x=(float)x0;
	y=(float)y0;
	cx=(float)(x1-x0)/s;
	cy=(float)(y1-y0)/s;
	for(int i=0;i<s;i++)
	{
		pDC->SetPixel(round(x),round(y),RGB(0,0,255));
		x+=cx;
		y+=cy;
	}

}

中点画线算法(代码报错的地方自己填整数)

void CDraw_LineView::OnMid() 
{
// TODO: Add your command handler code here
	   CDC*pDC=GetDC();//得到绘图类指针
	   //RedrawWindow();//重绘窗口
	   int x0,y0,x1,y1;//(x0,y0)为直线的起点,(x1,y1)为直线的终点
	   x0=,y0=,x1=,y1=;
	   int x=x0,y=y0;
	   int a=y0-y1,b=x1-x0;
	   int cx=(b>=0?1:(b=-b,-1));
	   int cy=(a<=0?1:(a=-a,-1));
	   pDC->SetPixel(x,y,RGB(0,0,255));//SetPixel为CDC类里面的画点函数,具体参数
                        // 有3个,分别是点的坐标和画点所用的颜色。   
			int d,d1,d2;
			if(-a<=b){    //斜率绝对值小于等于1
				d=2*a+b;
				d1=2*a;
				d2=2*(a+b);
				while(x!=x1){
					if(d<0)
					{y+=cy;d+=d2;}
					else
						d+=d1;
					x+=cx;
					pDC->SetPixel(x,y,RGB(0,255,0));
				}
			}
			else
			{
				d=2*b+a;
				d1=2*b;
				d2=2*(a+b);
				while(y!=y1){
					if(d<0)
						d+=d1;
					else
						{x+=cx;d+=d2;}
					y+=cy;
					pDC->SetPixel(x,y,RGB(0,255,0));
				}
			}

	
}

这位大佬写得也可以
中点画线任意斜率

Bresenham画线算法(代码报错的地方自己填整数)

void CDraw_LineView::OnBre() 
{
	  // TODO: Add your command handler code here
	   CDC*pDC=GetDC();//得到绘图类指针
	   //RedrawWindow();//重绘窗口
	   int x0,y0,x1,y1;//(x0,y0)为直线的起点,(x1,y1)为直线的终点
	   x0=,y0=,x1=,y1=;     //400 400  300 600
	   int x=x0,y=y0;
	   int dx=abs(x1-x0);
	   int dy=abs(y1-y0);
	   int s1=x1>x0?1:-1;
	   int s2=y1>y0?1:-1;
	   bool m =false;   //标记
	   if(dy>dx){    //当斜率大于1 互换
		int temp=dx;
		dx=dy;
		dy=temp;
		m=true;
	   }
	   int p=2*dy-dx;
	   for(int i=0;i<dx;i++){
			pDC->SetPixel(x,y,RGB(255,0,0));
			if(p>=0){
				if(!m)  y+=s2;
				else  x+=s1;
				p-=2*dx;
			}
			if(!m)  x+=s1;
			else    y+=s2;
			p+=2*dy;
	   }	
}

数字部分自己填(保证斜率大于1就可以了),下面是我自己的结果:
实现直线的生成算法
有的同学跟我说为什么用数值微分算法画直线前面画的线就没了,那可能就是没有注释掉RedrawWindow();

实现直线的生成算法
所以看你自己,想改就自己改。