分享
 
 
 

用C实现直线和圆的bressham算法

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

单看算法,不是很难,如果在256下,程序接口为直接输入数值的这种程序很好写,我希望自己能用C语言作出那种用鼠标绘制的效果.经过几个小时的看书和在网上搜集相关资料,终于实现了鼠绘直线的效果,然后再举一反三,圆的bressnham算法也很就容易的实现了.

基中算法思想的文档可以参考这里:

http://www.ekany.com/wdg98/cg/contents/chapter2/les212.htm

实现直线的bressnham算法的整个程序代码如下:

#include "stdio.h"

#include"dos.h"

#include"graphics.h"

#include"conio.h"

union REGS regs;

int X__max,Y__max,x_max,y_max,yn_first_point=0,f_x=0,f_y=0,c_x,c_y;

void Initgr(); /*屏幕初始化成图形模式*/

int Msinit(int Xlo,int Xhi,int Ylo,int Yhi);/*鼠标初始化*/

int Msread(int *px,int *py,int *pbuttons);/*读鼠标位置及状态*/

int Xpixel(int x);/*由象素坐标变换为屏幕坐标*/

int Ypixel(int y);/*由象素坐标变换为屏幕坐标*/

void Cursor(int x,int y); /*显示十字光标*/

int put_line(int x1,int y1,int x2,int y2,int color);/*bresenham直线生成*/

void iswap(int *a,int *b);/*交换数据*/

main()

{int buttons,X,Y,x,y,a,b;

char i;

Initgr();/*初始化图形屏幕*/

setcolor(EGA_LIGHTRED);/*设置屏幕前景色*/

setcolor(EGA_WHITE);

setwritemode(XOR_PUT);/*设置屏幕输出模式*/

Msinit(0,(int)x_max,0,(int)y_max);/*初始化鼠标*/

a=x_max;b=y_max;

x=0;

Cursor(a,b); /*在a=x_max;b=y_max;处画指针*/

while(x!=2)

{Msread(&X,&Y,&x);

Cursor(a,b); /*删除之前的鼠标,因为屏幕输出模式的关系*/

if(x==1){

if (yn_first_point==1)

{

put_line(Xpixel(f_x),Ypixel(f_y),Xpixel(c_x),Ypixel(c_y),4);

yn_first_point=0;

}

else

{

f_x=X;/* 保存第一点的坐标*/

f_y=Y;

yn_first_point=1;

}

} /*画点*/

if (yn_first_point==1 && x!=1 && x!=2)

{

put_line(Xpixel(f_x),Ypixel(f_y),Xpixel(c_x),Ypixel(c_y),0);

put_line(Xpixel(f_x),Ypixel(f_y),Xpixel(X),Ypixel(Y),2);

}

Cursor(X,Y);

a=X;b=Y;

c_x=X;c_y=Y;/*当前鼠标的坐标*/

}

Cursor(X,Y);/*再调用一次把原来的指针削掉*/

getch();

closegraph();

}

void Initgr(void) /*屏幕初始化成图形模式*/

{

int w,h,grdriver=DETECT,grmode;

initgraph(&grdriver,&grmode,"");/*在双引号中可加你tc放的路径,但要在tc里有EGAVGA.BGI这个来初始图形*/

if(graphresult())/*若调用不成功,退出*/

{printf("\n jkdjkj.\n");

exit(1);

}

X__max=getmaxx();/*求横向象点坐标数*/

Y__max=getmaxy();/*求纵向象点坐标数*/

getaspectratio(&w,&h);/*求纵横比*/

x_max=1000; /*设置屏幕坐标的宽度*/

y_max=x_max*(float)Y__max*h/((float)X__max*w);

}

int Msinit(int Xlo,int Xhi,int Ylo,int Yhi)/*鼠标初始化*/

{int retcode;

regs.x.ax=0;/*初始化鼠标*/

int86(0x33,&regs,&regs);

retcode=regs.x.ax;

if(retcode==0) return 0;

regs.x.ax=7;/*设置鼠标X方向的移动范围*/

regs.x.cx=Xlo;

regs.x.dx=Xhi;

int86(0x33,&regs,&regs);

regs.x.ax=8;/*设置鼠标Y方向的移动范围*/

regs.x.cx=Ylo;

regs.x.dx=Yhi;

int86(0x33,&regs,&regs);

regs.x.ax=15;/*设置mickey与象素的比,这各会影响鼠标移动速度*/

regs.x.cx=(int)(x_max/X__max);

regs.x.dx=(int)(y_max/Y__max);

int86(0x33,&regs,&regs);

return retcode;

}

int Msread(int *px,int *py,int *pbuttons)/*读鼠标位置及状态*/

