九点円(nine-point circle)をPythonで計算する

オイラー線について調べていたら、今度はオイラー円(Euler’s circle)というのがでてきました。一般的には九点円(nine-point circle)、フォイエルバッハ円(Feuerbach circle)といわれているようです。どういうものかというと、三角形の各辺の中点、頂点と垂心の中点、垂心から各辺に下した足、計9つの点が同一線上に並ぶという恐ろしいことが起こるようです。証明は別として実験してみます。

はじめに、点lから点p1,p2に下した垂線の足の座標を計算するp_legs_line関数をつくります。

def p_legs(a,b,c,p):
    d=abs(a*p[0]+b*p[1]+c)/(a**2+b**2)**0.5
    x=(b**2*p[0]-a*b*p[1]-a*c)/(a**2+b**2)
    y=(a**2*p[1]-a*b*p[0]-b*c)/(a**2+b**2)
    return d,(x,y)

def l_formula(p1,p2):
    a=p2[1]-p1[1]
    b=p1[0]-p2[0]
    c=p1[1]*p2[0]-p1[0]*p2[1]
    return a,b,c

def p_legs_line(p1,p2,l):
    return p_legs(*l_formula(p1,p2),l)[1]          

p_legs_line((0,0),(2,0),(1,1))

例として、点(1,1)から、2点(0,0),(2,0)を通る直線に下した垂線の足の座標は、p_legs_line関数を適用することにより(1,0)になります。これを使い、中点を通る円、垂心からの足、頂点と垂心の中点の中心を計算します。中心というのは3点を通る点を三角形の外接円と考え、その中心と考えればよいと思われます。

pa=(12,18)
pb=(390,18)
pc=(102,138)

ma=i_division(pa,pb,1,1)
mb=i_division(pb,pc,1,1)
mc=i_division(pc,pa,1,1)
o=orthocenter(pa,pb,pc)
print('中点を通る円の中心',circumcenter(ma,mb,mc))  
print('垂心からの足の中心',circumcenter(p_legs_line(pa,pb,o),p_legs_line(pb,pc,o),p_legs_line(pc,pa,o)))
print('頂点と垂心の中点の中心',circumcenter(i_division(pa,o,1,1),i_division(pb,o,1,1),i_division(pc,o,1,1)))
中点を通る円の中心 [151.5, 102.0]
垂心からの足の中心 [151.49999999999991, 102.00000000000001]
頂点と垂心の中点の中心 [151.50000000000003, 101.99999999999999]

少し誤差があるものの、(151.5,102)ということで一致しました。これのどこがすごいかというと、この点はオイラー線の中点となることです。また、ついでに九点円の半径も計算します。

print('オイラー線の中点',i_division(o,circumcenter(pa,pb,pc),1,1))
print('九点円の半径',length(circumcenter(ma,mb,mc),ma))

このように、オイラー円は面白いことに使えそうで、とても重要な考え方のようです。その証拠にSymPyにもオイラー円の中心と半径を求める機能があります。

import sympy.geometry 
A, B, C = sympy.geometry.Point(pa), sympy.geometry.Point(pb), sympy.geometry.Point(pc)
tri_s = sympy.geometry.Triangle(A, B, C)
print(tri_s.nine_point_circle)
Circle(Point2D(303/2, 102), 195/2)

結果は上記と一致します。

この記事を書いた人

目次
閉じる