DDA称为数值微分画线算法,是直线生成算法中最简单的一种原理相当简单,就是最直观的根据斜率的偏移程度,决定是以x为步进方向还是以y为步进方向然后在相应的步进方向上,步进变量每次增加一个像素,而另一个相关坐标变量则为Yk_1=Yk+m(以x为步进变量为例,m为斜率)假定直线斜率k在0~1之间,当前象素点为(xp,yp),则下一个象素点有两种可选择点P1(xp+1,yp)或P2(xp+1,yp+1)若P1与P2的中点(xp+1,yp+05)称为M,Q为理想直线与x=xp+1垂线的交点当M在Q的下方时,则取P2应为下一个象素点;当M在Q的上方时,则取P1为下一个象素点这就是中点画线法的基本原理Bresenham:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近的像素该算法的优点在于可以采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列所求的像素大概就是这样,预知详细,
这个是画圆的。
#include <mathh>
#include <graphicsh> /预定义库函数/
void circlePoint(int x,int y) /八分法画圆程序/
{
circle(320 x20,240 y20,3);
circle(320 y20,240 x20,3);
circle(320-y20,240 x20,3);
circle(320-x20,240 y20,3);
circle(320-x20,240 y20,3);
circle(320-x20,240-y20,3);
circle(320-y20,240-x20,3);
circle(320 y20,240-x20,3);
circle(320 x20,240-y20,3);
}
void MidBresenhamcircle(int r) / 中点Bresenham算法画圆的程序 /
{
int x,y,d;
x=0;y=r;d=1-r; / 计算初始值 /
while(x<y)
{ circlePoint(x,y); / 绘制点(x,y)及其在八分圆中的另外7个对称点 /
if(d<0) d =2x 3; / 根据误差项d的判断,决定非最大位移方向上是走还是不走 /
else
{ d =2(x-y) 5;
y--;
}
x ;
delay(900000);
} / while /
}
main()
{
int i,j,r,graphmode,graphdriver;
detectgraph(&graphdriver,&graphmode);
initgraph(&graphdriver,&graphmode," ");
printf("中点Bresenhamcircle算法画圆的程序\n"); /提示信息/
printf("注意 |r|<=11");
printf("\n输入半径值 r:");
scanf("%d",&r);
printf("按任意键显示图形");
getch();
cleardevice();
setbkcolor(BLACK);
for(i=20;i<=620;i =20) /使用双循环画点函数画出表格中的纵坐标/
for(j=20;j<=460;j )
putpixel(i,j,2);
for(j=20;j<=460;j =20) /使用双循环画点函数画出表格中的横坐标/
for(i=20;i<=620;i )
putpixel(i,j,2);
outtextxy(320,245,"0"); /原点坐标/
outtextxy(320-520,245,"-5");circle(320-520,240,2); /横坐标值/
outtextxy(320 520,245,"5");circle(320 520,240,2);
outtextxy(320-1020,245,"-10");circle(320-1020,240,2);
outtextxy(320 1020,245,"10");circle(320 1020,240,2);
outtextxy(320-1520,245,"-15");circle(320-1520,240,2);
outtextxy(320 1520,245,"15");circle(320 1520,240,2);
outtextxy(320,240-520,"-5");circle(320,240-520,2); /纵坐标值/
outtextxy(320,240 520,"5");circle(320,240 520,2);
outtextxy(320,240-1020,"-10");circle(320,240-1020,2);
outtextxy(320,240 1020,"10");circle(320,240 1020,2);
outtextxy(20,10,"The center of the circle is (0,0) "); /坐标轴左上角显示提示信息/
setcolor(RED); /标记坐标轴/
line(20,240,620,240); outtextxy(320 1520,230,"X");
line(320,20,320,460); outtextxy(330,20,"Y");
setcolor(YELLOW);
MidBresenhamcircle(r);
setcolor(BLUE); /绘制圆/
circle(320,240,r20);
setcolor(2);
getch();
closegraph();
}
下面这个是画直线的。
#include<graphicsh>
#include<mathh>
/
###############################################################################
功 能:本函数的作用是用逐点比较法来画一条直线
格 式:void myline1(int x1,int y1,int x2,int y2,int color)
参数说明:x1,y1是起始点坐标,x2,y2是终止点,color是画线的颜色
调用示例:myline1(10,20,500,440,4)
###############################################################################
/
void myline1(int x1,int y1,int x2,int y2,int color)
{
/变量定义开始(2007/10/16增加)/
int iTx; /x轴终点的相对坐标xa或临时变量/
int iTy; /y轴终点的相对坐标ya或临时变量/
int iDx; /x轴方向的步长dx/
int iDy; /y轴方向的步长dy/
int iFt; /偏差Fm/
int iSt; /记数循环数(dx+dy)S/
int iXt; /x方向循环变量xm/
int iYt; /y方向循环变量ym/
/变量定义结束/
/变量初始化开始/
/如果是第三象限或第四象限则换成第一或第二象限/
if(y2<y1)
{
iTx=x1;
x1=x2;
x2=iTx;
iTy=y1;
y1=y2;
y2=iTy;
}
iTx=x2-x1; /取x轴的相对坐标/
iTy=y2-y1; /取y轴的相对坐标/
iDx=1;
iDy=1;
iFt=0;
iSt=iTx+iTy;
if(iTx<0)iSt=-1iTx+iTy;; /如果在第二象限,则x轴方向步长取负值/
iXt=0;
iYt=0;
/变量初始化结束/
/数据处理开始/
while(iSt>0)
{
putpixel(x1+iXt,y1+iYt,color);
if(iTx>=0) /如果在第一象限/
{
if(iFt<0) /如果偏差小于0/
{
iYt+=iDy; /y方向走一步/
iFt+=iTx;
}
else /如果偏差大于或等于0/
{
iXt+=iDx; /x方向走一步/
iFt-=iTy;
}
}
else
{
if(iFt<0) /如果偏差小于0/
{
iXt-=iDx; /负x方向走一步/
iFt+=iTy;
}
else /如果偏差大于或等于0/
{
iYt+=iDy; /y方向走一步/
iFt+=iTx;
}
}
iSt--;
}
}
/
###############################################################################
功 能:本函数的作用是用来画一条直线
格 式:void myline2(int x1,int y1,int x2,int y2,int color)
参数说明:x1,y1是起始点坐标,x2,y2是终止点,color是画线的颜色
调用示例:myline2(10,20,500,440,4)
###############################################################################
/
int myline2(int x1,int y1,int x2,int y2,int color)
{
int iX; /x方向的坐标变量/
int iY; /y方向的坐标变量/
int iTx; /x方向的步长变量/
int iTy; /y方向的步长变量/
float fDx; /x方向的差分变量/
float fDy; /y方向的差分变量/
float fMinf; /算法中的f/
float fMaxF; /算法中的F/
float fS; /终点判断变量/
fMinf=05; /f=05/
iX=x1;
iY=y1;
putpixel(x1,y1,color);
if(x1==x2&&y1==y2) /如果终点和起始点相同/
{
return(1);
}
iTx=1;
iTy=1;
fDx=(float)(x2-x1);
fDy=(float)(y2-y1);
fMaxF=fDy/fDx>0fDy/fDx:(-fDy/fDx); /F=|dy/dx|/
if(fDx<0)iTx=-1;
if(fDy<0)iTy=-1;
fS=fDx>0fDx:(-fDx);
if(fMaxF==1) /如果F=1/
{
iX=x1;
iY=y1;
while(fS>0)
{
iX+=iTx; /x方向走一步/
iY+=iTy; /y方向走一步/
putpixel(iX,iY,color);
fS--;
}
}
else if(fMaxF>1) /如果F>1/
{
fS+=fDy>0fDy:(-fDy);
while(fS>0)
{
iY+=iTy; /y方向走一步/
putpixel(iX,iY,color);
fMinf+=1/fMaxF; /f=f+1/F/
fS--;
if(fMinf>=1) /如果f>=1/
{
iX+=iTx; /x方向走一步/
fMinf--; /f=f-1/
putpixel(iX,iY,color);
fS--;
}
}
}
else /如果F<1/
{
fS+=fDy>0fDy:(-fDy);
while(fS>0)
{
iX+=iTx; /x方向走一步/
putpixel(iX,iY,color);
fMinf+=fMaxF; /f=f+F/
fS--;
if(fMinf>=1) /如果f>=1/
{
iY+=iTy; /y方向走一步/
fMinf--; /f=f-1/
putpixel(iX,iY,color);
fS--;
}
}
}
}
不懂的可以继续探讨。谢谢
包含windowsh,里面有一个SetPixel方法,画线常用算法有三种dda,中点画线Bresenham画线->_->
刚把三种都写了下
void CDDALineView::drawDDALine(CDC pDC, int x0, int y0, int x1, int y1, COLORREF color){
float deltax, deltay, x, y;
int steps = max(abs(x1 - x0), abs(y1 - y0));
deltax = (x1 - x0) / steps;
deltay = (y1 - y0) / steps;
x = x0;
y = y0;
pDC->SetPixel((int)(x + 05) , (int)(y + 05), color);
for(int i = 0; i < steps; i++)
{
x += deltax;
y += deltay;
pDC->SetPixel((int)(x + 05), (int)(y + 05), color);
}
}
//preCondition:x0 < x1
void CDDALineView::MidpointLine(CDC pDC, int x0, int y0, int x1, int y1, COLORREF color)
{
int a = y0 - y1;
int b = x1 - x0;
int c = x0 y1 - x1 y0;
float d, d1, d2;
d = 2 a + b;
d1 = 2 a;
d2 = 2 (a + b);
int x = x0, y = y0;
pDC->SetPixel(x, y, color);
while(x < x1)
{
if(d < 0)
{
x++;
y++;
d+=d2;
}
else{
x++;
d+=d1;
}
pDC->SetPixel(x, y, color);
}
}
void CDDALineView::BresenhamLine(CDC pDC, int x0, int y0, int x1, int y1, COLORREF color)
{
int x, y, dx, dy;
dx = x1 - x0;
dy = y1 - y0;
float k = dy / dx;
x = x0;
y = y0;
float e = -05;
for(int i = 0; i <= dx; i++)
{
pDC->SetPixel(x, y, color);
x++;
e+=k;
if(e >= 0)
{
y++;
e-=1;
}
}
}
仅供参考
个人认为最关键的区别就是那个决策参数的计算方式!
在Bresenham算法中,假设我们在(x0,y0)处画了一个点,那我们就要决定下一个点是在(x0+1,y0)还是在(x0+1,y0+1)处画,这两个点一般都不在直线上,我们要计算这两个点离直线有多远,分别设两个点离直线的距离为p1、p2,然后决策参数就是p=p2-p1,再根据p的符号来判断选择哪个点
至于中点法,我没有用它来画过直线,只用来画过圆(自我感觉画圆用这个算法比Bresenham算法要好很多),但原理应该差不多!
在中点算法中,决策参数的就是方式就是圆的方程(换成直线就是直线的方程了),比如要画x^2+y^2=r^2的圆,那决策参数p=x^2+y^2-r^2,然后就不是代入上面找到的两个点直接代进去,而是代这两个点的中点进去,求出p的值,根据p的符号来判断那个中点是在圆上、圆内还是圆外,再进一步决定选择绘哪个点!
具体的计算过程没办法在这里完整演示,但个人认为不同之处还是在于决策参数的选择与计算
以上就是关于求计算机图形学中的直线绘制函数法、DDA算法、中点法和Bresenham算法的优缺点以及比较.全部的内容,包括:求计算机图形学中的直线绘制函数法、DDA算法、中点法和Bresenham算法的优缺点以及比较.、C++实现画图功能的程序 急啊!!!!!!!!!!!!!!、c++如何画直线等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)