{static int x0=320,y0=240,but0=0;

int xnew,ynew,ch;

do{

if(kbhit()){

ch=getch();

if(ch==13){

*pbuttons=1;

return -1;

}

else return ch; /*返回键盘输入*/

}

regs.x.ax=3; /*调用功能3,读鼠标位置及状态*/

int86(0x33,&regs,&regs);

xnew=regs.x.cx;/*返回鼠标当前的位置的X坐标*/

ynew=regs.x.dx;/*返回鼠标当前的位置的Y坐标*/

*pbuttons=regs.x.bx;/*返回鼠标当前的状态*/

}while(xnew==x0&&ynew==y0&&*pbuttons==but0);

/*当鼠标状态改变或位置改变终止循环*/

but0=*pbuttons;/*将鼠标状态保存到静态变量中*/

x0=xnew;y0=ynew;/*将鼠标位置保存到静态变量中*/

*px=xnew;*py=(int)(y_max-ynew);

return -1;

}

int Xpixel(int x)/*由象素坐标变换为屏幕坐标*/

{ return (int)((long)X__max*x/x_max);}

int Ypixel(int y)

{ return Y__max-(int)((long)Y__max*y/y_max);}

void Cursor(int x,int y) /*显示十字光标*/

{int X=Xpixel(x),Y=Ypixel(y),color;

char *str=" \0";

line(X-8,Y,X-3,Y);

line(X,Y-8,X,Y-4);

line(X+3,Y,X+8,Y);

line(X,Y+4,X,Y+8);

color=getcolor();

setcolor(BLACK);

outtextxy(X__max-100,10,str);/*删除前次显示值*/

sprintf(str,"%d,%d",x,y);

setcolor(WHITE);

outtextxy(X__max-100,10,str);/*在屏幕右上角显示当前光标的坐标*/

setcolor(color);

}

int put_line(int x1,int y1,int x2,int y2,int color)/*画直线函数*/

{

int curx,cury,tx,ty,inc1,inc2,d;

int dx,dy,itag;

if(x1==x2&y1==y2)return 1;

else

itag=0;

dx=abs(x2-x1);

dy=abs(y2-y1);

if(dx<dy)

{

itag=1;

iswap(&x1,&y1);

iswap(&x2,&y2);

iswap(&dx,&dy);

}

tx=(x2-x1)>0?1:-1;

ty=(y2-y1)>0?1:-1;

curx=x1;

cury=y1;

inc1=2*dy;

inc2=2*(dy-dx);

d=inc1-dx;

while(curx!=x2)

{

if(d<0)d+=inc1;

else

{

cury+=ty;

d+=inc2;

}

if(itag)

putpixel(cury,curx,color);

else

putpixel(curx,cury,color);

curx+=tx;

}

return 0;

}

void iswap(int *a,int *b)

{

int tmp;

tmp=*a;

*a=*b;

*b=tmp;

}



实现圆的bressnham算法的整个程序代码如下:

#include "stdio.h"

#include"dos.h"

#include"graphics.h"

#include"conio.h"

#include"math.h"

union REGS regs;

double X__max,Y__max,x_max,y_max,yn_first_point=0,f_x=0,f_y=0,c_x,c_y;

void Initgr(); /*屏幕初始化成图形模式*/

int Msinit(int Xlo,int Xhi,int Ylo,int Yhi);/*鼠标初始化*/

int Msread(int *px,int *py,int *pbuttons);/*读鼠标位置及状态*/

int Xpixel(int x);/*由象素坐标变换为屏幕坐标*/

int Ypixel(int y);/*由象素坐标变换为屏幕坐标*/

void Cursor(int x,int y); /*显示十字光标*/

void ff(int xc,int yc,int x,int y,int c); /*画点*/

void circlea(int xc,int yc,int radius,int c); /*用bresshuam算法画圆*/

main()

{int buttons,X,Y,x,y,a,b;

char i;

Initgr();/*初始化图形屏幕*/

setcolor(EGA_LIGHTRED);/*设置屏幕前景色*/

setcolor(EGA_WHITE);

setwritemode(XOR_PUT);/*设置屏幕输出模式*/

Msinit(0,(int)x_max,0,(int)y_max);/*初始化鼠标*/

a=x_max;b=y_max;

x=0;

Cursor(a,b); /*在a=x_max;b=y_max;处画指针*/

while(x!=2)

{Msread(&X,&Y,&x);

Cursor(a,b); /*删除之前的鼠标,因为屏幕输出模式的关系*/

if(x==1){

if (yn_first_point==1)

{

circlea(Xpixel(f_x),Ypixel(f_y),(int)sqrt((Xpixel(c_x)-Xpixel(f_x))*(Xpixel(c_x)-Xpixel(f_x))+(Ypixel(c_y)-Ypixel(f_y))*(Ypixel(c_y)-Ypixel(f_y))),4);

yn_first_point=0;

}

else

{

f_x=X;/* 保存第一点的坐标*/

f_y=Y;

yn_first_point=1;

}

}

if (yn_first_point==1 && x!=1 && x!=2)

{

circlea(Xpixel(f_x),Ypixel(f_y),(int)sqrt((Xpixel(c_x)-Xpixel(f_x))*(Xpixel(c_x)-Xpixel(f_x))+(Ypixel(c_y)-Ypixel(f_y))*(Ypixel(c_y)-Ypixel(f_y))),3);

}

Cursor(X,Y);

a=X;b=Y;

c_x=X;c_y=Y;/*当前鼠标的坐标*/

}

Cursor(X,Y);/*再调用一次把原来的指针削掉*/

getch();

closegraph();

}

