在计算机屏幕上显示连续的平滑弧线并不容易,因为我们的计算机屏幕是由以矩阵形式组织的像素组成的。因此,要在计算机屏幕上画一个圆,我们应该始终从打印的像素中选择最近的像素,以使它们形成弧形。有两种算法可以做到这一点:
- 中点画圆算法
- 布雷森汉姆的圆图绘制算法
在上一篇文章中我们已经讨论了Mid-Point圆图绘制算法,在这篇文章中,我们将讨论Bresenham的圆图绘制算法。
这两种算法都使用了高度对称的圆的关键特征。因此,对于整个360度的圆,我们将其分为45度的每个八分之八部分。为此,我们将使用Bresenham的Circle算法来计算45度第一个八分之一像素中像素的位置。假定圆以原点为中心。因此,对于它计算的每个像素(x,y),我们在圆的8个八分之一圆的每个像素中绘制一个像素,如下所示:
现在,我们将看到如何根据先前已知的像素位置(x,y)计算下一个像素位置。在布雷森汉姆算法的任意点(x,y)中,我们有两种选择:选择东部的下一个像素(x + 1,y)或东南的下一个像素(x + 1,y-1)。
这可以通过使用决策参数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
现在,对于每个像素,我们将执行以下操作:
- 设置(xc,yc)和(x,y)的初始值
- 将决策参数d设置为d = 3 –(2 * r)。
- 调用drawCircle(int xc,int yc,int x,int y)函数。
- 重复步骤5到8,直到x <= y
- x的增量值。
- 如果d <0,则设置d = d +(4 * x)+ 6
- 否则,将d = d + 4 *(x-y)+ 10设置为y减1。
- 调用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基础课程》。