案例2-直线中点Bresenham算法
中点bresenham算法过程
中点Bresenham算法是一种用于计算在直线上的格点的算法。
它是由Bresenham在1965年提出的,是一种高效的计算机图形学算法,通常用于直线、圆、椭圆等形状的绘制。
通过这篇文章,我们将详细介绍中点Bresenham算法的过程。
1. 背景知识在计算机图形学中,我们经常需要在屏幕上绘制直线、圆、椭圆等形状。
而计算机屏幕上的图像是由像素组成的,因此我们需要一种算法来计算出这些形状上的像素坐标,从而进行绘制。
中点Bresenham算法就是用来解决这个问题的。
2. 中点Bresenham算法的原理中点Bresenham算法的原理是通过巧妙的数学推导,找到离直线最近的像素点,从而确定需要绘制的像素坐标。
该算法通过利用误差项来判断下一个像素点的位置,具有高效、简洁的特点。
3. 中点Bresenham算法的过程中点Bresenham算法的过程可以分为以下几个步骤:3.1 初始化变量:首先需要确定直线的起点和终点,并初始化相关变量,如起点坐标(x0, y0)、终点坐标(x1, y1)、误差项d和增量变化量dx、dy等。
3.2 计算斜率k和误差项初始值:通过计算直线的斜率k,并根据斜率确定误差项的初始值。
3.3 循环计算像素点的坐标:根据误差项的大小,确定下一个像素点的位置,并更新误差项的值,直到绘制完整条直线。
4. 中点Bresenham算法的优势* 算法简洁高效:中点Bresenham算法通过简单的数学计算,即可确定直线上的像素坐标,避免了直接计算斜率导致的浮点数运算,因此在计算速度上具有较大优势。
* 适用范围广泛:中点Bresenham算法不仅适用于直线,还可以用于绘制圆、椭圆等图形,具有良好的通用性。
5. 中点Bresenham算法的应用中点Bresenham算法广泛应用于计算机图形学中的直线、圆、椭圆等图形的绘制。
其高效、简洁的特点使得它成为了计算机图形学中不可或缺的算法之一。
中点Bresenham算法是计算机图形学中的重要算法之一,通过巧妙的数学计算,实现了高效、简洁的直线绘制。
改进的Bresenham算法
改进的Bresenham算法这里不仔细讲原理,只是把我写的算法发出来,跟大家分享下,如果有错误的话,还请大家告诉我,如果写的不好,也请指出来,一起讨论进步。
算法步骤:(1)输入直线的两端点P0(x0,y0)和P1(x1,y1)。
(2)计算初始值dx,dy,e=-dx,x=x0,y=y0。
(3)绘制点(x,y)。
(4)e更新为e+2*dy。
判断e的符号,若e 0,则(x,y)更新为(x+1,y+1),同时将e更新为e-2*dx;否则(x,y)更新为(x+1,y)。
(5)当直线没有画完时,重复步骤(3)和(4)否则结束。
水平、垂直和|k|=1的直线可以直接装入帧缓冲存储器面无须进行画线算法处理。
下面是我的算法,如有错误请指出。
#include GL/freeglut.h voidinit(void){glClearColor(0.0f,0.0f,0.0f,1.0f);}void drawLine(intx1,int y1,int x2,int y2){int x,y,dx,dy,e;//k does not existif(x1==x2){if(y1 y2){y=y1;glBegin(GL_POINTS);while(y=y2){glVertex2i(x1,y);++y;}glEnd();}//if(y1 y2)else{y=y2;glBegin(GL_POINTS);while(y=y1){glVertex2i(x1,y);++y;}glEnd();}}//if(x1==x2)else if(y1==y2)//k=0{if(x1 x2){x=x1;glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y1);++x;}glEnd();}//if(x1 x2)else{x=x2;glBegin(GL_POINTS);while(x=x1){glVertex2i(x,y1);++x;}glEnd();}}else{if(x1 x2){int temp=x1;x1=x2;x2=temp;temp=y1;y1=y2;y2=temp;}x=x1;y=y1;dx=x2-x1;dy=y2-y1;//k=1 if(dx==dy){glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y);++x;++y;}glEnd();}else if(dx==-dy)//k=-1{glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y);++x;--y;}glEnd();}else if(dy dx)//k 1{glBegin(GL_POINTS);dx=1;e=-dy;dy=1;y=y1 y2?y2:y1;int maxY=y1 y2?y1:y2;while(y=maxY){glVertex2i(x,y);++y;e+=dx;if(e 0){++x;e-=dy;}}glEnd();}else if(dy 0)//0 k1{e=-dx;dx=1;dy=1;glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y);++x;e+=dy;if(e0){e-=dx;++y;}}glEnd();}else if(-dy dx)//0 k-1{e=-dx;dx=1;dy=1;glBegin(GL_POINTS);while(x=x2){glVertex2i(x,y);++x;e+=dy;if(e0){--y;e+=dx;}}glEnd();}else if(-dy dx)//k-1{e=dy;dx=1;dy=1;glBegin(GL_POINTS);y=y1 y2?y1:y2;int minY=y1 y2?y2:y1;while(y=minY){glVertex2i(x,y);--y;e+=dx;if(e 0){++x;e+=dy;}}glEnd();}}}void display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0f,0.0f,0.0f);//Vertical line drawLine(0,-200,0,200);//Horizontal line drawLine(-200,0,200,0);//k=1 line drawLine(-200,-200,200,200);//k=-1 line drawLine(-200,200,200,-200);//k=1/2 line drawLine(200,100,-200,-100);//k=2 line drawLine(-100,-200,100,200);//k=-1/2 line drawLine(-200,100,200,-100);//k=-2 line drawLine(-100,200,100,-200);drawLine(30,120,10,70);drawLine(10,70,30,10);drawLine(30,10,60,50);drawLine(60,50,80,10);drawLine(80,10,120,80);drawLine(120,80,70,80);drawLine(70,80,30,120);glutSwapBuffers();}void reshape(int w,inth){glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if(w=h){gluOrtho2D(-600.0,600.0,-600.0*(GLfloat)h/(GLfloat)w,600.0*(GLfloat)h/(GLfloat)w);}else{gluOr tho2D(-600.0*(GLfloat)w/(GLfloat)h,600.0*(GLfloat)w/(GLfloat)h,-600.0,600.0);}glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void keyboard(unsigned char key,int x,int y){switch(key){case 27://'VK_ESCAPE'exit(0);break;default:break;}}int main(intargc,char*argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);glutInitWindowSize(600,600);glutCreateWindow("optimized Bresenhamline");init();glutReshapeFunc(reshape);glutDisplayFunc(display);glutKeyboardFunc(keyboard);glutMainLoop();return 0;}作者:断桥&残雪发表于2010-12-04 20:29原文链接评论:0查看评论发表评论最新新闻:·马云:B2C创业者别埋怨淘宝不会停下来等你(2010-12-04 20:17)·Chrome to WP7手机端应用程序已经通过审核,可以下载了(2010-12-04 20:00)·盘点网络犯罪与信息战风云30年(2010-12-04 18:06)·网易邮箱:推出简历中心(2010-12-04 18:03)·马云:互联网三座大山将败给创新型小网站(2010-12-04 17:33)编辑推荐:"博客无双"活动:写博客、攒园豆、赢大奖网站导航:博客园首页我的园子新闻闪存小组博问知识库。
bresenham算法实现直线段插值函数
在计算机图形学中,Bresenham算法是一种用于在离散坐标系上绘制直线段的算法。
它是一种高效的算法,能够准确地计算出直线段上的所有像素点,使得在计算机屏幕上显示出直线段来。
Bresenham算法的实现可以帮助我们更好地理解画线原理,并且在计算机视觉、图像处理等领域有着广泛的应用。
1. Bresenham算法的原理Bresenham算法是通过计算直线段的斜率来确定每个像素点的位置。
具体来说,它利用了直线的对称性和整数的特性,通过计算像素点与真实直线的距离来判断下一个像素点应该取的位置。
这样可以避免使用浮点运算,使得算法更加高效。
2. 实现Bresenham算法的关键步骤在实现Bresenham算法时,需要考虑以下几个关键步骤:- 初始化各个变量,包括起始点(x0, y0)和终点(x1, y1),以及斜率的计算值,例如dx和dy。
- 根据斜率的正负情况,确定每个像素点的增量步长,以便在遍历过程中准确计算出像素点来。
- 利用对称性和整数特性,进行迭代计算,逐步确定直线段上的所有像素点的位置。
3. Bresenham算法的优缺点Bresenham算法作为一种离散直线段插值算法,具有以下几个优点:- 算法简单高效,节省存储空间和运算时间。
- 可以高效地解决像素化显示问题,避免了浮点运算的复杂性。
- 在硬件上实现时,只需少量的资源就能完成计算,适合嵌入式系统和图形处理器。
然而,Bresenham算法也存在一些缺点,比如对于曲线的绘制就不太奏效,因为它是基于直线段的形式来处理的。
4. 我对Bresenham算法的理解在我看来,Bresenham算法是一种经典的离散直线段插值算法,其思想简洁高效。
它通过逐步迭代的方式,计算出直线段上的所有像素点位置,使得在计算机屏幕上显示出直线段来更加精确。
这种算法的实现可以帮助我们更好地理解画线的原理,对于理解计算机图形学和计算机视觉都有着重要的意义。
总结起来,Bresenham算法作为一种高效的离散直线段插值算法,具有着重要的理论和实际价值。
直线的Bresenham算法
直线的Bresenham算法本算法由Bresenham在1965年提出。
设直线从起点(x1, y1)到终点(x2, y2)。
直线可表示为方程y=mx+b。
其中b = y1 - m * x1,我们的讨论先将直线方向限于1a象限(图2.1.1)在这种情况下,当直线光栅化时,x每次都增加1个单元,即xi+1=xi+1而y的相应增加应当小于1。
为了光栅化,yi+1只可能选择如下两种位置之一(图2.1.2)。
图2.1.2 yi+1的位置选择yi-1=yi 或者yi+1=yi+1选择的原则是看精确值y与yi及yi+1的距离d1及d2的大小而定。
计算式为:y=m(xi+1)+b (2.1.1)d1=y-yi (2.1.2)d2=yi+1-y (2.1.3)如果d1-d2>0,则yi+1=yi+1,否则yi+1=yi。
因此算法的关键在于简便地求出d1-d2的符号。
将式(2.1.1)、(2.1.2)、(2.1.3)代入d1-d2,得用dx乘等式两边,并以Pi=dx(d1-d2)代入上述等式,得Pi=2xidy-2yidx+2dy+dx(2b-1) (2.1.4)d1-d2是我们用以判断符号的误差。
由于在1a象限,dx总大于0,所以Pi仍旧可以用作判断符号的误差。
Pi+1为:Pi+1=Pi+2dy-2dx(yi+1-yi) (2.1.5)误差的初值P1,可将x1, y1,和b代入式(2.1.4)中的xi, yi而得到:P1=2dy-dx综述上面的推导,第1a象限内的直线Bresenham算法思想如下:1、画点(x1, y2); dx=x2-x1; dy=y2-y1;计算误差初值P1=2dy-dx; i=1;2、求直线的下一点位置:xi+1=xi+1;if Pi>0 则yi+1=yi+1;否则yi+1=yi;3、画点(xi+1, yi-1);4、求下一个误差Pi+1;if Pi>0 则Pi+1=Pi+2dy-2dx;否则Pi+1=Pi+2dy;5、i=i+1; if i<dx+1则转2;否则end。
像素画圆算法范文
像素画圆算法范文一、引言像素画圆算法是一种用于计算机图形学中绘制圆的常用算法。
在计算机图形学中,圆是一个非常基本的图形元素,无论是在2D还是3D图形中,圆都是最直观的图形之一、因此,能够高效绘制圆形对于计算机图形学来说是非常重要的。
在本篇文章中,我们将介绍两种常用的像素画圆算法:Bresenham算法和中点画圆算法。
这两种算法都是基于直线绘制算法的思想发展而来,通过巧妙的数学推导,将直线绘制算法应用到圆形的绘制过程中。
二、Bresenham算法Bresenham算法是一种经典的像素画圆算法,它是由Jack E. Bresenham于1962年发明的。
该算法通过计算以像素为单位的数学判定来绘制圆形。
该算法的基本思想是,对于给定的圆心坐标和半径长度,我们从一个点开始,根据圆的对称性,计算出其他8个对称特殊点的坐标,并选择最接近圆的边缘的点绘制。
接着,根据选择的点计算下一个边缘点,并反复迭代这一过程,直到找到了整个圆的边缘点。
具体的Bresenham算法如下:1.初始化半径r和圆心坐标(x,y);2.设置两个变量x1和y1分别为0和r;3.计算判别式d=3-2*r;4.在每次迭代中,绘制八个对称点中最接近圆边缘的点,并更新判别式d和坐标x和y的值:-如果d<0,选择右偏移的点(x+1,y),d的值不变;-如果d>=0,选择右上偏移的点(x+1,y+1),d的值减去Δd;-更新判别式d=d+4*x+6;5.重复步骤4,直到x>y。
这里的Δd是一个关于x和y的常数,它的值预先计算得出,使得可以在循环中快速计算判别式d的变化。
通过这种方式,Bresenham算法能够高效地计算出整个圆的边缘点,从而实现圆形的绘制。
三、中点画圆算法中点画圆算法(Midpoint Circle Drawing Algorithm)是另一种常用的像素画圆算法,它是由Jack E. Bresenham于1977年发展而来的。
Bresenham快速画直线算法
Bresenham快速画直线算法 现在的计算机的图像的都是⽤像素表⽰的,⽆论是点、直线、圆或其他图形最终都会以点的形式显⽰。
⼈们看到屏幕的直线只不过是模拟出来的,⼈眼不能分辨出来⽽已。
那么计算机是如何画直线的呢,其实有⽐较多的算法,这⾥讲的是Bresenham的算法,是光栅化的画直线算法。
直线光栅化是指⽤像素点来模拟直线,⽐如下图⽤蓝⾊的像素点来模拟红⾊的直线。
给定两个点起点P1(x1, y1), P2(x2, y2),如何画它们直连的直线呢,即是如何得到上图所⽰的蓝⾊的点。
假设直线的斜率0<k>0,直线在第⼀象限,Bresenham算法的过程如下:1.画起点(x1, y1).2.准备画下⼀个点,X坐标加1,判断如果达到终点,则完成。
否则找下⼀个点,由图可知要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点。
2.1.如果线段ax+by+c=0与x=x1+1的交点y坐标⼤于(y+*y+1))/2则选右上那个点 2.2.否则选右下那个点。
3.画点4.跳回第2步5.结束 算法的具体过程是怎样的呢,其实就是在每次画点的时候选取与实现直线的交点y坐标的差最⼩的那个点,例如下图:关键是如何找最近的点,每次x都递增1,y则增1或者不增1,由上图,假设已经画了d1点,那么接下来x加1,但是选d2 还是u点呢,直观上可以知道d2与⽬标直线和x+1直线的交点⽐较近即纵坐标之差⼩也即与(x+1, y+1)点纵坐标差⼤于0.5,所当然是选d2,其他点了是这个道理。
⼀、算法原理简介:算法原理的详细描述及部分实现可参考:假设以(x, y)为绘制起点,⼀般情况下的直观想法是先求m = dy /dx(即x每增加1, y的增量),然后逐步递增x, 设新的点为x1 = x + j,则y1 = round(y + j * m)。
可以看到,这个过程涉及⼤量的浮点运算,效率上是⽐较低的(特别是在嵌⼊式应⽤中,DSP可以⼀周期内完成2次乘法,⼀次浮点却要上百个周期)。
Bresenham画直线算法
Bresenham画直线算法发表于:03-28 20:23 | 分类:代码阅读:(4) 评论:(0)给定两个点起点P1(x1, y1), P2(x2, y2),如何画它们直连的直线呢,即是如何得到上图所示的蓝色的点。
假设直线的斜率0<k>0,直线在第一象限,Bresenham算法的过程如下:1.画起点(x1, y1).2.准备画下一个点,X坐标加1,判断如果达到终点,则完成。
否则找下一个点,由图可知要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点。
2.1.如果线段ax+by+c=0与x=x1+1的交点y坐标大于(y+*y+1))/2则选右上那个点2.2.否则选右下那个点。
3.画点4.跳回第2步5.结束具体的算法如下,原理就是比较目标直线与x+1直线交点的纵坐标,哪个离交点近就去哪个void Bresenhamline(int x0, int y0, int x1, int y1, int color){int x, y, dx, dy;float k, e;dx = x1 - x0;dy = y1 - y0;k = dy / dx;e = -0.5;x = x0;y = y0;for (x= x0;x < x1; x++){drawpixel(x, y, color);//这个是画点子函数e = e + k;if (e > 0){y++;e = e - 1;}}}上述Bresenham算法在计算直线斜率与误差项时用到小数与除法。
可以改用整数以避免除法。
等式两边同时乘以2*dx,得到2*e*dx = 2*e*dx + 2dy, 2*e*dx = 2*e*dx - 2*dx.由于算法中只用到误差项的符号,因此可作如下替换:2*e*dx.改进的Bresenham画线算法程序:将e统一乘以2*dx即变成了整数的Bresenhan算法了,^_^void InterBresenhamline (int x0, int y0, int x1, int y1, int color){int dx = x1 - x0;int dy = y1 - y0;int dx2 = dx << 1;//乘2int dy2 = dy << 1;//乘2int e = -dx;int x = x0;int y = y0;for (x = x0; x < x1; x++){drawpixel (x, y, color);e=e + dy2;if (e > 0){y++;e = e - dx2;}}}其他象限或斜率不同可以转换一下位置即可,这里不具体展开。
Bresenham算法
Bresenham算法1 算法原理基本原理从某处摘得:设直线⽅程为y i+1=y i+k(x i+1-x i)+k。
假设列坐标象素已经确定为x i,其⾏坐标为y i。
那么下⼀个象素的列坐标为x i+1,⽽⾏坐标要么为y i,要么递增1为y i+1。
是否增1取决于误差项d的值。
误差项d的初值d0=0,x坐标每增加1,d的值相应递增直线的斜率值k,即d=d+k。
⼀旦d≥1,就把它减去1,这样保证d在0、1之间。
当d≥0.5时,直线与垂线x=x i+1交点最接近于当前象素(x i,y i)的右上⽅象素(x i+1,y i+1);⽽当d<0.5时,更接近于右⽅象素(x i+1,y i)。
为⽅便计算,令e=d-0.5,e的初值为-0.5,增量为k。
当e≥0时,取当前象素(x i,y i)的右上⽅象素(x i+1,y i+1);⽽当e<0时,取(x i,y i)右⽅象素(x i+1,y i)。
由于显⽰直线的像素点只能取整数值坐标,可以假设直线上第i个像素点的坐标为(X i,Y i),它是直线上点(X i,Y i)最佳近似,并且X i=X i(假设m<1),如下图所⽰.那么直线上下⼀个像素点的可能位置是(X i+1,Y i)或者(X i+1,Y i+1).由图可知:在x=X i+1处,直线上的点y的值是:y=m(X i+1)+b,该点离像素点(X i+1,Y i)和像素点(X i+1,Y i+1)的距离分别为d1和d2。
d1 = Y - Y i = m(X i+1)+b - Y i; (1) d2 = (Y i+1) - Y = (Y i+1) - m(X i+1) - b; (2) 两个距离的差是: d1-d2 = 2m(X i+1) - 2Y i + 2b -1; (3) 对于公式(3): a:当此值为正时,d1>d2,说明直线上理论点离(X i+1,Y i+1)像素较近,下⼀个像素点应取(X i+1,Y i+1); b:当此值为负时,d1<d2,说明直线上理论点离(X i+1,Y i)像素较近,下⼀个像素点赢取(X i+1,Y i); c:当此值为零时,d1=d2,说明直线上理论点离上、下两个像素点的距离相等,取那个点都⾏,假设算法规定这种情况下取(X i+1,Y i+1)作为下⼀个像素点。
Bresenham算法-直线光栅化算法
Bresenham算法是计算机图形学典型的直线光栅化算法。
∙从另一个角度看直线光栅化显示算法的原理o由直线的斜率确定选择在x方向或y方向上每次递增(减)1个单位,另一变量的递增(减)量为0或1,它取决于实际直线与最近光栅网格点的距离,这个距离的最大误差为0.5。
∙1)Bresenham的基本原理o假定直线斜率k在0~1之间。
此时,只需考虑x方向每次递增1个单位,决定y方向每次递增0或1。
设直线当前点为(xi,y)直线当前光栅点为(xi,yi)则下一个直线的点应为(xi+1,y+k)下一个直线的光栅点或为右光栅点(xi+1,yi)(y方向递增量0)或为右上光栅点(xi+1,yi+1)(y方向递增量1)记直线与它垂直方向最近的下光栅点的误差为d,有:d=(y+k)–yi,且0≤d≤1当d<0.5:下一个象素应取右光栅点(xi+1,yi)当d≥0.5:下一个象素应取右上光栅点(xi+1,yi+1)如果直线的(起)端点在整数点上,误差项d的初值:d0=0,x坐标每增加1,d的值相应递增直线的斜率值k,即:d=d + k。
一旦d≥1,就把它减去1,保证d的相对性,且在0-1之间。
令e=d-0.5,关于d的判别式和初值可简化成:e的初值e0= -0.5,增量亦为k;e<0时,取当前象素(xi,yi)的右方象素(xi+1,yi);e>0时,取当前象素(xi,yi)的右上方象素(xi+1,yi+1);e=0时,可任取上、下光栅点显示。
Bresenham算法的构思巧妙:它引入动态误差e,当x方向每次递增1个单位,可根据e 的符号决定y方向每次递增 0 或 1。
e<0,y方向不递增e>0,y方向递增1x方向每次递增1个单位,e = e + k因为e是相对量,所以当e>0时,表明e的计值将进入下一个参考点(上升一个光栅点),此时须:e = e - 1∙2)Bresenham算法的实施——Rogers 版o通过(0,0)的所求直线的斜率大于0.5,它与x=1直线的交点离y=1直线较近,离y=0直线较远,因此取光栅点(1,1)比(1,0)更逼近直线;o如果斜率小于0.5,则反之;o当斜率等于0.5,没有确定的选择标准,但本算法选择(1,1)(程序)▪//Bresenham's line resterization algorithm for the first octal.▪//The line end points are (xs,ys) and (xe,ye) assumed not equal.▪// Round is the integer function.▪// x,y, ∆x, ∆y are the integer, Error is the real.▪//initialize variables▪x=xs▪y=ys▪∆x = xe -xs▪∆y = ye -ys▪//initialize e to compensate for a nonzero intercept▪Error =∆y/∆x-0.5▪//begin the main loop▪for i=1 to ∆x▪ WritePixel (x, y, value)▪if (Error ≥0) then▪ y=y+1▪ Error = Error -1▪ end if▪ x=x+1▪ Error = Error +∆y/∆x▪next i▪finish∙3)整数Bresenham算法o上述Bresenham算法在计算直线斜率和误差项时要用到浮点运算和除法,采用整数算术运算和避免除法可以加快算法的速度。
Bresenham算法
2.1.2 生成直线的B resenham算法从上面介绍的DDA算法可以看到,由于在循环中涉及实型数据的加减运算,因此直线的生成速度较慢。
在生成直线的算法中,B resenham算法是最有效的算法之一。
B resenham算法是一种基于误差判别式来生成直线的方法。
一、直线Bresenham算法描述:它也是采用递推步进的办法,令每次最大变化方向的坐标步进一个象素,同时另一个方向的坐标依据误差判别式的符号来决定是否也要步进一个象素。
我们首先讨论m=△y/△x,当0≤m≤1且x1<x2时的B resenham算法。
从DDA直线算法可知这些条件成立时,公式(2-2)、(2-3)可写成:x i+1=x i+1 (2-6)y i+1=y i+m(2-7)有两种B resenham算法思想,它们各自从不同角度介绍了B resenham算法思想,得出的误差判别式都是一样的。
二、直线B resenham算法思想之一:由于显示直线的象素点只能取整数值坐标,可以假设直线上第i个象素点坐标为(x i,y i),它是直线上点(x i,y i)的最佳近似,并且x i=x i(假设m<1),如下图所示。
那么,直线上下一个象素点的可能位置是(x i+1,y i)或(x i+1,y i+1)。
由图中可以知道,在x=x i+1处,直线上点的y值是y=m(x i+1)+b,该点离象素点(x i+1,y i)和象素点(x i+1,y i+1)的距离分别是d1和d2:d1=y-y i=m(x i+1)+b-y i(2-8)d2=(y i+1)-y=(y i+1)-m(x i+1)-b (2-9)这两个距离差是我们来分析公式(2-10):(1)当此值为正时,d1>d2,说明直线上理论点离(x i+1,y i+1)象素较近,下一个象素点应取(x i+1,y i+1)。
(2)当此值为负时,d1<d2,说明直线上理论点离(x i+1,y i)象素较近,则下一个象素点应取(x i+1,y i)。
直线的中点Bresenham算法
直线的中点Bresenham算法作者:王芳,王正兰来源:《电脑知识与技术》2011年第04期摘要:直线Bresenham算法的基本原理是采取对整型参量的符号进行检测,整型参量的值正比于两像素与实际线段之间的偏移。
直线的中点Bresenham算法是依据下一个点可能出现的两个点的中间点处在直线的位置来判断下一个点的取舍。
关键词:Bresenham算法;斜率;误差项中图分类号:TP312文献标识码:A文章编号:1009-3044(2011)04-0825-02The Bresenham Algorithm of Center Point of Straight LineWANG Fang, WANG Zheng-lan(Commanding Institute of Engineer Corps, Xuzhou 221004, China)Abstract: The basic principle of the Bresenham algorithm of center point of straight line Adopts carries on the examination to the trueing parameter mark, the trueing parameter value is in proportion to two picture elements and actual line segment displacements. The Bresenham algorithm of center point of the straight line is two spot intermediate points which the basis next spot possibly appears occupies the straight line position judgment next spot choices.Key words: Bresenham algorithm; slope; error term1 直线Bresenham算法设直线从起点(x1,y1)到终点(x2,y2)。
计算机图形学实验Bresenham算法
根据理想直线的斜率k,除垂线外(k=±∞)将直线划分为k>1、0≤k≤1、-1≤k<0和k<-1四种情况。当0≤k≤1时或-1≤k<0时,x方向为主位移方向;当k>1时或k<-1时,y方向为主位移方向。对于|k|=∞的垂线,可以直接画出。
具体算法:
1.确定主位移方向。在主位移方向上每次加1,另一个方向上加不加1,取决于中点误差项。
if(y0>y1)
{
double tx=x0;
double ty=y0;
x0=x1;y0=y1;
x1=tx;
y1=ty;
}
x=x0;y=y0;
d=1-0.5*k;
for(y=y0;y<=y1;y++)
{
dc.SetPixel(ROUND(x),ROUND(y),rgb);
if(d>=0)
{
x++;
d+=1-k;
}
else
d+=1;
}
}
if(k<-1)
{
if(y0<y1)
{
double tx=x0;
double ty=y0;
x0=x1;y0=y1;
x1=tx;
y1=ty;;
for(y=y0;y>y1;y--)
{
dc.SetPixel(ROUND(x),ROUND(y),rgb);
if(d>0)
{
y--;
d-=1+k;
}
else
d-=k;
}
}
if(fabs(x0-x1)<1e-6)
{
if(y0>y1){
double tx=x0;
中点bresenham算法的基本原理与递推公式
中点Bresenham算法是一种用于绘制直线的光栅化算法,它可以在计算机图形学中高效地绘制直线,尤其适用于嵌入式系统和低性能设备。
本文将介绍中点Bresenham算法的基本原理和递推公式。
一、中点Bresenham算法的基本原理1.1 数值方式直线的差值算法在了解中点Bresenham算法之前,我们需要先了解数值方式直线的差值算法。
通过计算两个端点的坐标差值,可以得到直线的斜率和步长,从而在光栅化的像素网格上绘制直线。
然而,这种算法需要进行浮点数运算,对于嵌入式系统和低性能设备来说,性能较差。
1.2 中点Bresenham算法的优势中点Bresenham算法通过整数运算和递推公式来高效地绘制直线,避免了浮点数运算的开销,因此在嵌入式系统和低性能设备上具有很高的应用价值。
它利用了直线的对称性和整数坐标的特点,通过逐个像素的递推计算来实现直线的绘制。
1.3 算法的基本思想中点Bresenham算法的基本思想是从直线的起点到终点,在每一步选择最接近直线的像素作为下一个像素,从而逐步绘制整条直线。
通过比较像素的位置和理想直线的位置关系,选择最接近直线的像素进行绘制,从而得到了中点Bresenham算法的递推过程。
二、中点Bresenham算法的递推公式2.1 直线斜率的计算我们需要计算直线的斜率m。
对于给定的两个端点P1(x1, y1)和P2(x2, y2),直线的斜率可以通过以下公式计算得到:m = (y2 - y1) / (x2 - x1)2.2 中点Bresenham算法的关键递推公式中点Bresenham算法通过比较像素的位置和理想直线的位置关系,选择最接近直线的像素进行绘制。
其关键递推公式如下:对于斜率0 ≤ m ≤ 1的直线:d = 2 * (y - y0) - (x - x0)若d < 0,则选择(x, y)为下一个像素,d = d + 2 * (y1 - y0)若d ≥ 0,则选择(x, y)为下一个像素,d = d + 2 * (y1 - y0) - 2 * (x1 - x0)对于斜率m > 1的直线:d = 2 * (x - x0) - (y - y0)若d < 0,则选择(x, y)为下一个像素,d = d + 2 * (x1 - x0)若d ≥ 0,则选择(x, y)为下一个像素,d = d + 2 * (x1 - x0) - 2 * (y1 - y0)2.3 递推过程通过以上递推公式,我们可以在每一步选择最接近直线的像素进行绘制,从而逐步绘制整条直线。
详解直线扫描算法之---bresenham改进算法(任何斜率,任何方向)
先标明这转载自/xxxxxx91116/article/details/6295714直线扫描算法之---bresenham改进算法(任何斜率,任何方向)by zxx图形学神马的全都是数学,看来以后我不能搞这个,伤脑筋,所以先把我现在懂得先记录下来吧。
不过呢,我的水平实在有限,对于算法这种东西实在难以说明白,请大家包涵。
书上讲的实在是太过简略,所以这里我把一些简单的推导过程都记录下来:1.重温bresenham未改进算法(斜率在0-1之间的直线)我想要记录的是bresenham改进算法,所以在讲解改进算法之前,我先用一个简单的例子说明一下未改进算法的思想:这是一个斜率k在0-1之间的一条直线,我就用斜率为0-1之间的直线来重温:首先,如图1所示,假设x列的像素已定,其坐标为(x,y),那么下一个坐标一定是:(x+1,y+1)或者(x+1,y)。
而是哪一个取决于d的值,如果d>0.5那么就是(x+1,y+1),如果d<0.5,那么就是(x+1,y),而d是什么呢?当然是斜率了。
(原因如下:y=kx+b当x增加1时:y=kx+k+b所以当x增加1是,y方向的增量是d。
)所以每次我们只需要让d=d+k(k是斜率)即可,当d>=1时,就让d减一,这样就保证了d在0-1之间。
当d>0.5,下一个点取(x+1,y+1)当d<0.5,下一个点取(x+1,y)然后呢,我们为了判断的方便,让e=d-0.5,这样就变成了:当e>0,下一个点取(x+1,y+1)当e<0,下一个点取(x+1,y)2.过渡,重温之后,我们就想要改进,为什么要改进呢?因为我们这里面有0.5,还有k,k里面有dx/dy,这些除法和小数都不是我们想要的,我们想要的是,只有整数,且只有加法的算法,下面就全面讨论一下改进算法。
3.改进算法篇(不同斜率,不同方向)这里,我们主要分为4个角度来说明:A.斜率在0-1只间B.斜率在1-无穷之间C.斜率在0-(-1)之间D.斜率在(-1)-负无穷之间E.两种特殊情况,两条直线。
Bresenham算法
举例:图3-4用Bresenham方法扫描转换连接两点P0(0,0)和 P1 (5,2)的直线段。△y = 2, △x = 5, d0 =-1。 Line: P0(0, 0), P1(5, 2) x y d 0 0 -1 1 0 3 2 1 -3 3 1 1 4 2 -5 5 2 -1
PLAY
2y x
以下是当0<k<1时的Bresenham画线算法程序: void Bresenham_Line (int x0,int y0,int x1, int y1,int color) { int dx,dy,d,i,x,y; 复杂度:加法。x每次注定 dx = x1-x0, dy = y1- y0, d=2*dy-dx; 前进1,对于0<k<1,y一定 x=x0, y=y0; 要么前进1,要么不变。如 for (i=0; i<=dx; i++) 果k的取值范围不在(0<k<1) { 之间,上述程序略作修改 SetPixel (x, y, color); 即可满足要求。例如,当 x++; if (d>=0) k>1时,y总是增1,再用 { Bresenham误差量判别式可 y++; 以确定x变量是否增加1。 d=d+2*dy-2*dx; 此时,上述程序只需交换x }else 和y的坐标即可实现。其次, d=d+2*dy; 当k<0,要考虑x或y不是递 } 增1,而是递减1。 }
c 2y x(2b 1) 是常量,与像素位置无关
令di x(d1 d 2 ) ,则di的符号与(d1-d2)的符号相同。
当di<0时,直线上理想位置与像素(xi+1,yi)更接近,应取 右方像素; 当di>0时,像素(xi+1,yi+1)与直线上理想位置更接近; 当di=0时,两个像素与直线上理想位置一样接近,可约定 取(xi+1,yi+1)。
计算机图形学课程设计实验报告(59543)
《计算机图形学》实验报告班级计算机科学与技术姓名学号2014 年6 月2 日实验一基本图形生成算法一、实验目的:1、掌握中点Bresenham绘制直线的原理;2、设计中点Bresenham算法;3、掌握八分法中点Bresenham算法绘制圆的原理;4、设计八分法绘制圆的中点Bresenham算法;5、掌握绘制1/4椭圆弧的上半部分和下半部分的中点Bresenham算法原理;6、掌握下半部分椭圆偏差判别式的初始值计算方法;7、设计顺时针四分法绘制椭圆的中点Bresenham算法。
二、实验过程:1、实验描述实验1:使用中点Bresenham算法绘制斜率为0<=k<=1的直线。
实验2:使用中点Bresenham算法绘制圆心位于屏幕客户区中心的圆。
实验3:使用中点Bresenham算法绘制圆心位于屏幕客户区中心的椭圆。
2、实验过程1)用MFC(exe)建立一个单文档工程;2)编写对话框,生成相应对象,设置相应变量;3)在类CLineView中声明相应函数,并在相关的cpp文件中实现;4)在OnDraw()函数里调用函数实现绘制直线、圆、椭圆;5)运行程序,输入相应值,绘制出图形。
三、源代码实验1:直线中点Bresenham算法1.// cline.cpp : implementation file// cline dialogcline::cline(CWnd* pParent /*=NULL*/): CDialog(cline::IDD, pParent){//{{AFX_DATA_INIT(cline)m_x0 = 0;m_y0 = 0;m_x1 = 0;m_y1 = 0;//}}AFX_DATA_INIT}void cline::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(cline)DDX_Text(pDX, IDC_x0, m_x0);DDX_Text(pDX, IDC_y0, m_y0);DDX_Text(pDX, IDC_x1, m_x1);DDX_Text(pDX, IDC_y1, m_y1);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(cline, CDialog)//{{AFX_MSG_MAP(cline)//}}AFX_MSG_MAPEND_MESSAGE_MAP()2、// LineView.hclass CLineView : public CView{public:CLineDoc* GetDocument();..........void Mbline(double,double,double,double); //直线中点Bresenham函数.......}3、// Line.cpp//*******************直线中点Bresenham函数*********************/void CLineView::Mbline(double x0, double y0, double x1, double y1) {CClientDC dc(this);COLORREF rgb=RGB(0,0,255); //定义直线颜色为蓝色double x,y,d,k;x=x0; y=y0; k=(y1-y0)/(x1-x0); d=0.5-k;for(x=x0;x<=x1;x++){dc.SetPixel((int)x,(int)y,rgb);if(d<0){y++;d+=1-k;}elsed-=k;}}4、//LineView.cppvoid CLineView::OnDraw(CDC* pDC){CLineDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data herecline a;a.DoModal();//初始化CLineView::Mbline(a.m_x0,a.m_y0,a.m_x1,a.m_y1); }实验2:圆中点Bresenham算法1、//cricle.cpp// Ccricle dialogCcricle::Ccricle(CWnd* pParent /*=NULL*/): CDialog(Ccricle::IDD, pParent){//{{AFX_DATA_INIT(Ccricle)m_r = 0;//}}AFX_DATA_INIT}void Ccricle::DoDataExchange(CDataExchange* pDX) {CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(Ccricle)DDX_Text(pDX, r_EDIT, m_r);//}}AFX_DATA_MAP}2、//CcircleView.hclass CCcircleView : public CView{.......public:CCcircleDoc* GetDocument();void CirclePoint(double,double); //八分法画圆函数void Mbcircle(double); //圆中点Bresenham函数........}3、//CcircleView.cppvoid CCcircleView::OnDraw(CDC* pDC){CCcircleDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereCcricle r;r.DoModal();CCcircleView::Mbcircle(r.m_r);//画圆}4、//CcircleView.cpp//*******************八分法画圆*************************************/ void CCcircleView::CirclePoint(double x,double y){CClientDC dc(this);COLORREF rgb=RGB(0,0,255);dc.SetPixel((int)(300+x),(int)(300+y),rgb);dc.SetPixel((int)(300-x),(int)(300+y),rgb);dc.SetPixel((int)(300+x),(int)(300-y),rgb);dc.SetPixel((int)(300-x),(int)(300-y),rgb);dc.SetPixel((int)(300+y),(int)(300+x),rgb);dc.SetPixel((int)(300-y),(int)(300+x),rgb);dc.SetPixel((int)(300+y),(int)(300-x),rgb);dc.SetPixel((int)(300-y),(int)(300-x),rgb);}//**************************圆中点Bresenham函数*********************/ void CCcircleView::Mbcircle(double r){double x,y,d;COLORREF rgb=RGB(0,0,255);d=1.25-r;x=0;y=r;for(x=0;x<y;x++){CirclePoint(x,y); //调用八分法画圆子函数if(d<0)d+=2*x+3;else{d+=2*(x-y)+5;y--;}}}实验3:椭圆中点Bresenham算法1、//ellipse1.cpp// Cellipse dialogCellipse::Cellipse(CWnd* pParent /*=NULL*/) : CDialog(Cellipse::IDD, pParent){//{{AFX_DATA_INIT(Cellipse)m_a = 0;m_b = 0;//}}AFX_DATA_INIT}void Cellipse::DoDataExchange(CDataExchange* pDX) {CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(Cellipse)DDX_Text(pDX, IDC_EDIT1, m_a);DDX_Text(pDX, IDC_EDIT2, m_b);//}}AFX_DATA_MAP}2、//EllipseView.hclass CEllipseView : public CView{......................public:CEllipseDoc* GetDocument();void EllipsePoint(double,double); //四分法画椭圆void Mbellipse(double a, double b); //椭圆中点Bresenham函数..................}3、//Ellipse.cpp//*****************四分法画椭圆********************************/void CEllipseView::EllipsePoint(double x,double y){CClientDC dc(this);COLORREF rgb=RGB(0,0,255);dc.SetPixel((int)(300+x),(int)(300+y),rgb);dc.SetPixel((int)(300-x),(int)(300+y),rgb);dc.SetPixel((int)(300+x),(int)(300-y),rgb);dc.SetPixel((int)(300-x),(int)(300-y),rgb);}//************************椭圆中点Bresenham函数*********************/ void CEllipseView::Mbellipse(double a, double b){double x,y,d1,d2;x=0;y=b;d1=b*b+a*a*(-b+0.25);EllipsePoint(x,y);while(b*b*(x+1)<a*a*(y-0.5))//椭圆AC弧段{if(d1<0)d1+=b*b*(2*x+3);else{d1+=b*b*(2*x+3)+a*a*(-2*y+2);y--;}x++;EllipsePoint(x,y);}d2=b*b*(x+0.5)*(x+0.5)+a*a*(y-1)*(y-1)-a*a*b*b;//椭圆CB弧段while(y>0){if(d2<0){d2+=b*b*(2*x+2)+a*a*(-2*y+3);x++;}elsed2+=a*a*(-2*y+3);y--;EllipsePoint(x,y);}}4、//EllipseView.cppvoid CEllipseView::OnDraw(CDC* pDC){CEllipseDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereCellipse el;el.DoModal();//初始化CEllipseView::Mbellipse(el.m_a, el.m_b);//画椭圆}四、实结果验实验1:直线中点Bresenham算法实验2:圆中点Bresenham 算法实验3:椭圆中点Bresenham 算法实验二有效边表填充算法一、实验目的:1、设计有效边表结点和边表结点数据结构;2、设计有效边表填充算法;3、编程实现有效边表填充算法。
通用整数bresenham算法
通用整数bresenham算法
Bresenham算法是一种用于在计算机屏幕上绘制直线、圆和其
他形状的算法。
在这里,我将重点介绍通用整数Bresenham算法,
用于绘制直线。
通用整数Bresenham算法是一种用于在计算机屏幕上绘制直线
的算法。
它是一种基于整数运算的算法,因此在计算机上执行速度
很快。
该算法通过在每个步骤中选择最接近直线路径的像素来绘制
直线。
该算法的基本原理是利用斜率来确定下一个要绘制的像素。
在
每一步中,根据直线斜率的大小来决定是向横坐标方向移动一个像
素还是向纵坐标方向移动一个像素。
通过适当的取整和判断,Bresenham算法能够以非常高效的方式绘制直线。
通用整数Bresenham算法的优点之一是它不需要使用浮点运算,这使得它非常适合于嵌入式系统和其他资源受限的环境。
此外,该
算法的实现比较简单,适用于各种编程语言和平台。
然而,通用整数Bresenham算法也有一些局限性。
例如,当直
线的斜率非常大或非常小的时候,该算法可能会出现绘制的直线与实际直线有所偏差。
此外,对于对角线上的像素,该算法可能不够精确。
总的来说,通用整数Bresenham算法是一种高效的直线绘制算法,特别适合于需要在计算机屏幕上绘制直线的应用程序。
它的简单性和高效性使得它成为计算机图形学中常用的算法之一。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程实验报告步骤为了规范颜色的处事,定义了CRGB类,重载了“+”,“-”、“*”、“\”、“+=”、“-=”、“*=”、“/=”运算符。
成员函数Normalize()将颜色分量red,green,blue规范到[0,1]闭区间内。
RGB.h#pragma onceclass CRGB{public:CRGB();CRGB(double, double, double);~CRGB();friend CRGB operator + (const CRGB&, const CRGB&);friend CRGB operator - (const CRGB&, const CRGB&);friend CRGB operator * (const CRGB&, const CRGB&);friend CRGB operator * (const CRGB&, double);friend CRGB operator * (double, const CRGB&);friend CRGB operator / (const CRGB&, double);friend CRGB operator += (const CRGB&, const CRGB&);friend CRGB operator -= (const CRGB&, const CRGB&);friend CRGB operator *= (const CRGB&, const CRGB&);friend CRGB operator /= (const CRGB&, double);void Normalize();public:double red;double green;double blue;};RGB.cpp#include"stdafx.h"#include"RGB.h"CRGB::CRGB(){red = 1.0;green = 1.0;blue = 1.0;}CRGB::~CRGB(){}CRGB::CRGB(double r, double g, double b){red = r;green = g;blue = b;}CRGB operator +(const CRGB &c1, const CRGB &c2) {CRGB c;c.red = c1.red + c2.red;c.green = c1.green + c2.green;c.blue = c1.blue + c2.blue;return c;}CRGB operator - (const CRGB &c1, const CRGB &c2) {CRGB c;c.red = c1.red - c2.red;c.green = c1.green - c2.green;c.blue = c1.blue - c2.blue;return c;}CRGB operator * (const CRGB&c1, const CRGB&c2) {CRGB c;c.red = c1.red * c2.red;c.green = c1.green * c2.green;c.blue = c1.blue * c2.blue;return c;}CRGB operator * (const CRGB&c1, double k){CRGB c;c.red = c1.red*k;c.green = c1.green*k;c.blue = c1.blue*k;return c;}CRGB operator * (double k, const CRGB&c1){CRGB c;c.red = c1.red*k;c.green = c1.green*k;c.blue = c1.blue*k;return c;}CRGB operator / (double k, const CRGB&c1){CRGB c;c.red = c1.red / k;c.green = c1.green / k;c.blue = c1.blue / k;return c;}CRGB operator +=(const CRGB &c1, const CRGB &c2) {CRGB c;c.red = c1.red + c2.red;c.green = c1.green + c2.green;c.blue = c1.blue + c2.blue;return c;}CRGB operator -= (const CRGB &c1, const CRGB &c2) {CRGB c;c.red = c1.red - c2.red;c.green = c1.green - c2.green;c.blue = c1.blue - c2.blue;return c;}CRGB operator *= (const CRGB&c1, const CRGB&c2) {CRGB c;c.red = c1.red * c2.red;c.green = c1.green * c2.green;c.blue = c1.blue * c2.blue;return c;}CRGB operator /= (const CRGB&c1, double k){CRGB c;c.red = c1.red / k;c.green = c1.green / k;c.blue = c1.blue / k;return c;}void CRGB::Normalize(){red = (red<0.0) ? 0.0 : ((red>1.0) ? 1.0 : red);green = (green<0.0) ? 0.0 : ((green>1.0) ? 1.0 : green);blue = (blue<0.0) ? 0.0 : ((blue>1.0) ? 1.0 : blue);}4、设计Cline直线类定义直线绘制任意斜率的直线,其成员函数为MoveTo()和LineTo()。
Line.h#pragma once#include"P2.h"#include"RGB.h"class CLine{public:CLine();virtual ~CLine();void MoveTo(CDC *, CP2);//移动到指定位置void MoveTo(CDC *, double, double);void LineTo(CDC *, CP2);//绘制直线,不含终点void LineTo(CDC *, double, double);public:CP2P0;//起点CP2P1;//终点};Line.cpp#include"stdafx.h"#include"Line.h"#include"math.h"#define Round(d) int(floor(d+0.5))//四舍五入宏定义#ifdef_DEBUG#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#define new DEBUG_NEW#endifCLine::CLine(){}CLine::~CLine(){}void CLine::MoveTo(CDC *pDC, CP2p0)//绘制直线起点函数{P0 = p0;}void CLine::MoveTo(CDC *pDC, double x0, double y0)//重载函数{P0 = CP2(x0, y0);}void CLine::LineTo(CDC *pDC, CP2p1){P1 = p1;CP2p, t;CRGB clr = CRGB(0.0, 0.0, 0.0);//黑色像素点if (fabs(P0.x - P1.x)<1e-6)//绘制垂线{if (P0.y>P1.y)//交换顶点,使得起始点低于终点{t = P0; P0 = P1; P1 = t;}for (p = P0; p.y<P1.y; p.y++){pDC->SetPixelV(Round(p.x), Round(p.y), RGB(clr.red* 255, clr.green * 255, clr.blue * 255));}}else{double k, d;k = (P1.y - P0.y) / (P1.x - P0.x);if (k>1.0)//绘制k>1{if (P0.y > P1.y){t = P0; P0 = P1; P1 = t;}d = 1 - 0.5*k;for (p = P0; p.y < P1.y; p.y++){pDC->SetPixelV(Round(p.x), Round(p.y), RGB(clr.red * 255, clr.green * 255, clr.blue * 255));if (d >= 0){p.x++;d += 1 - k;}elsed += 1;}}if (0.0 <= k && k <= 1.0)//绘制0<=k<=1{if (P0.x > P1.x){t = P0; P0 = P1; P1 = t;}d = 0.5 - k;for (p = P0; p.x < P1.x; p.x++){pDC->SetPixelV(Round(p.x), Round(p.y), RGB(clr.red * 255, clr.green * 255, clr.blue * 255));if (d < 0){p.y++;d += 1 - k;}elsed -= k;}}if (k >= -1.0 && k<0.0)//绘制-1<=k<0{if (P0.x>P1.x){t = P0; P0 = P1; P1 = t;}d = -0.5 - k;for (p = P0; p.x<P1.x; p.x++){pDC->SetPixelV(Round(p.x), Round(p.y), RGB(clr.red * 255, clr.green * 255, clr.blue * 255));if (d>0){p.y--;d -= 1 + k;}elsed -= k;}}if (k < -1.0)//绘制k<-1{if (P0.y<P1.y){t = P0; P0 = P1; P1 = t;}d = -1 - 0.5*k;for (p = P0; p.y>P1.y; p.y--){pDC->SetPixelV(Round(p.x), Round(p.y), RGB(clr.red * 255, clr.green * 255, clr.blue * 255));if (d < 0){p.x++;d -= 1 + k;}elsed -= 1;}}}P0 = p1;}void CLine::LineTo(CDC *pDC, double x1, double y1)//重载函数{LineTo(pDC, CP2(x1, y1));}5、添加鼠标消息映射添加WM_LBUTTONDOWN消息映射函数void CTestView::OnLButtonDown(UINT nFlags, CPoint point){// TODO: 在此添加消息处理程序代码和/或调用默认值p0.x = point.x;p0.y = point.y;p0.x = p0.x - rect.Width() / 2; //设备坐标系向自定义坐标系转换p0.y = rect.Height() / 2 - p0.y;CView::OnLButtonDown(nFlags, point);}添加WM_LBUTTONUP消息映射函数void CTestView::OnLButtonUp(UINT nFlags, CPoint point){// TODO: 在此添加消息处理程序代码和/或调用默认值p1.x=point.x;p1.y=point.y;CLine *line=new CLine;CDC *pDC=GetDC();//定义设备上下文指针//与案例比新加的语句GetClientRect(rect);pDC->SetMapMode(MM_ANISOTROPIC); //自定义坐标系pDC->SetWindowExt(rect.Width(),rect.Height()); //设置窗口比例pDC->SetViewportExt(rect.Width(),-rect.Height()); //设置视区比例,且x轴水平向右,y轴垂直向上pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);//设置客户区中心为坐标系原点rect.OffsetRect(-rect.Width()/2,-rect.Height()/2); //矩形与客户区重合/*pDC->MoveTo(0, 0);pDC->LineTo(100, 200);*/p1.x=p1.x-rect.Width()/2;p1.y=rect.Height()/2-p1.y;line->MoveTo(pDC,p0);line->LineTo(pDC,p1);delete line;ReleaseDC(pDC);CView::OnLButtonUp(nFlags, point);}调试过程及实验结果总结本案例实现的Cline类的成员函数类似于CDC类的MoveTo()函数和LineTo()函数,用于绘制任意斜的直线段。