void Initgr(void) /*屏幕初始化成图形模式*/

{

int w,h,grdriver=DETECT,grmode;

initgraph(&grdriver,&grmode,"");/*在双引号中可加你tc放的路径,但要在tc里有EGAVGA.BGI这个来初始图形*/

if(graphresult())/*若调用不成功,退出*/

{printf("\n jkdjkj.\n");

exit(1);

}

X__max=getmaxx();/*求横向象点坐标数*/

Y__max=getmaxy();/*求纵向象点坐标数*/

getaspectratio(&w,&h);/*求纵横比*/

x_max=1000; /*设置屏幕坐标的宽度*/

y_max=x_max*(float)Y__max*h/((float)X__max*w);

}

int Msinit(int Xlo,int Xhi,int Ylo,int Yhi)/*鼠标初始化*/

{int retcode;

regs.x.ax=0;/*初始化鼠标*/

int86(0x33,&regs,&regs);

retcode=regs.x.ax;

if(retcode==0) return 0;

regs.x.ax=7;/*设置鼠标X方向的移动范围*/

regs.x.cx=Xlo;

regs.x.dx=Xhi;

int86(0x33,&regs,&regs);

regs.x.ax=8;/*设置鼠标Y方向的移动范围*/

regs.x.cx=Ylo;

regs.x.dx=Yhi;

int86(0x33,&regs,&regs);

regs.x.ax=15;/*设置mickey与象素的比,这各会影响鼠标移动速度*/

regs.x.cx=(int)(x_max/X__max);

regs.x.dx=(int)(y_max/Y__max);

int86(0x33,&regs,&regs);

return retcode;

}

int Msread(int *px,int *py,int *pbuttons)/*读鼠标位置及状态*/

{static int x0=320,y0=240,but0=0;

int xnew,ynew,ch;

do{

if(kbhit()){

ch=getch();

if(ch==13){

*pbuttons=1;

return -1;

}

else return ch; /*返回键盘输入*/

}

regs.x.ax=3; /*调用功能3,读鼠标位置及状态*/

int86(0x33,&regs,&regs);

xnew=regs.x.cx;/*返回鼠标当前的位置的X坐标*/

ynew=regs.x.dx;/*返回鼠标当前的位置的Y坐标*/

*pbuttons=regs.x.bx;/*返回鼠标当前的状态*/

}while(xnew==x0&&ynew==y0&&*pbuttons==but0);

/*当鼠标状态改变或位置改变终止循环*/

but0=*pbuttons;/*将鼠标状态保存到静态变量中*/

x0=xnew;y0=ynew;/*将鼠标位置保存到静态变量中*/

*px=xnew;*py=(int)(y_max-ynew);

return -1;

}

int Xpixel(int x)/*由象素坐标变换为屏幕坐标*/

{ return (int)((long)X__max*x/x_max);}

int Ypixel(int y)

{ return Y__max-(int)((long)Y__max*y/y_max);}

void Cursor(int x,int y) /*显示十字光标*/

{int X=Xpixel(x),Y=Ypixel(y),color;

char *str=" \0";

line(X-8,Y,X-3,Y);

line(X,Y-8,X,Y-4);

line(X+3,Y,X+8,Y);

line(X,Y+4,X,Y+8);

color=getcolor();

setcolor(BLACK);

outtextxy(X__max-100,10,str);/*删除前次显示值*/

sprintf(str,"%d,%d",x,y);

setcolor(WHITE);

outtextxy(X__max-100,10,str);/*在屏幕右上角显示当前光标的坐标*/

setcolor(color);

}

void ff(int xc,int yc,int x,int y,int c)

{

putpixel(xc+x,yc+y,c);

putpixel(xc-x,yc+y,c);

putpixel(xc+x,yc-y,c);

putpixel(xc-x,yc-y,c);

putpixel(xc+y,yc+x,c);

putpixel(xc-y,yc+x,c);

putpixel(xc+y,yc-x,c);

putpixel(xc-y,yc-x,c);

}

void circlea(int xc,int yc,int radius,int c)

{int x,y,p;

x=0;

y=radius;

p=3-2*radius;

while (x<y)

{ff(xc,yc,x,y,c);

if (p<0)

p=p+4*x+6;

else

{p=p+4*(x-y)+10;

y-=1;

}

x+=1;

}

if (x==y)

ff(xc,yc,x,y,c);

}

基中在运行圆的算法时,开始是很正常,过了一会儿,提示sqrt domain error.我还没弄懂.不知道是怎么一回事,有时间再请教别人.星期六要软考了.汗~我得赶快去看书.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有