用Bresenham算法画直线写名字

目录

1.基本原理

2.具体推导

3.用代码实现操作 


1.基本原理

        bresenham画线算法的基本原理是:若设p(x,y)是直线上的一点,与p点最近的网格为(xi,yi),那么,下一个与直线最近的像素只能是正右方的网格点S(xi+1,yi),或右上方的网格点T(xi+1,yi+1)。设直线与网格的交点为Q,令s=|QS|,t=|QT|,则有:

当s<t时,S比较靠近理想直线,应选为S。

当s>=t时,T比较靠近理想直线,应选T。

2.具体推导

        设直线段由P1(x1,y1)到Pn(xn,yn),则直线方程可以表示为

        y = kx + b

其中 k = (yn-y1)/(xn-x1) = dy/dx , b = y1-kx1

可知,S的坐标为(xi+1,yi),T的坐标为(xi+1,yi+1),因此

s = y-yi =k(xi+1)+b-yi

t = yi+1-y= yi+1-k(xi+1)-b

则有 s-t = 2k(xi+1)+2b-2yi-1

带入k= dy/dx

dx(s-t) = 2(xidy-yidx)+(2dy+2bdx-dx)

 因为dx>0,所以以dx(s-t)的正负作为选择S或T的依据,故可令di = dx(s-t)

di = 2(xidy-yidx)+(2dy+2bdx-dx)

将每一个下标加1,则有

di+1 = 2(xi+1dy-yi+1dx)+(2dy+2bdx-dx)

两式相减

di+1 = di+2dy(xi+1-xi)+2dx(yi+1-yi)

因为xi+1-xi = 1,所以

di+1 = di+2dy+2dx(yi+1-yi)

这样,就得到一个递推公式,下一个di+1可以由前一个di递推得到。

d>=0,即下一个应该选T,此刻yi+1-yi = 1,则

di+1 = di +2(dy-dx) 

d>=0,即下一个应该选S,此刻yi+1=yi 则 

di+1 = di+2dy

于是

d1 = 2dy-dx 

3.用代码实现操作 

        首先要用一个函数实现bresenham画图算法来画直线

void Bresenham(int x1,int y1,int x2,int y2){
	int dx =abs(x2-x1);
	int dy =abs(y2-y1);
	if(dx==0 && dy==0) return;
	int flag=0;
	if(dx<dy){
		flag = 1;
		swap(&x1,&y1);//这是一个交换函数,如果dy>dx那么交换x,y的坐标
		swap(&x2,&y2);//函数swap后续会详写
		swap(&dx,&dy);
	
	}
	int tx =(x2-x1)>0?1:-1;//这是判断x的画图方向
	int ty =(y2-y1)>0?1:-1;//这是判断y的画图方向
	int curx =x1;//定义一个当前的x和y
	int cury =y1;
	int d1=2*dy;
	int d2=2*(dy-dx);
	int d=d1-dx;
	while(curx!=x2){
	
	if(d<0){
			d+=d1;//用while函数计算点一直到点与目标点相同
		
		}
	else{
			cury+=ty;//如果d>0,那么y++
			d+=d2;
	
		
		}
	curx+=tx;
	if(flag)//根据之前判断dx与dy的大小,画图时要将xy的坐标换回来
	{	glPointSize(2);//定义线的大小
		glBegin(GL_POINTS);
		glVertex2f(cury/400.0,curx/400.0);//根据当前的点画线
		glColor3f(1.0f, 0.0f, 0.0f);//定义颜色为红色
		glEnd();
		glFlush();
	
	}
	else
	{	glPointSize(2);
		glBegin(GL_POINTS);
		glVertex2f(curx/400.0,cury/400.0);
		glColor3f(1.0f, 0.0f, 0.0f);
		glEnd();
		glFlush();
	
	}
	
	}


}

在dy>dx的时候要自己设定一个函数swap来交换x和y的坐标点

void swap(int *x,int *y){
	int temp = *x;
	*x = *y;
	*y = temp;
}

设定一个函数给出自己名字的点,根据这个点画图

void myDisplay(void){
	glClearColor(0.0, 0.0, 0.0, 0.0);//背景颜色
	glClear(GL_COLOR_BUFFER_BIT);//清空页面
	Bresenham(-100,50,-150,-30);
	Bresenham(-70,-50,80,-50);
	Bresenham(-70,-50,-70,10);
	Bresenham(45,0,10,20);//心
	Bresenham(120,-20,125,-80);
	Bresenham(-150,-150,100,-150);//一
	Bresenham(-75,400,-125,330);
	Bresenham(-50,400,-150,270);
	Bresenham(-100,320,-100,120);
	Bresenham(30,400,-50,270);
	Bresenham(30,400,110,270);
	Bresenham(-20,270,90,270);
	Bresenham(-30,230,100,230);
	Bresenham(35,270,35,120);
	Bresenham(35,120,15,150);
	Bresenham(-10,160,-30,120);
	Bresenham(80,160,100,120);//徐


}

最后用主函数实现画直线写名字

int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100,100);//窗口位置
glutInitWindowSize(400, 400);//窗口大小
glutCreateWindow("徐心一");//窗户名
glutDisplayFunc(&myDisplay);//调用函数
glutMainLoop();//一直循环刷帧
return 0;
}

下面是总体的效果

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值