【计算机图形学】圆绘制算法-Bresenham
原理分析与算法描述
-
待绘制的圆弧
圆心在原点,半径为R的第一象限上的一段圆弧。且取(0,R)为起点,按顺时针方向绘制该1/8圆弧。
-
决策方程
F(x,y)=x2+y2−R2 F(x,y)=x^2+y^2-R^2 F(x,y)=x2+y2−R2
对于圆上的点,有F(x,y)=0;对于圆外的点,F(x,y)>0;
对于圆内的点,F(x,y)<0。

M的坐标为:M(xi+1,yi−0.5)M(x_i+1,y_i-0.5)M(xi+1,yi−0.5)
•当F(xM,yM)<0F(x_M,y_M)<0F(xM,yM)<0时,取Pu(xi+1,yi)P_u(x_i+1,y_i)Pu(xi+1,yi)
•当F(xM,yM)>0F(x_M,y_M)>0F(xM,yM)>0时,取Pd(xi+1,yi−1)P_d(x_i+1,y_i-1)Pd(xi+1,yi−1)
•当F(xM,yM)=0F(x_M,y_M)=0F(xM,yM)=0时,约定取PuP_uPu。
-
构造判别式
di=F(xM,yM)=F(xi+1,yi−0.5)=(xi+1)2+(yi−0.5)2−R2 d_i=F(x_M,y_M)=F(x_i+1,y_i-0.5)=(x_i+1)^2+(y_i-0.5)^2-R^2 di=F(xM,yM)=F(xi+1,yi−0.5)=(xi+1)2+(yi−0.5)2−R2
•当di≤0d_i≤0di≤0时,下一点取Pu(xi+1,yi)P_u(x_i+1,y_i)Pu(xi+1,yi);•当di>0d_i>0di>0时,下一点取Pd(xi+1,yi−1)P_d(x_i+1,y_i-1)Pd(xi+1,yi−1)。
-
误差项的递推
di<=0,di+1=F(xi+2,yi−0.5)=di+2xi+3d_i<=0,d_{i+1}=F(x_i+2,y_i-0.5)=d_i+2x_i+3di<=0,di+1=F(xi+2,yi−0.5)=di+2xi+3;
di>0,di+1=F(xi+2,yi−1.5)=di+2(xi−yi)+5d_i>0,d_{i+1}=F(x_i+2,y_i-1.5)=d_i+2(x_i-y_i)+5di>0,di+1=F(xi+2,yi−1.5)=di+2(xi−yi)+5;
d0=F(1,R−0.5)=1.25−Rd_0=F(1,R-0.5)=1.25-Rd0=F(1,R−0.5)=1.25−R
-
算法步骤
1.输入圆的半径R。
2.计算初始值d=1.25-R、x=0、y=R。
3.绘制点(x,y)及其在八分圆中的另外七个对称点。
4.判断d的符号。若d≤0,则先将d更新为d+2x+3,再将(x,y)更新为(x+1,y);否则先将d更新为d+2(x-y)+5,再将(x,y)更新为(x+1,y-1)。
5.当x<=y时,重复步骤3和4。否则结束。
代码实现
std::vector<Point> DrawCircle(Point center, float radius)
{
std::vector<Point> points;
int x = 0, y = radius;
int d = 1.25 - radius;//决策变量初始值
int xc = center.x, yc = center.y;
while (y >= x) {//八对称点
points.push_back({ xc + x, yc + y });
points.push_back({ xc + x, yc - y });
points.push_back({ xc - x, yc + y });
points.push_back({ xc - x, yc - y });
points.push_back({ xc + y, yc + x });
points.push_back({ xc + y, yc - x });
points.push_back({ xc - y, yc + x });
points.push_back({ xc - y, yc - x });
if (d <= 0) {//更新决策变量和坐标
d = d + 2 * x + 3;
x += 1;
}
else {
d = d + 2 * (x - y) + 5;
x += 1, y -= 1;
}
}
return points;
}
结果展示

算法优化
- 改进:用d-0.25代替d,减少浮点数运算
更多推荐

所有评论(0)