利用直角三角形画圆的算法
另外一种画圆的算法:
算法的数学原理:
我们知道圆的内接三角形中,如果有一条边是直径,那么该边所对应的角度是直角。而在解析几何中,对任意两条斜率存在的直线,如果它们相互垂直,那么它们的斜率相乘为-1,
而倘若是在园外(稍微在圆外一点),则夹角变小,斜率相乘小于-1(待会儿给出证明),倘若在园内一点,则夹角变大,斜率相乘大于-1,如图:
证明:
(由于只需要画出1/8圆即能画出整个圆,因此以下以第二个八分圆证明)
对于B 点
设x =r cos θ, y =r sin θ(r 为圆的半径) 则k BC =r sin θr sin θ, k BA =, r cos θ+r r cos θ-r
k BC *k BA r 2sin 2θ=2=-1。 r (cos2θ-1)
对于B ’点
设x =r cos θ+dx , y =r sin θ
其中dx ∈(0,r -r cos θ) 则k B ' C =r sin θr sin θ, k B ' A = r cos θ+dx +r r cos θ+dx -r
r 2sin 2θk B ' C *k B ' A =(r cos θ+dx ) 2-r 2
dx >0∴k B ' C *k B ' A
同理可得,对于B ”点
k B " C *k B " A >-1
以上是对该数学方法的证明
下面我们讨论一下具体的描点,如图:
设我们已经画出了P 点(P 在第二个八分圆的圆弧上),则我们设P (x ,y ),则下一个应该描的点应该是P1或P2,我们取P1和P2的中点Pmid ,我们只需要判断出Pmid 与圆的关系即可判断应取P1还是P2了,如图:
按照前面的论证方法,我们分别算出了
k PmidA 11y -,k =PmidC =x +1-r x +1+r y -
1(y -) 2
= 2(x +1) -r 2k PmidA *k PmidC
因为是否在圆上是以斜率相乘是否为-1为分界线的,所以我们令k PmidA *k PmidC +1,则 k PmidA *k PmidC 1(y -) 2+(x +1) 2-r 2+1= (x +1) 2-r 2
只需判断出k PmidA *k PmidC +1是否大于0即可
我们观察到,对于第二个八分圆,分母(x +1) -r 0时,则Pmid 在圆外,取P2 当分子(y -) +(x +1) -r
如果相等,则我们约定取P2
这样就可以画出圆来了,但是效率太低了,我们可以稍加改进,将其改变成增量的形式 因为我们已经取了P 点,则我们可以分情况讨论在P 点之前一次的取点情况,共有两种情况,一是P ’点,二是P ”点,则对应这两种情况:
如果是P ’点,则计算的是P ’mid 点的斜率相乘的结果
如果是P ”点,则计算的是P ”mid 点的斜率相乘的结果
我们设a 为每一次的斜率相乘加1后的分子的值,则对应于P ’mid [1**********]2
1a P ' mid =(y +) 2+x 2-r 2 2
而对应于P ”mid
1a P " mid =(y -) 2+x 2-r 2 2
而我们所需要求的Pmid 点的
11a Pmid =(y -) 2+(x +1) 2-r 2=(y +) 2+x 2-r 2+(2x -2y +1) =a P ' mid +(2x -2y +1) 22
11a Pmid =(y -) 2+(x +1) 2-r 2=(y -) 2+x 2-r 2+(2x +1) =a P " mid +(2x +1) 22
由此,我们便将a 的值表示成了增量的形式,通过判断a 的正负来判断该点是在圆内还是圆外,具体的c 代码算法部分如下所示:
float a,x,y,r,espinon=0.00001;
int tag; //tag是用来判别前一个点是P ’还是P ”的 x=0; //tag==1,表示取的是P ’,tag==0,表示取得是P ” r=100; y=r; pDC->SetPixel(0,y,RGB(x,y,((x+y)/2))); a=(y-0.5)*(y-0.5)+(x+1)*(x+1)-r*r; if(a>espinon) { pDC->SetPixel(x+1,y-1,RGB(x,y,((x+y)/2))); x++,y--; tag=1; } else { pDC->SetPixel(x+1,y,RGB(x,y,((x+y)/2))); x++; tag=0; } while(xespinon) { pDC->SetPixel(x+1,y-1,RGB(x,y,((x+y)/2)));
} x++,y--; tag=1; } else { pDC->SetPixel(x+1,y,RGB(x,y,((x+y)/2))); x++; tag=0; } 下图为用该算法画出的圆(圆心坐标是(100,,100),半径是100):
算法的分析到此为止