📜  布雷森汉姆的圆图绘制算法

📅  最后修改于: 2021-05-25 21:14:12             🧑  作者: Mango

在计算机屏幕上显示连续的平滑弧线并不容易,因为我们的计算机屏幕是由以矩阵形式组织的像素组成的。因此,要在计算机屏幕上画一个圆,我们应该始终从打印的像素中选择最近的像素,以使它们形成弧形。有两种算法可以做到这一点:

  1. 中点画圆算法
  2. 布雷森汉姆的圆图绘制算法

在上一篇文章中我们已经讨论了Mid-Point圆图绘制算法,在这篇文章中,我们将讨论Bresenham的圆图绘制算法。

这两种算法都使用了高度对称的圆的关键特征。因此,对于整个360度的圆,我们将其分为45度的每个八分之八部分。为此,我们将使用Bresenham的Circle算法来计算45度第一个八分之一像素中像素的位置。假定圆以原点为中心。因此,对于它计算的每个像素(x,y),我们在圆的8个八分之一圆的每个像素中绘制一个像素,如下所示:

圈1

现在,我们将看到如何根据先前已知的像素位置(x,y)计算下一个像素位置。在布雷森汉姆算法的任意点(x,y)中,我们有两种选择:选择东部的下一个像素(x + 1,y)或东南的下一个像素(x + 1,y-1)。

圈2

这可以通过使用决策参数d来确定:

  • 如果d> 0,则将选择(x + 1,y-1)作为下一个像素,因为它将更靠近圆弧。
  • 否则(x + 1,y)将被选作下一个像素。

现在绘制给定半径“ r”和中心(xc,yc)的圆,我们将从(0,r)开始并在第一象限中移动,直到x = y(即45度)。我们应该从列出的初始条件开始:

d = 3 - (2 * r)
x = 0
y = r

现在,对于每个像素,我们将执行以下操作:

  1. 设置(xc,yc)和(x,y)的初始值
  2. 将决策参数d设置为d = 3 –(2 * r)。
  3. 调用drawCircle(int xc,int yc,int x,int y)函数。
  4. 重复步骤5到8,直到x <= y
  5. x的增量值。
  6. 如果d <0,则设置d = d +(4 * x)+ 6
  7. 否则,将d = d + 4 *(x-y)+ 10设置为y减1。
  8. 调用drawCircle(int xc,int yc,int x,int y)函数

drawCircle()函数:

CPP
// function to draw all other 7 pixels
// present at symmetric position
drawCircle(int xc, int yc, int x, int y)
{
    putpixel(xc+x, yc+y, RED);
    putpixel(xc-x, yc+y, RED);
    putpixel(xc+x, yc-y, RED);
    putpixel(xc-x, yc-y, RED);
    putpixel(xc+y, yc+x, RED);
    putpixel(xc-y, yc+x, RED);
    putpixel(xc+y, yc-x, RED);
    putpixel(xc-y, yc-x, RED);
}


CPP
// C-program for circle drawing
// using Bresenham’s Algorithm
// in computer-graphics
#include 
#include 
#include 
 
// Function to put pixels
// at subsequence points
void drawCircle(int xc, int yc, int x, int y)
{
    putpixel(xc+x, yc+y, RED);
    putpixel(xc-x, yc+y, RED);
    putpixel(xc+x, yc-y, RED);
    putpixel(xc-x, yc-y, RED);
    putpixel(xc+y, yc+x, RED);
    putpixel(xc-y, yc+x, RED);
    putpixel(xc+y, yc-x, RED);
    putpixel(xc-y, yc-x, RED);
}
 
// Function for circle-generation
// using Bresenham's algorithm
void circleBres(int xc, int yc, int r)
{
    int x = 0, y = r;
    int d = 3 - 2 * r;
    drawCircle(xc, yc, x, y);
    while (y >= x)
    {
        // for each pixel we will
        // draw all eight pixels
         
        x++;
 
        // check for decision parameter
        // and correspondingly
        // update d, x, y
        if (d > 0)
        {
            y--;
            d = d + 4 * (x - y) + 10;
        }
        else
            d = d + 4 * x + 6;
        drawCircle(xc, yc, x, y);
        delay(50);
    }
}
 
 
// Driver code
int main()
{
    int xc = 50, yc = 50, r2 = 30;
    int gd = DETECT, gm;
    initgraph(&gd, &gm, "");  // initialize graph
    circleBres(xc, yc, r);    // function call
    return 0;
}


以下是上述方法的C实现。

CPP

// C-program for circle drawing
// using Bresenham’s Algorithm
// in computer-graphics
#include 
#include 
#include 
 
// Function to put pixels
// at subsequence points
void drawCircle(int xc, int yc, int x, int y)
{
    putpixel(xc+x, yc+y, RED);
    putpixel(xc-x, yc+y, RED);
    putpixel(xc+x, yc-y, RED);
    putpixel(xc-x, yc-y, RED);
    putpixel(xc+y, yc+x, RED);
    putpixel(xc-y, yc+x, RED);
    putpixel(xc+y, yc-x, RED);
    putpixel(xc-y, yc-x, RED);
}
 
// Function for circle-generation
// using Bresenham's algorithm
void circleBres(int xc, int yc, int r)
{
    int x = 0, y = r;
    int d = 3 - 2 * r;
    drawCircle(xc, yc, x, y);
    while (y >= x)
    {
        // for each pixel we will
        // draw all eight pixels
         
        x++;
 
        // check for decision parameter
        // and correspondingly
        // update d, x, y
        if (d > 0)
        {
            y--;
            d = d + 4 * (x - y) + 10;
        }
        else
            d = d + 4 * x + 6;
        drawCircle(xc, yc, x, y);
        delay(50);
    }
}
 
 
// Driver code
int main()
{
    int xc = 50, yc = 50, r2 = 30;
    int gd = DETECT, gm;
    initgraph(&gd, &gm, "");  // initialize graph
    circleBres(xc, yc, r);    // function call
    return 0;
}

输出:

圈出

好处

  • 这是一个简单的算法。
  • 它可以轻松实现
  • 它完全基于圆的方程,即x 2 + y 2 = r 2

缺点

  • 生成点时存在精度问题。
  • 该算法不适用于复杂的高图形图像。
想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。