アトリエ ぺっぺ

トップページ > プログラムTips > 三点から円を求める

◆ 三点から円を求める
三点を通る円を求めるには、次のようにします。
ちょっと長いですが、やっていることは単純です。
#define eps    0.00001
// 0.0か?
#define EQ0(x) ((-eps <= (x)) && ((x) <= eps))
// 同一か?
#define EQ(a, b) (EQ0((a) - (b)))

// 直線の垂直二等分線算出
void CalcPerpLineSeg(double sx, double sy, double ex, double ey, double& a, double& b)
{
    // 線の傾き
    double a1 = (sy - ey) / (sx - ex);

    // 垂直二等分線の傾き
    if(EQ0(a1)){
        a = 1.0;
    }
    else{
        a = -1.0 / a1;
    }
    // 線の中点
    double cx(sx + (ex - sx) / 2.0);
    double cy(sy + (ey - sy) / 2.0);
    // 求める切片
    if(EQ0(a1)){
        b = 0;
    }
    else{
        b = cy - a * cx;
    }
}

bool CircleBy3Point(double x1, double y1, double x2, double y2, double x3, double y3,
                    double& cx, double& cy, double& dRad)
{
    // もし3点の中で同じ点が存在すれば、エラーとして返す
    if( (EQ(x1, x2) && EQ(y1, y2))
    ||  (EQ(x2, x3) && EQ(y2, y3))
    ||  (EQ(x3, x1) && EQ(y3, y1))
    ){
        return false;
    }
    // == 中心を算出 == 
    // 与えられた二点の垂直二等分線を算出
    double a, b, c, d;
    CalcPerpLineSeg(x1, y1, x2, y2, a, b);
    CalcPerpLineSeg(x2, y2, x3, y3, c, d);

    // もし3点が直線上の点なら、円にはならない
    if(EQ0(a - c)){
        return false;
    }
    // 中心を算出
    cx = (d - b) / (a - c);
    cy = a * cx + b;
    // 半径を算出
    dRad = sqrt(pow(cx - x1, 2.0) + pow(cy - y1, 2.0));

    return true;
}
	
※ 解説 この例では、三点を通る円を、次のようにして求めています。
まず、三点を通る、と言うことは、逆に言えばその三点は円周上にある、と言うことになります。

この三点を使い、直線を二本つくります。そして、その垂直二等分線をひいてみると、円の中心で交差することが分かります。

また、中心が求められれば、中心と三点のうちのいずれかの点との距離を求めることにより、半径を求められます。
二点間の距離はこちらをご参照ください。

この方法の条件としては、三点がいずれも違う点であること、三点が同一直線上に並んでいないこと、です。
同一直線上にある三点からは、円は定義できません。
(C) 2002 atelier-peppe
ababa@atelier-peppe.sakura.ne.jp