問題引入
給定二維平面上三個不共線的點 A(x0,y0),B(x1,y1),C(x2,y2), 求出他們形成的圓的圓心和半徑。
問題分析
計算幾何問題常用數形結合解決,不妨設圓心 O(x,y),則滿足三個點到圓心的距離相同。我們可以用兩個等價方程來描述:
(x−x0)2+(y−y0)2=(x−x1)2+(y−y1)2(x−x0)2+(y−y0)2=(x−x2)2+(y−y2)2(1)
現在轉換爲兩個方程解兩個未知數 x,y 的問題。上式化簡後可得兩個線性方程,使用克拉默法則可以容易解出答案。
公式推導
對公式 (1) 分別移項展開消去二次項,得到:
2(x1−x0)x+2(y1−y0)y=x12−x02+y12−y022(x2−x0)x+2(y2−y0)y=x22−x02+y22−y02(2)
如此得到一組二元一次線性方程則,方程有解充要條件是係數矩陣行滿秩,容易發現無解當且僅當三點共線,即行列式(同時也是三點形成兩個向量的叉積)爲0,即
(x1−x0)×(y2−y0)−(x2−x0)×(y1−y0)=0(3)
其他情況下均有解。方便起見以a,b,c,d,e,f,g來代替原係數,即:
ax+by=cdx+ey=f(4)
其中:
a=2(x1−x0)b=2(y1−y0)c=x12−x02+y12−y02d=2(x2−x0)e=2(y2−y0)f=x22−x02+y22−y02(5)
在有解情況下,由克拉默法則可得
x=DDx=ae−dbce−fb
y=DDy=ae−bdaf−dc(6)
於是可在 O(1) 內求出圓心,從而計算可得半徑。
代碼實現
node findO(const node &p,const node &q,const node &r){
double a = 2 * (p.x - q.x);
double b = 2 * (p.y - q.y);
double c = p.x * p.x + p.y * p.y - q.x * q.x - q.y * q.y;
double d = 2 * (p.x - r.x);
double e = 2 * (p.y - r.y);
double f = p.x * p.x + p.y * p.y - r.x * r.x - r.y * r.y;
double g = a*e-b*d;
return {(c*e-f*b)/g,(a*f-d*c)/g};
}
例題
Geometry Problem
其實本題並不是求圓心模板題,但是考慮到本題去掉思維部分可以被視爲2-D版本三點共圓模板題,而且模板題確實難找,故當作模板題放在此處。
高維情況
三維三角形外心
給定三維空間上三個不共線的點A(x0,y0,z0) , B(x1,y1,z1) , C(x2,y2,z2) , 求出他們形成的圓的圓心和半徑。
依據數形結合思路,仍要先把幾何問題轉化爲代數問題:
R=(x−x0)2+(y−y0)2+(z−z0)2 =(x−x1)2+(y−y1)2+(z−z1)2 =(x−x2)2+(y−y2)2+(z−z2)2
其中 (x,y,z) 爲圓心座標,於是得到三個未知數兩個方程。要求解至少還需要一個方程。但是三個點可以確定一張平面,可以通過叉積得到法向量,構造平面方程,如此則轉化爲三元一次線性方程組,且方程係數比較容易求出。容易利用克拉默法則求三階行列式分別求出 x,y,z 的數值。
n維度三角形外心
給定n維空間上三個不共線的點A(x0,y0,z0,...) , B(x1,y1,z1,...) , C(x2,y2,z2,...) , 求出他們形成的圓的圓心和半徑。
類推處理二維和三維情況下的方案,設圓心爲 O(x,y,z,...)。由等距性質得到兩個線性方程。在n維空間下,表徵一個二維平面平面,需要n-2個線性方程。於是綜合上述兩組方程得到n元一次線性方程組,高斯消元可以 O(n3) 處理得到方程的解。