精华内容
下载资源
问答
  • 主要为大家详细介绍了OpenGL通过中点法绘制直线和,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 使用两种交互方式画圆:一个是鼠标拖动(可显示预生成的),另一个是从对话框输入数值自定义圆心和半径。
  • 中点画椭圆

    2016-02-26 19:00:25
    华科图形学,用中点画椭圆法绘制整个椭圆。
  • OpenGL绘制直线和中点法

    千次阅读 2013-10-11 22:56:21
    //设置投影参数 //指的是视图范围,如果(0,200,0,200)的话就只能在第一象限显示,就1/4,第1,3的参数是左下角坐标,第2,4的参数是右上角坐标 } /*void Display(void) { glClear(GL_COLOR_BUFFER_BIT); //用...
    #include <gl/glut.h>
    #include <math.h>
    
    static  int i=1;
    
    void Initial(void)
    {
    		glClearColor(1.0f, 1.0f, 1.0f, 1.0f);      //设置窗口背景颜色为白色
    		glMatrixMode(GL_PROJECTION);    //指定设置投影参数
    		gluOrtho2D(-200.0,200.0,-200.0,200.0); //设置投影参数  //指的是视图范围,如果(0,200,0,200)的话就只能在第一象限显示,就1/4圆,第1,3的参数是左下角坐标,第2,4的参数是右上角坐标
    }
    /*void Display(void)
    {
    		glClear(GL_COLOR_BUFFER_BIT);   //用当前背景色填充窗口
    		glColor3f(1.0f, 0.0f, 0.0f);            //设置当前的绘图颜色为红色
    		glRectf(50.0f, 100.0f, 150.0f, 50.0f);    //绘制一个矩形
                 glFlush();                         //处理所有的OpenGL程序
    }
    */
    
    void DDALine(int x0,int y0,int x1,int y1)
    {
    	//glVertex2f(10,10);
    	int dx,dy,epsl,k;
    	float x,y,xIncre,yIncre;
    	dx = x1 - x0;
    	dy = y1 - y0;
    	x = x0;
    	y = y0;
    
    	if(abs(dx)>abs(dy))
    		epsl=abs(dx);
    	else
    		epsl=abs(dy);
    
    	xIncre=(float)dx/(float)epsl;
    	yIncre=(float)dy/(float)epsl;
    	glPointSize(2);
    	glBegin(GL_POINTS);
    	for(k = 0;k <= epsl; k++)
    	{
    		glColor3f(1.0f, 0.0f, 0.0f);
    		glVertex2f(int(x+0.5),int(y+0.5));
    		x += xIncre;
    		y += yIncre;
    	}
    	glEnd();
    
    }
    
    
    
    void Mid_B(int x0,int y0,int x1,int y1)
    {
    	int dx,dy,d,UpIncre,DownIncre,x,y;
    	if(x0 > x1)
    	{
    		x = x1;
    		x1 = x0;
    		x0 = x;
    		y = y1;
    		y1 = y0;
    		y0 = y;
    	}
    	x = x0;
    	y = y0;
    	dx = x1 - x0;
    	dy = y1 - y0;
    	d = dx - 2*dy;
    	UpIncre = 2*dx - 2*dy;
    	DownIncre =- 2*dy;
    
    	glPointSize(2);
    	glBegin(GL_POINTS);
    	while(x <= x1)
    	{
    		glColor3f(1.0f, 0.0f, 0.0f);
    		glVertex2f(x,y);
    		x++;
    		if(d < 0)
    		{
    			y++;
    			d += UpIncre;
    		}
    		else
    			d += DownIncre;
    	}
    	glEnd();
    
    }
    
    void G_B(int x0,int y0,int x1,int y1)
    {
    	int x,y,dx,dy,e;
    	dx = x1 - x0;
    	dy = y1 - y0;
    	e =- dx;
    	x=x0;
    	y=y0;
    	
    	glPointSize(2);
    	glBegin(GL_POINTS);
    	while(x <= x1)
    	{
    		glColor3f(1.0f, 0.0f, 0.0f);
    		glVertex2f(x,y);
    		x++;
    		e = e + 2*dy;
    		if(e > 0)
    		{
    			y++;
    			e = e - 2*dx;
    		}
    
    	}
    	glEnd();
    }
    
    void CirclePoint(int x, int y)
    {
    	glPointSize(2);
    	glBegin(GL_POINTS);
    	glColor3f(1.0f, 0.0f, 0.0f);
    	glVertex2f(x,y);
    	glVertex2f(y,x);	
    	glVertex2f(-y,x);	
    	glVertex2f(-x,y);	
    	glVertex2f(-x,-y);	
    	glVertex2f(-y,-x);	
    	glVertex2f(y,-x);	
    	glVertex2f(x,-y);
    	glEnd();
    }
    
    void MidBresenhamCircle(int r)
    {
    	int x = 0, y = r, d = 1-r;
    	//glPointSize(2);
    	//glBegin(GL_POINTS);
    	while(x <= y)
    	{
    		CirclePoint(x,y);
    		
    		if(d < 0)
    					d += 2*x+3;
    				else
    				{
    					d += 2*(x-y)+5;
    					y--;
    				}
    				x++;
    	}
    	glEnd();
    }
    
    void ProcessMenu(int value)
    {
    	i = value;  
    	glutPostRedisplay();
    }
    
    
    
    void Display(void)
    {
    		glClear(GL_COLOR_BUFFER_BIT);   //用当前背景色填充窗口
    		glViewport(0,0,400,400); //前两个参数改变原点坐标,后两个参数改变图形长宽(放大缩小)
    		switch(i)
    		{
    		case 1:
    			DDALine(2,3,55,83);
    			break;
    		case 2:
    			Mid_B(2,3,55,83);
    			break;
    		case 3:
    			G_B(2,3,55,83);
    			break;
    		case 4:
    			MidBresenhamCircle(50);
    			break;
    		
    		}
    		glFlush(); 
    }
    
    int main(int argc, char* argv[])
    
    {
    		glutInit(&argc, argv);				 //初始化GLUT库,处理命令行参数 
    		glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);  //初始化窗口的显示模式
    		glutInitWindowSize(400,400);              //设置窗口的尺寸
    		glutInitWindowPosition(100,100);       //设置窗口的位置
    		glutCreateWindow("直线");                 //创建一个名为矩形的窗口
    
    		int MainMenu = glutCreateMenu(ProcessMenu);  //创建主菜单
    		glutAddMenuEntry("DDA算法",1);
    		glutAddMenuEntry("中点Bresenham算法",2);
    		glutAddMenuEntry("改进的Bresenham算法",3);
    		glutAddMenuEntry("中点bresenham画圆",4);
    		glutAttachMenu(GLUT_RIGHT_BUTTON);		
    
    		glutDisplayFunc(Display);     //设置当前窗口的显示回调函数
    		Initial();                                    //完成窗口初始化
    		glutMainLoop();                     //启动主GLUT事件处理循环
    		return 0;
    	
    
    }
    

    展开全文
  • 方程为非线性的,计算像素与的距离...该方法的基本思想是检验两像素间的中间位置以确定该中点是在边界值内还是之外。 【注】算法代码如下,其中void circleBresham(GLint xc,GLint yc,GLint radius)为用Bresenha

    圆方程为非线性的,计算像素与圆的距离必须进行平方运算,Bresenham画圆方法则通过比较像素与圆的距离的方法而避免了平方根运算。

    然而,不做平方运算而直接比较距离是可能得。该方法的基本思想是检验两像素间的中间位置以确定该中点是在圆边界值内还是之外。

    【注】算法代码如下,其中void circleBresham(GLint xc,GLint yc,GLint radius)为用Bresenham算法画圆的算法,而其中void circleMidpoint(GLint xc,GLint yc,GLint radius)为中点画圆的算法:

    #include<windows.h>

    #include<math.h>

     

    #ifdef __APPLE__

    #include <GLUT/glut.h>

    #else

    #include <GL/glut.h>

    #endif

     

     

    #include <stdlib.h>

     

    void init (void)

    {

        glClearColor(0.0, 1.0, 0.0, 0.0);  // Set display-window color to white.

        glMatrixMode (GL_PROJECTION);       // Set projection parameters.

        gluOrtho2D (0.0, 200.0, 0.0, 150.0);

    }

     

    class screenPt

    {

    private:

        GLint x,y;

    public:

        screenPt(){

            x = y =0;

        }

        void setCoords(GLint xCoordValue,GLint yCoordValue){

            x = xCoordValue;

            y = yCoordValue;

        }

     

        GLint getx() const

        {

            return x;

        }

        GLint gety() const

        {

            return y;

        }

        void incrementx()

        {

            x ++;

        }

        void decrementy()

        {

            y--;

        }

    };

     

    void setPixel(GLint xCoord,GLint yCoord)

    {

        glBegin(GL_POINTS);

            glVertex2i(xCoord,yCoord);

        glEnd();

        //glFlush();

    }

     

    void circleMidpoint(GLint xc,GLint yc,GLint radius)

    {

        glColor 3f(1.0,0.0,0.0);

        screenPt circPt;

        GLint p = 1 - radius;

     

        circPt.setCoords(0,radius);

     

        void circlePlotPoints(GLint,GLint,screenPt);

     

        circlePlotPoints(xc,yc,circPt);

     

        while(circPt.getx()< circPt.gety())

        {

            circPt.incrementx();

            if (p<0){

                p += 2*circPt.getx() + 1;

            }

            else{

                circPt.decrementy();

                p += 2*(circPt.getx() - circPt.gety()) + 1;

            }

            circlePlotPoints(xc,yc,circPt);

        }

    }

     

    void circleBresham(GLint xc,GLint yc,GLint radius)

    {

        glColor3f(1.0,0.0,0.0);

        screenPt circPt;

        //GLint p = 1 - radius;

     

        circPt.setCoords(0,radius);

     

        void circlePlotPoints(GLint,GLint,screenPt);

     

        circlePlotPoints(xc,yc,circPt);

     

        while(circPt.getx()< circPt.gety())

        {

            GLint x1,x2,y1,y2;

            circPt.incrementx();

            x1 = circPt.getx();

            y1 = circPt.gety();

            x2 = circPt.getx();

            y2 = circPt.gety()-1;

            //if ((x1*x1+y1*y1-radius*radius)<(x2*x2+y2*y2-radius*radius)){

     

            //}

            if (fabs(x1*x1+y1*y1-radius*radius)>fabs(x2*x2+y2*y2-radius*radius)){

                circPt.decrementy();

               // p += 2*(circPt.getx() - circPt.gety()) + 1;

            }

            circlePlotPoints(xc,yc,circPt);

        }

    }

     

    void circlePlotPoints(GLint xc,GLint yc,screenPt circPt)

    {

        setPixel(xc + circPt.getx(),yc + circPt.gety());

        setPixel(xc - circPt.getx(),yc + circPt.gety());

        setPixel(xc + circPt.getx(),yc - circPt.gety());

        setPixel(xc - circPt.getx(),yc - circPt.gety());

        setPixel(xc + circPt.gety(),yc + circPt.getx());

        setPixel(xc - circPt.gety(),yc + circPt.getx());

        setPixel(xc + circPt.gety(),yc - circPt.getx());

        setPixel(xc - circPt.gety(),yc - circPt.getx());

    }

     

    void pointsFun(void)

    {

        glPointSize(3.0);

        glEnable(GL_POINT_SMOOTH);

        glClear(GL_COLOR_BUFFER_BIT);

        circleBresham(100,100,30);

        glFlush();

    }

     

    int main (int argc, char** argv)

    {

     

        glutInit (&argc, argv);                         // Initialize GLUT.

        glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);   // Set display mode.

        glutInitWindowPosition (50, 100);   // Set top-left display-window position.

        glutInitWindowSize (400, 300);      // Set display-window width and height.

        glutCreateWindow ("An Example OpenGL Program"); // Create display window.

     

           init();                           // Execute initialization procedure.

        glutDisplayFunc (pointsFun);       // Send graphics to display window.

        glutMainLoop ( );// Send graphics to display window.                  // Display everything and wait.

           return 0;

    }

    展开全文
  • 【计算机图形学】中点画线实现焦点在x、y轴上的椭圆绘制 一、中点画线原理简介 1.建立基础 中点画线的原理介绍见直线绘制的博文中点画线实现任意斜率直线的绘制。基本思路是以下一点在椭圆外/内的位置关系...

    【计算机图形学】中点画线法实现焦点在x、y轴上的椭圆绘制

    一、中点画线法原理简介

    1.建立基础

    2.具体分析

    • 待补具体图例

    二、代码实现

    • 分析出椭圆右上部分、右下部分的中点画线方法,并将所得点关于y轴对称,得出整个椭圆图案。
    /*
    程序:中点画线法实现焦点在x\y轴上的椭圆绘制
    编译环境:Visual C++ 6.0 EasyX_20200109(beta)
    作者ID:weixin_43536824
    邮箱:changye303@163.com
    */
    #include <easyx.h>
    #include <graphics.h>
    #include <conio.h>
    #include <stdio.h>
    #include <math.h>
    
    //情况1:画上部分(屏幕显示为下部分)
    void GetOvalUp(double a,double b,double m,double n,int COLOR,int c){
    	double x,y,d,xx,yy,l;
    	double xp = m+pow(a,2)/sqrt(pow(a,2)+pow(b,2));
    	double yp = n+pow(b,2)/sqrt(pow(a,2)+pow(b,2));
    	double xpp = pow(a,2)/sqrt(pow(a,2)+pow(b,2));
    	double ypp = pow(b,2)/sqrt(pow(a,2)+pow(b,2));
    	double d10 = pow(a,2)*(0.25-b)+pow(b,2);
    	double d20 = pow(b,2)*pow(xpp+0.5,2)+pow(a,2)*pow(ypp-1,2)-pow(a,2)*pow(b,2);
    	
    	//x <= xp:
    	x = m;
    	y = n+b;
    	xx = 0;
    	yy = b;
    	moverel((int)x,(int)y);
    	d = d10;
    	while (x <= xp){
    		if(d < 0){
    			//若焦点在x轴上
    			if(c==0){
    				putpixel((int)x,(int)y,COLOR);
    			    l = x-m;
    			    putpixel((int)(m-l),(int)y,COLOR);		
    			}
    			//若焦点在y轴上
    			else{
    				putpixel((int)y,(int)x,COLOR);
    			    l = x-m;
    			    putpixel((int)y,(int)(m-l),COLOR);		
    			}
    			d+= (pow(b,2)*(2*xx+3));
    			x+= 1;
    			xx+=1;
    		}
    		else{
    			//若焦点在x轴上
    			if(c==0){
    				putpixel((int)x,(int)y,COLOR);
    			    l = x-m;
    			    putpixel((int)(m-l),(int)y,COLOR);		
    			}
    			//若焦点在y轴上
    			else{
    				putpixel((int)y,(int)x,COLOR);
    			    l = x-m;
    			    putpixel((int)y,(int)(m-l),COLOR);		
    			}
    			d+= (pow(b,2)*(2*xx+3)+pow(a,2)*(2-2*yy));
    			x+= 1;
    			y-= 1;
    			xx+= 1;
    			yy-= 1;
    		}
    	}
    
    	//x > xp:
    	x = xp;
    	y = yp;
    	xx = xpp;
    	yy = ypp;
    	moverel((int)x,(int)y);
    	d = d20;
    	while(x >= xp && x <= m+a && y >= n ){
    		if(d < 0){
    			//若焦点在x轴上
    			if(c==0){
    				putpixel((int)x,(int)y,COLOR);
    			    l = x-m;
    			    putpixel((int)(m-l),(int)y,COLOR);	
    			}
    			//若焦点在y轴上
    			else{
    				putpixel((int)y,(int)x,COLOR);
    			    l = x-m;
    			    putpixel((int)y,(int)(m-l),COLOR);		
    			}
    			d+= (pow(b,2)*(2*xx+2)+pow(a,2)*(3-2*yy));
    			y-= 1;
    			x+= 1;
    			yy-= 1;
    			xx+= 1;
    		}
    		else{
    			//若焦点在x轴上
    			if(c==0){
    				putpixel((int)x,(int)y,COLOR);
    			    l = x-m;
    			    putpixel((int)(m-l),(int)y,COLOR);		
    			}
    			//若焦点在y轴上
    			else{
    				putpixel((int)y,(int)x,COLOR);
    			    l = x-m;
    			    putpixel((int)y,(int)(m-l),COLOR);		
    			}
    	
    			d+= pow(a,2)*(3-2*yy);
    			y-= 1;
    			yy-= 1;
    		}
    	}
    }
    
    //画下部分(屏幕上显示为上部分)
    void GetOvalDown(double a,double b,double m,double n,int COLOR,int c){
    	double x,y,d,xx,yy,l;
    	double xp = m+pow(a,2)/sqrt(pow(a,2)+pow(b,2));
    	double yp = n-pow(b,2)/sqrt(pow(a,2)+pow(b,2));
    	double xpp = pow(a,2)/sqrt(pow(a,2)+pow(b,2));
    	double ypp = (-1)*(pow(b,2)/sqrt(pow(a,2)+pow(b,2)));
    	double d10 = pow(a,2)*(0.25-b)+pow(b,2);
    	double d20 = pow(b,2)*pow(xpp+0.5,2)+pow(a,2)*pow(ypp+1,2)-pow(a,2)*pow(b,2);
    
    	//x <= xp:
    	x = m;
    	y = n-b;
    	xx = 0;
    	yy = -1*b;
    	moverel((int)x,(int)y);
    	d = d10;
    	while (x <= xp){
    		if(d < 0){
    			//若焦点在x轴上
    			if(c==0){
    				putpixel((int)x,(int)y,COLOR);
    			    l = x-m;
    			    putpixel((int)(m-l),(int)y,COLOR);		
    			}
    			//若焦点在y轴上
    			else{
    				putpixel((int)y,(int)x,COLOR);
    			    l = x-m;
    			    putpixel((int)y,(int)(m-l),COLOR);		
    			}
    		
    			d+= (pow(b,2)*(2*xx+3));
    			x+= 1;
    			xx+= 1;
    		}
    		else{
    			//若焦点在x轴上
    			if(c==0){
    				putpixel((int)x,(int)y,COLOR);
    			    l = x-m;
    			    putpixel((int)(m-l),(int)y,COLOR);		
    			}
    			//若焦点在y轴上
    			else{
    				putpixel((int)y,(int)x,COLOR);
    			    l = x-m;
    			    putpixel((int)y,(int)(m-l),COLOR);		
    			}
    	
    			d+= (pow(b,2)*(2*xx+3)+pow(a,2)*(2+2*yy));
    			x+= 1;
    			y+= 1;
    			xx+= 1;
    			yy+= 1;
    		}
    	}
    	//x > xp:
    	x = xp;
    	y = yp;
    	xx = xpp;
    	yy = ypp;
    	moverel((int)x,(int)y);
    	d = d20;
    	while(x >= xp && y <= n){
    		if(d < 0){
    			//若焦点在x轴上
    			if(c==0){
    				putpixel((int)x,(int)y,COLOR);
    			    l = x-m;
    			    putpixel((int)(m-l),(int)y,COLOR);		
    			}
    			//若焦点在y轴上
    			else{
    				putpixel((int)y,(int)x,COLOR);
    			    l = x-m;
    			    putpixel((int)y,(int)(m-l),COLOR);		
    			}
    	
    			d+= (pow(b,2)*(2*xx+2)+pow(a,2)*(3+2*yy));
    			y+= 1;
    			x+= 1;
    			yy+= 1;
    			xx+= 1;
    		}
    		else{
    			//若焦点在x轴上
    			if(c==0){
    				putpixel((int)x,(int)y,COLOR);
    			    l = x-m;
    			    putpixel((int)(m-l),(int)y,COLOR);		
    			}
    			//若焦点在y轴上
    			else{
    				putpixel((int)y,(int)x,COLOR);
    			    l = x-m;
    			    putpixel((int)y,(int)(m-l),COLOR);		
    			}
    			d+= pow(a,2)*(3+2*yy);
    			y+= 1;
    			yy+= 1;
    		}
    	}
    }
    
    
    //画椭圆函数
    //c=0,画焦点在x轴上的椭圆
    //c=1,画焦点在y轴上的椭圆
    void GetOval(double a,double b,double m,double n,int COLOR,int c){
    		GetOvalUp(a,b,m,n,COLOR,c);
    	    GetOvalDown(a,b,m,n,COLOR,c);
    }
    int main(){
    	initgraph(500,500);	//创建绘图窗口
    	GetOval(200,100,250,250,WHITE,1);
    	getch();			//按任意键继续
    	closegraph();		//关闭绘图窗口
    	return 0;
    }
    
    展开全文
  • 1、调用画点函数,实现任意斜率直线的绘制 (运用DDA算法、中点Bresenam算法实现并比较算法精度与效率) ② 基本论述 DDA算法又称数值微分,是计算机图形学中一种基于直线的微分方程来生成直线的方法。 原理就是最...

    1、调用画点函数,实现任意斜率直线的绘制 (运用DDA算法、中点Bresenam算法实现并比较算法精度与效率)

    ② 基本论述
    DDA算法又称数值微分法,是计算机图形学中一种基于直线的微分方程来生成直线的方法。 原理就是最直观的根据斜率的偏移程度,决定是以x为步进方向还是以y为步进方向。然后在相应的步进方向上,每次增加一个像素,而另一个相关坐标变量则为Y k+1=Y k + m(以x为步进变量为例,m为斜率)
    假定直线斜率k在0~1之间,当前象素点为(xp,yp),则下一个象素点有两种可选择点P1(xp+1,yp)或P2(xp+1,yp+1)。若P1与P2的中点(xp+1,yp+0.5)称为M,Q为理想直线与x=xp+1垂线的交点。当M在Q的下方时,则取P2应为下一个象素点;当M在Q的上方时,则取P1为下一个象素点。这就是中点画线法的基本原理
    Bresenham算法:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。该算法的优点在于可以采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列所求的像素。

    ②算法
    DDA算法描述:
    m =直线的斜率
    可通过计算由x方向的增量△x引起y的改变来生成直线:
    xi+1=xi+△x
    yi+1=yi+△y=yi+△x·m
    也可通过计算由y方向的增量△y引起x的改变来生成直线:
    yi+1=yi+△y
    xi+1=xi+△x=xi+△y/m
    以此类推。
    中点Bresenam算法描述:
    任意给定的两点所绘制的线段斜率k可能有四种情况,分别是:0<k<1,k>=1,-1<k<0,
    k<=-1。下面对这四种情况分别进行分析。

    (一)  当0<k<1时
       1.算法原理的推导
    (1)	构造中点误差项为:
    di=F(xM,yM)=F(xi + 1,yi + 0.5)=yi + 0.5 –k(xi + 1) -b
    (2)	中点误差的初始值是:
    d0=F(x0 + 1,y0 + 0.5)=y0 + 0.5 –k(x0 + 1) -b
    =y0 – kx0 – b – k +0.5
    其中,因为(x0,y0)在直线上,所以y0-kx0-b=0,则:d0=0.5-k
    (3)	推导di+1
    a.	当di>=0时;中点在直线上方,取下面的点(x i+1,yi)
    di+1 = F(xi+2,yi+0.5)
    =yi+0.5-k(xi+2)-b
    =di-k
    b.	当d<i0时;中点在直线下方,取下面的点(x i+1,yi+1)
    di+1 = F(xi+2,yi+1.5)
    =yi+1.5-k(xi+2)-b
    =di+1 - k
    
    (二)  当k>=1时
       1.算法原理的推导
    (1)	构造中点误差项
    di=F(xM,yM)=F(xi + 0.5,yi +1)=yi + 1 –k(xi + 0.5) -b
    (2)	中点误差的初始值
    d0=F(x0 + 0.5,y0 + 1)=y0 + 1 –k(x0 + 0.5) -b
    =y0 – kx0 – b –0.5k+1
    其中,因为(x0,y0)在直线上,所以y0-kx0-b=0,则:d0=1-0.5k
    ( 3 )  推导di+1
    a.当di>=0时;中点在直线左方,取右方的点(x i+1,yi+1)
    di+1 = F(xi+1.5,yi+2)
    =yi+2-k(xi+1.5)-b
    =di+1-k
    b.当d<i0时;中点在直线右方,取左方的点(x i+1,yi+1)
    di+1 = F(xi+0.5,yi+2)
    =yi+2-k(xi+0.5)-b
    =di+1 
    
    (三)当-1<k<0时
    1.算法原理的推导
    (1)	构造中点误差项
    di=F(xM,yM)=F(xi + 1,yi -0.5)=yi - 0.5 –k(xi + 1) -b
    (2)	中点误差的初始值
    d0=F(x0 + 1,y0 - 0.5)=y0 - 0.5 –k(x0 + 1) -b
    =y0 – kx0 – b – k -0.5
    其中,因为(x0,y0)在直线上,所以y0-kx0-b=0,则:d0=-0.5-k
    ( 3 )  推导di+1
    a.当di>=0时;中点在直线上方,取下方的点(x i+1,yi-1)
    di+1 = F(xi+2.,yi-1.5)
    =yi+1.5-k(xi+2)-b
    =di-1-k
    b.当di<0时;中点在直线下方,取下方的点(x i+1,yi)
    di+1 = F(xi+2.,yi-0.5)
    =yi-0.5-k(xi+2)-b
    =di-k
    
    (四)  当k<=-1时
       1.算法原理的推导
    (1)	构造中点误差项
    di=F(xM,yM)=F(xi + 0.5,yi -1)=yi - 1 –k(xi + 0.5) -b
    (2)	中点误差的初始值
    d0=F(x0 + 0.5,y0 - 1)=y0 - 1 –k(x0 + 0.5) -b
    =y0 – kx0 – b –0.5k-1
    其中,因为(x0,y0)在直线上,所以y0-kx0-b=0,则:d0=0.5-k
    ( 3 )  推导di+1
    a.当di>=0时;中点在直线右方,取左方的点(x i,yi-1)
    di+1 = F(xi+0.5,yi-2)
    =yi-2-k(xi+0.5)-b
    =di-1
    b.当d<i0时;中点在直线下方,取下方的点(x i+1,yi-1)
    di+1 = F(xi+1.5,yi-2)
    =yi-2-k(xi+1.5)-b
    =di-1-k
    
    
    

    ③ 程序源代码(是能直接运行的源代码)

    #include <conio.h>
    #include<stdio.h>	
    #include <string.h>
    #include <queue>
    #include <windows.h>
    #include<iostream>
    #include<graphics.h>  // 引用 EasyX 图形库
    #include<time.h>
    #include<math.h>
    #include<stdlib.h>
    using namespace std;
    
    
    //(DDA算法实现)
    void DDA_Line(int x1,int y1,int x2,int y2) {
    	float increx, increy, x, y, length;//定义变量
    	int i;
    	if (abs(x2 - x1) > abs(y2 - y1))//判断以哪个可以作为增量
    		length = abs(x2 - x1);
    	else
    		length = abs(y2 - y1);
    	increx = (x2 - x1) / length;//设置增量,分别为1和k
    	increy = (y2 - y1) / length;
    	x = x1, y = y1;//这是起点
    	for (i = 1; i <= length; i++) {
    		putpixel(int(x + 0.5), int(y + 0.5), RED);//强制转换为整型(因为像素点都是整个整个的)
    		x += increx;// x加增量
    		y += increy;// y加增量
    	}
    }
    
    
    //(中点Bresenam算法实现)
    void Bresenham_line(int x0,int y0,int x1,int y1)
    {
     int x,y,dx,dy;
     float k,e;  //定义变量
     dx=x1-x0;
     dy=y1-y0;
     k=dy/dx;//这是完成k值的初始化
     e=-0.5;
     x=x0;
     y=y0;  
    
     for(int i=0;i<=dx;i++)//i每次加一个,直到终点,y选择性加一或者不加
     {
    putpixel(x,y,BLUE); //画像素点
     x=x+1;
     e=e+k;
     if(e>=0)  //这里e大于零就减一
     {
     y=y+1;
     e=e-1;
     }
     }
    }
    
    void main()  //主函数测试调用算法
    {
     int x0,y0,x1,y1;
    
     initgraph(640, 480); // 定义640 x 480的画面
     setbkcolor(GREEN);  //背景
     cleardevice();
     setcolor(BLACK);
    
     DDA_Line(100, 100, 640, 480);
     Bresenham_line(100, 100, 640, 480);  
    
    
     getch();    // 按任意键继续
     closegraph();   // 关闭图形界面
    }
    

    关于二者效率和精度的研究:
    bresenham算法的特点是:
    1,不必计算直线之斜率,因此不做除法;
    2,不用浮点数,只用整数;
    3,只做整数加减法和乘2运算,而乘2运算可以用硬件移位实现.
    DDA算法的特点:
    浮点数运算
    不易硬件实现
    所以:Bresenham算法相比较于dda算法,速度很快,但是精度没有dda高,适于用硬件实现.

    3、圆或椭圆的绘制

    ①基本论述

    中点画圆法,考虑圆心在原点,半径为R的圆在第一象限内的八分之一圆弧,从点(0, R)到点(R, R )顺时针方向确定这段圆弧。

    ②算法
    假定某点Pi(xi, yi)已经是该圆弧上最接近实际圆弧的点,那么Pi的下一个点只可能是正右方的P1或右下方的P2两者之一
    构造判别函数:
    F(x, y)= x2 + y2 – R2

    当F(x, y)= 0,表示点在圆上,当F(x, y)> 0,表示点在圆外,当F(x, y)< 0,表示点在圆内。如果M是P1和P2的中点,则M的坐标是(xi + 1, yi – 0.5),当F(xi + 1, yi – 0.5)< 0时,M点在圆内,说明P1点离实际圆弧更近,应该取P1作为圆的下一个点。同理分析,当F(xi + 1, yi – 0.5)> 0时,P2离实际圆弧更近,应取P2作为下一个点。当F(xi + 1, yi – 0.5)= 0时,P1和P2都可以作为圆的下一个点,算法约定取P2作为下一个点。

    现在将M点坐标(xi + 1, yi – 0.5)带入判别函数F(x, y),得到判别式d:
    d = F(xi + 1, yi – 0.5)= (xi + 1)2 + (yi –0.5)2 – R2
    若d < 0,则取P1为下一个点,此时P1的下一个点的判别式为:
    d’ = F(xi + 2, yi – 0.5)= (xi + 2)2 + (yi –0.5)2 – R2

    展开后将d带入可得到的递推关系:
    d’ = d + 2xi + 3
    若d > 0,则取P2为下一个点,此时P2的下一个点的判别式为:
    d’ = F(xi + 2, yi – 1.5)= (xi + 2)2 + (yi –1.5)2 – R

    展开后将d带入可得到判别式的递推关系:
    d’ = d + 2(xi - yi) + 5
    特别的,在第一个象限的第一个点(0, R)时,可以推倒出判别式d的初始值d0:
    d0 = F(1, R – 0.5) = 1 – (R – 0.5)2 –R2 = 1.25 - R

    ③程序源代码(是能直接运行的源代码)
    //圆的绘制
    #include<stdio.h>
    #include<graphics.h>  // 引用 EasyX 图形库
    #include<conio.h>
    #define x0 400
    #define y0 400     //坐标轴中心(x0,y0)
    void draw_circle(int x1, int y1, int r) //定义中点画圆方法
    {
    	int d0, x = 0, y = r;//d0为判别式的值
    	d0 = 1.25 - r;   //判别式的初始值,1.25可以改为1(方便计算)
    	while (x < y)   //
    	{
    		if (d0 >= 0) 
    		{
    			d0 = d0 + 2 * (x - y) + 5;  //这是d<0时,判别式的递推关系
    			x += 1;                //因为x,y是上一个点,所以要更新坐标
    			y -= 1;
    			//这里体现八段画法:
    			putpixel(((x + x1) + x0), (y0 - (y + y1)), RED);         //像素点(x,y)着色
    			putpixel(((-x + x1) + x0), (y0 - (y + y1)), RED);        //像素点(-x,y)着色
    			putpixel(((y + x1) + x0), (y0 - (x + y1)), RED);         //像素点(y,x)着色
    			putpixel(((-y + x1) + x0), (y0 - (x + y1)), RED);        //像素点(-y,x)着色
    			putpixel(((x + x1) + x0), (y0 - (-y + y1)), RED);        //像素点(x,-y)着色
    			putpixel(((-x + x1) + x0), (y0 - (-y + y1)), RED);       //像素点(-x,-y)着色
    			putpixel(((y + x1) + x0), (y0 - (-x + y1)), RED);        //像素点(y,-y)着色
    			putpixel(((-y + x1) + x0), (y0 - (-x + y1)), RED);       //像素点(-y,-x)着色
    			Sleep(50);  //休眠函数,作用是延时
    		}
    		else 
    		{ 
    			d0 = d0 + 2 * x + 3;  //这是d》0时,判别式的递推关系
    			x += 1;
    			y = y;    //更新坐标点
    			putpixel(((x + x1) + x0), (y0 - (y + y1)), RED);         //像素点(x,y)
    			putpixel(((-x + x1) + x0), (y0 - (y + y1)), RED);        //像素点(-x,y)
    			putpixel(((y + x1) + x0), (y0 - (x + y1)), RED);         //像素点(y,x)
    			putpixel(((-y + x1) + x0), (y0 - (x + y1)), RED);        //像素点(-y,x)
    			putpixel(((x + x1) + x0), (y0 - (-y + y1)), RED);        //像素点(x,-y)
    			putpixel(((-x + x1) + x0), (y0 - (-y + y1)), RED);       //像素点(-x,-y)
    			putpixel(((y + x1) + x0), (y0 - (-x + y1)), RED);        //像素点(y,-y)
    			putpixel(((-y + x1) + x0), (y0 - (-x + y1)), RED);       //像素点(-y,-x)
    			Sleep(50);
    		}
    	}
    }
    void main() 
    {
    	int x1, y1, r;
    	printf("输入圆心坐标(x1,y1)和圆的半径r:\n");  //用户可以通过圆心坐标和圆的半径来定义圆的形状
    	scanf("%d %d %d", &x1, &y1, &r);    //输入算法
    	initgraph(x0 * 2, y0 * 2);		    //这是在初始化图形窗口大小
    	setbkcolor(GREEN);    //背景为绿色
    	cleardevice();   这里插入图片描述](https://img-blog.csdnimg.cn/20200730202245196.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RvbWF0b2FhYWE=,size_16,color_FFFFFF,t_70)
    
    	setcolor(BLUE);    //坐标轴为蓝色
    	line(x0, 0, x0, y0 * 2);			//这是描绘坐标轴X
    	line(0, y0, x0 * 2, y0);			 //这是描绘坐标轴Y
    	draw_circle(x1, y1, r);             //中点画圆算法调用
    	_getch();                                        //等待一个任意输入结束
    	closegraph();                                    //关闭图形窗口
    	}
    

    ② 程序运行截图(提交你的测试数据及运行结果)

    在这里插入图片描述

    加油加油!

    展开全文
  • OpenGL中使用中点画圆画圆

    万次阅读 2016-10-05 09:50:52
    OpenGL 中采用中点画圆法绘制圆
  • 圆中点Bresenham算法

    2015-03-29 07:56:03
    使用MFC绘制圆中点Bresenham算源程序,直接运行即可看到效果。这是vs2010版程序。参考教材是孔令德编写的《计算机图形学实践教程(Visual C++版)第2版》。
  • 华科图形学,用中点画圆、Bresenham画圆算法绘制整个
  • 绘制算法

    2010-04-15 00:39:00
    算法一,// 中点画圆// 绘制x从0到等于radium/2的八分之一圆弧,其余部分通过对称完成void circleMidpoint(int xCenter, int yCenter, int radium, HDC hDC, COLORREF crColor){ int x = 0, y = radium;...
  • 整个画圆利用了的八对称性,故只需画出八分之一就可利用对称性就可以画出整个。  专门写了一个函数来画圆的点,其中(x0,y0)为圆心坐标,根据(x,y)来画出八对称点,DrawPixel()为绘制点的函数。 function ...
  • 计算机图形学——八分法中点画圆

    千次阅读 2020-03-27 15:06:55
    八分法中点画圆 实现方法:从0°到45°开始画,其余部分进行求对称 1 、绘制X^2+Y^2=R^2的⚪,将⚪划分为八份。我们从第二份开始绘制分析 分析: 最大位移方向是Y方向,因此令y每增加1,x不变或者减少1,我们...
  •  对于一个,这里给出的中点坐标和的半径,同样有三种常用方法。最终使用的依旧是Bresenham。 (1)直角坐标  根据的方程(x– x0) ^ 2 + (y – y0) ^ 2 = r ^2,当一个坐标确定时,另外一个坐标也...
  • 图形学 实验一.zip

    2020-05-12 09:50:50
    本资源包含图形学的实验的报告及源代码,使用easyX库,安装后即可直接编译运行,包含了任意斜率直线、中点画圆、椭圆、圆弧、宽度直线、宽度和椭圆的绘制,代码和报告详细,拿A不是问题
  • 1、实验目的: 理解Bresenham光栅化算法,掌握绘制曲线的...要求一:利用Bresenham中点画圆画出圆形。 要求二:动态表现画圆过程。 要求三:根据Bresenham光栅化画圆算法,以(0,0)为圆心,以100为半径,绘制
  • 这是我在做计算机图形学是做的软件,用的是C#语言。能够实现绘制简单的直线,,椭圆,bezier曲线。实现了图形的橡皮拉伸和图形...用的是基础的算法,如:中点画线中点画圆,bresenham等!界面美观!使用方便
  • 计算机图形学实验

    2021-01-24 23:07:31
    文章目录实验介绍实验内容实验一实验二实验三实验四实验五实验源码 实验介绍 大二学期的计算机图形学课程,内容...实验题1-3:用中点画圆画圆 实验题1-4:中点画圆画椭圆 实验题1-5:中点画圆画圆弧 实
  • HTML5新特性 canvas 实践

    2016-03-12 09:19:57
    HTML5新特性 canvas 实践 —— PainterGitHub地址: ...项目发布地址: http://moyuyc.xyz/painter功能说明绘制基本的点线绘制线采用中点画线 function (paint, color, linewidth) { this.colo
  • DDA 算法* 正负* Bresenham 算法* 中点算法 3 椭圆生成算法2 课时 DDA 算法* 正负* 中点算法 4 区域填充3 课时 三二维几何变换4 课时 四二维观察 1 观察流程以及窗口变换1 课时 2 线段的裁剪2 课时 Cohen-...
  • GSP5.exe

    2020-04-01 09:16:40
    逗号( , ) —— 绘制圆 斜杠( / ) —— 绘制线(包括线段、射线和直线,它们各类型之间可通过重复点击来切换) 分号( ;) —— 绘制圆弧 撇号( ’) —— 绘制多边形 下面以绘制多边形(4边形)为例来说明: 按下撇...
  • 5.2的扫描转换 5.2.1八分画圆 5.2.2中点Bresenham画圆算法 5.3椭圆的扫描转换 5.3.1椭圆的特征 5.3.2椭圆的中点Bresenham算法 5.4多边形的扫描转换与区域填充 5.4.1多边形的扫描转换 5.4.2边缘...
  • 本源码演示了三种VC 直线扫描转换算法,这3种方式是:bresenham方法、数值微分中点画线。本程序同时是一个MFC单文档程序,进行直线段扫面转换算法的算法验证。  1.使用Wizard建立单文档程序;  2.绘制20*20...
  • 2.4 的生成—Bresenham算法 57 2.5 椭圆的生成 64 2.6 一般函数的光栅化 69 2.7 扫描转换—显示的生成 71 2.7.1 实时扫描转换 71 2.7.2 使用指针的简单活化边表 72 2.7.3 排序活化边表 72 2.7.4 使用链表...
  • Python 科学计算

    2018-09-20 16:59:31
    5.1.4 绘制多个子图 ...........................145 5.1.5 配置文件...................................147 5.1.6 在图表中显示中文....................149 5.2 Artist 对象 ......................................

空空如也

空空如也

1 2
收藏数 30
精华内容 12
关键字:

中点法绘制圆