实现直线的生成算法
利用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();
所以看你自己,想改就自己改。
上一篇: C/C++ 16bit转8bit
下一篇: MacOS下编译osgEarth