您的位置:首页 > 其它

直线生成算法

2012-03-26 20:48 741 查看
直线生成算法:在光栅系统中绘制直线段,需要采用直线生成算法,常用的有DDA算法、Bresenham算法等。

Ø DDA直线生成算法是一种使用微分方程生成直线的算法,又称作数值微分法。该算法的基本思想是:根据斜率确定增量最大的方向,每次迭代时均在该方向上走一步,然后根据直线方程计算出另一方向上的值,对其四舍五入后得到像素坐标。

Ø Bresenham直线生成算法与DDA算法类似,每次迭代时均在增量最大方向上走一步,并计算决策参数,根据决策参数确定像素坐标。算法的巧妙之处在于采用了增量计算,使得对于每一列,只要检查误差量的符号,就可以确定该下一列的像素坐标。

ok 我们可以有四种不同创建项目方法来实现算法,包括vs2010下创建MFC程序,win32 Application,控制台程序(注:如果用它的话还需要下载openGL库文件, 下载链接:http://download.csdn.net/detail/qiushuiqifei/4136616

具体在vs2010配置操作链接:http://apps.hi.baidu.com/share/detail/55613195),还有就是Dev-c++下创建,这些都差不多,在这里我选择win 32 Application

1.创建一个win 32 Application项目,项目名为“20101620113_1”

2.找到20101620113_1.cpp文件 在该文件下操作

3.找到下面代码行

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// TODO: 在此添加任意绘图代码...

EndPaint(hWnd, &ps);

break;

4.下面主要介绍算法



//----------------------------------------------------------------------------------------------------

//绘制指定宽度点

void DrawPixel(HDC hDC,int x,int y,int width,int color)

{

if(width<1)

return;

else

for(int i=0;i<=width;i++)

{

SetPixel(hDC,x,y-i,color);

}

}

template<typename T>

void Breasenham_line(HDC hDC,T x00,T y00,T x11,T y11,int width,int color)

{

int x0=int(x00+0.5);

int y0=int(y00+0.5);

int x1=int(x11+0.5);

int y1=int(y11+0.5);

int dx,dy,e,i,x,y;

dx=x1-x0;

dy=y1-y0;

x=x0;

y=y0;

//----------------------------------------------------------------------------------------------------

//当 y0=y1 即平行x轴 单独处理

if(y0==y1)

{

if(x1>=x0)

{

for(i=0;i<abs(dx);i++)

{

//

DrawPixel(hDC,x,y,width,color);

//SetPixel(hDC,x,y,color);

//pDC->SetPixel(x,y-1,color);

x++;

}

}

else

{

for(i=0;i<=abs(dx);i++)

{

DrawPixel(hDC,x,y,width,color);

x--;

}

}

}

//----------------------------------------------------------------------------------------------------

//当 x0=x1 即平行y轴 单独处理

if(x0==x1)

{

if(y1>=y0)

{

for(i=0;i<=abs(dy);i++)

{

for(int i=0;i<=width;i++)

{

SetPixel(hDC,x-i,y,color);

}

y++;

}

}

else

{

for(i=0;i<=abs(dy);i++)

{

for(int i=0;i<=width;i++)

{

SetPixel(hDC,x-i,y,color);

}

y--;

}

}

}

//----------------------------------------------------------------------------------------------------

//当x0<x1&& y0<y1 即在第一象限的直线处理

if(x0<x1 && y0<y1)

{

//当斜率小于1且大于0时

if((y1-y0)/(x1-x0)<1)

{

e=2*dy-dx;

for(i=0;i<abs(dx);i++)

{

DrawPixel(hDC,x,y,width,color);

x++;

e+=2*dy;

if(e>=0)

{

y++;

e-=2*dx;

}

}

}

//当斜率大于等于1时

else

{

e=2*dx-dy;

for(i=0;i<=abs(dy);i++)

{

DrawPixel(hDC,x,y,width,color);

y++;

e+=2*dx;

if(e>=0)

{

x++;

e-=2*dy;

}

}

}

}

//--------------------------------------------------------------------------------------------------------

//当x0>x1 && y0<y1 在第二象限的直线处理

if(x0>x1 && y0<y1)

{

/* 由对称的性质易知与在第一象限的直线关于y轴对称

故只需将上一段代码稍微更改,把与x有关的变量改为它的相反数

*/

//斜率小于-1

if(dy/dx<-1)

{

e=-2*dx-dy;

for(i=0;i<abs(dy);i++)

{

DrawPixel(hDC,x,y,width,color);

y++;

e-=2*dx;

if(e>0)

{

x--;

e-=2*dy;

}

}

}

//斜率大于等于-1小于0

else

{

e=2*dy+dx;

for(i=0;i<=abs(dx);i++)

{

DrawPixel(hDC,x,y,width,color);

x--;

e+=2*dy;

if(e>=0)

{

y++;

e+=2*dx;

}

}

}

}

//--------------------------------------------------------------------------------------------------------

//当x0>x1 && y0>y1 即第三象限的直线处理

if(x0>x1 && y0>y1)

{

/* 由对称的性质易知与在第一象限的直线关于原点对称

故只需将上一段代码稍微更改,把与x,y有关的变量改为它的相反数

*/

//斜率小于1

if((y1-y0)/(x1-x0)<1)

{

e=-2*dy+dx;

for(i=0;i<abs(dx);i++)

{

DrawPixel(hDC,x,y,width,color);

x--;

e-=2*dy;

if(e>=0)

{

y--;

e+=2*dx;

}

}

}

//斜率大于等于1

else

{

e=-2*dx+dy;

for(i=0;i<=abs(dy);i++)

{

DrawPixel(hDC,x,y,width,color);

y--;

e-=2*dx;

if(e>=0)

{

x--;

e+=2*dy;

}

}

}

}

//--------------------------------------------------------------------------------------------------------

//当x0<x1 && y0>y1 即第四象限的直线处理

if(x0<x1 && y0>y1)

{

/* 由对称的性质易知与在第一象限的直线关于x轴对称

故只需将上一段代码稍微更改,把与x,y有关的变量改为它的相反数

*/

//斜率小于-1

if(dy/dx<-1)

{

e=2*dx+dy;

for(i=0;i<abs(dy);i++)

{

DrawPixel(hDC,x,y,width,color);

y--;

e+=2*dx;

if(e>0)

{

x++;

e+=2*dy;

}

}

}

//斜率大于等于-1

else

{

e=-2*dy-dx;

for(i=0;i<=abs(dx);i++)

{

DrawPixel(hDC,x,y,width,color);

x++;

e-=2*dy;

if(e>=0)

{

y--;

e-=2*dx;

}

}

}

}

}

//------------------------------------------------------------------------------------------

//利用DDA算法和Bresenham算法结合对线的端点进行改进

void DDAAndBreasenham_line(HDC hDC,int x0,int y0,int x1,int y1,int width,int color)

{

int i;

float dx,dy,length,x,y;

if(abs(x1-x0)>=abs(y1-y0))

length=abs(x1-x0);

else

length=abs(y1-y0);

dx=(x1-x0)/length;

dy=(y1-y0)/length;

float k=dy/dx;

i=1;

x=x0;

y=y0;

while(i<=length)

{

//主要利用边线互相垂直的特点进行设计

Breasenham_line(hDC,x,y,x+(k*width)/(k*k+1),y+width/(k*k+1),1,color);

x+=dx;

y+=dy;

i++;

}

}

注释我写得挺详细的 但这里再多几嘴 对于Bresenham_line函数主要是分情况讨论,然后利用对称特性 故只要计算第一象限的直线生成算法,其他象限可以可以利用与第一象限的直线对称得出,这里利用函数模板只是为了兼容float类型(即坐标为浮点的支持)。而对于DDAAndBreasenham_line函数这是改进算法,主要处理有宽度的直线边界,使之不是尖形,这里混合了DDA算法和Bresenham算法,把两算法结合一起用了,通过几何运算处理,结果并未完全按我想象中的一样,而且利于了*
/ 运算 使得算法效率下降。有待改进……

看下运行效果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: