OpenGL 实现Bresenham法绘制圆图元…

本文探讨了在计算机图形学中使用Bresenham算法和中点画圆方法来绘制圆,重点解释了它们如何避免平方运算,并通过比较像素与圆的距离来实现高效的圆绘制过程。详细介绍了算法实现步骤和关键代码片段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

圆方程为非线性的,计算像素与圆的距离必须进行平方运算,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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值