计算机图形学 圆的两种生成算法(角度微分法、Bresenham算法) | 您所在的位置:网站首页 › 圆的多边形逼近算法 › 计算机图形学 圆的两种生成算法(角度微分法、Bresenham算法) |
圆的两种生成算法(角度微分法、Bresenham算法)
文章目录
1.角度微分法的原理
2.角度微分法的实现(基于matlab)
3.Bresenham 算法的原理
4.Bresenham 算法的实现(基于matlab)
1.角度微分法的原理
圆的角度微分法是用圆的内接正多边形来逼近该圆。 若我们设圆的参数方程为: 其中??为旋转角,0° ≤ φ ≤ 360° 现把该圆 n 等分,用 n 条直线来逐次逼近该圆,则各直线的端点坐标计算如下: 设旋转角??的起始角、终止角分别为α、β,且满足关系式0° ≤ α ≤ β ≤ 360° 把圆进行 n 等分,其对应的角度增量为:???? = 2?? ∕ ?? 则可以得到第 i 点所对应的角度与端点坐标为(其中 i = 0 , 1 , 2 , …… , n): 上式即为生成圆的基本公式之一。我们不难看出,n 越大,精度越高,但计算也越 复杂。下一步是如何确定 R 和 n 的关系? 可以这样认为:如果圆的内接多边形的边线与理想圆弧之间的距离在一个刻度单位之内时,其近似显示效果是能接受的。如下图所示: 即:如果线段 ab 的距离在一个刻度单位内都是能被接受的,即要求 ab 那 ab 的距离等于多少呢?显然 ???? = ?? ? ?? ? ?????????? 对于??????????,可按泰勒级数展开取前两项,得到?????????? = 1 ? ????2 / 2 将其带入 ab 中即得到 ?? ? ?? ? (1 ? ????2 / 2 ) 将???? = 2?? / ??带入上式可得?? > ?? ? √(2??) 用经验公式取代得到 ?? = 0.1?? + 15 这就是圆的半径与其内接正多边形边数之间的关系 2.角度微分法的实现(基于matlab)下面给出利用matlab实现该算法的完整代码: 123456789101112131415161718192021function main %测试主函数 clc clear; DifferentiationOfCircle(100,'r') %调用角度微分法 function DifferentiationOfCircle(R,color) %圆的角度微分算法 n = 0.1*R+15; %计算出需要微分的次数 delta = 2*pi/n; %从而得到每次需要增加的角度 alpha = delta; %初始化alpha x0 = R,y0 = 0; %初始化x0,y0 hold on while(n>0) x = R*cos(alpha); y = R*sin(alpha); plot([x0,x],[y0,y]); %绘制点(x0,y0)和(x,y)之间的线段 alpha = alpha + delta; %更新alpha x0 = x , y0 = y; %更新x0、y0 n = n-1; %n减1 end grid minor hold off在matlab中运行上述代码,实验结果如下: 可以看出,角度微分法在绘圆时具有明显的分段现象。当然,我们可以通过加大 n 的值来适当减轻分段效果。不过这样的代价是会使得程序需花费更多的时间来进行微分。 所以这才有了?? = 0.1?? + 15 这一公式的出现。 3.Bresenham 算法的原理圆可被定义为到给定中心位置 O(圆心)距离为 r 的点集。圆心位于原点的圆有四条对称轴 x=0,y=0, x=y 和 x=-y。若已知圆弧上一点(x,y),可以得到其关于四条对称轴的其它 7 个点,这种性质称为八分对称性(如下图所示)。因此,只要扫描转换八分之一圆弧,就可以求出整个圆弧的象素集。 所以接下来我们的重心就放在:如何将某段圆弧尽可能描绘清楚 对于上图中,点(y,x)所在那一段圆弧而言,其特征是 x 坐标变化率大于 y 坐标变化 率,且随着 x 的增加,y 在减小。因此逼近该圆弧的绘点步进规律是:每推算一次,其 x 坐标都加 1,而 y 坐标根据相应误差决定是否减 1。我们易知该圆中最上方的那个点的 坐标为(0,R),将其设为(??0,??0),则有?(??0,??0) = 0)。对于下一点而言,有两种可能: ① (??0+1,??0) ② (??0+1,??0?1) 现在我们的任务就是确定到底取谁。 在高中时,我们对于圆的定义式为:?(??,??) = ??2 + ??2 ? ??2。 这样定义的意义在于:对于某个给定点(??0,??0),其值的正负能反应该点位于圆内 还是圆外。具体的规则如下: 若?(??0,??0) 若?(??0,??0) > 0,则表示该点位于圆外; 若?(??0,??0) = 0,则表示该点位于圆内; 在确定到底取①还是②时,我们实际上并不关心它们到底在圆内还是圆外,我们只 关心它们到底谁距离圆的那一段圆弧更近。因此,我们可以将这两个点带入圆的定义式 中,即得到?(??0+1,??0)、?(??0+1,??0?1),通过加绝对值的方式来获得这两点距离圆弧的绝对距离,最后取其中的较小值作为下一个点的位置即可。 因此,如果我们设: ?(????) = (?????1 + 1)2 + (????)2 ? ??2 ?(????) = (?????1 + 1)2 + (???? ? 1)2 ? ??2 则可以将圆的 Bresenham 算法的偏差判别式定义为: ??? = |?(????)| ? |?(????)| 其原则是: ① 当 ??? ?? 作为下一个绘制的像素点 ② 当 ??? ≥ 0 时,选 ???? 作为下一个绘制的像素点 将上面偏差判别式的绝对值去掉,得到: ??? = ?(????) + ?(????)根据这个判别式,我们可通过一个循环来将八分之一圆弧绘制出,同时通过坐标变 换以将整个圆画出。但是,这个式子里的运算偏多,我们需要对其进行优化,以使整个 绘制过程中,尽量是以迭代运算为主,从而减少复杂的乘幂运算次数。 首先是将????(?????1 + 1, ?????1),????(?????1 + 1,?????1 ? 1)的坐标带入得到: ??? = 2(?????1 + 1)2 + (?????1 ? 1)2 + (?????1)2 ? 2??2 然后增加下标值可得到: ???+1 = 2(???? + 1)2 + (???? ? 1)2 + ????2 ? 2??2 将其作差(???+1 ? ???),得到: ??? = 2((???? + 1)2 ? (?????1 + 1)2) + ((???? ? 1)2 ? (?????1 ? 1)2) + (????2 ? (?????1)2) ① 当??? ??,此时???? = ?????1 + 1, ???? = ?????1,带入上式可得: ??? = 4?????1 + 6; ② 当??? ≥ 0时,选择的下一点是????,此时???? = ?????1 + 1,???? = ?????1 ? 1,带入上式 可得: ??? = 4(?????1 ? ?????1) + 10 。 这样一来,对于 ??? 的求解就由之前的算术求值变为了迭代求值,大大减少了程序的 运算时间。 4.Bresenham 算法的实现(基于matlab)下面给出利用matlab实现该算法的完整代码: 123456789101112131415161718192021222324252627282930313233function main %测试函数 clc clear; Bresenham(100) %调用Bresenham算法 function Plot(x,y) %此函数会将某个点集在对应的8个区域中所构成的弧线绘制出,从而构成一个圆 plot(x,y,'r') %用红色的线绘制第一象限的圆弧 plot(y,x,'r') plot(-x,y,'b') %用蓝色的线绘制第二象限的圆弧 plot(-y,x,'b') plot(-x,-y','y') %用黄色的线绘制第三象限的圆弧 plot(-y,-x,'y') plot(x,-y,'g') %用绿色的线绘制第四象限的圆弧 plot(y,-x','g') function Bresenham(R) %Bresenham算法 d = 0 , n = 1; %初始情况下d=0 x(1) = 0 , y(1) = R; while(x < y) if(d < 0) d = d + 4*x(n) + 6; y(n+1) = y(n); else d = d + 4*(x(n)-y(n)) + 10; y(n+1) = y(n) - 1; end x(n+1) = x(n) + 1; n = n + 1; end hold on; Plot(x,y); grid minor; hold off;在matlab中运行上述代码,实验结果如下: 可以看出,Bresenham 算法在绘圆时不会出现明显的分段现象,但是却存在“抖动”弧。出现这一现象的原因是由于 plot 函数是对像素点进行连结绘制,这个函数并不具有平滑拟合的效果。但如果仅对此算法在描绘圆弧的点上进行评估的话,该算法的效果明显是优于微分算法的。 |
CopyRight 2018-2019 实验室设备网 版权所有 |