arrows blog

解いた問題などを適当に書いていきます。

AOJ 0010 Circumscribed Circle of a Triangle

問題概要

平面上の3点(x1, y1), (x2, y2), (x3, y3)が与えられたとき、それらを頂点とした三角形の外接円の中心座標と半径を求めよ。

制約

  • -100 ≤ x1, y1, x2, y2, x3, y3 ≤ 100
  • データセットの数 ≤ 20

解法

点1と点2の垂直二等分線、点2と点3の垂直二等分線を求め、それぞれl1, l2とする。
l1l2の交点が外接円の中心座標となる。

また、半径は、中心座標からいずれかの点への距離である。

コード

#include <iostream>
#include <cmath>
 
using namespace std;
 
#define EPS (1e-5)
#define equals(a, b) (fabs(a - b) < EPS)
 
struct Point {
    double x, y;
 
    Point(){}
    Point(double x, double y) : x(x), y(y) {}
 
    Point operator + (const Point &p) const {
        return Point(x + p.x, y + p.y);
    }
 
    Point operator - (const Point &p) const {
        return Point(x - p.x, y - p.y);
    }
     
    Point operator * (const double &k) const {
        return Point(x * k, y * k);
    }
};
 
typedef Point Vector;
 
double dot(const Point &a, const Point &b)
{
    return a.x * b.x + a.y * b.y;
}
 
double cross(const Point &a, const Point &b)
{
    return a.x * b.y - b.x * a.y;
}
 
double norm(const Point &p)
{
    return dot(p, p);
} 
 
double abs(const Point &p)
{
    return sqrt(norm(p));
}
 
struct Line {
    Point s, t;
    Line(){}
    Line(Point s, Point t) : s(s), t(t) {}
};
 
Line getPerpendicularBisector(const Point &a, const Point &b)
{
    double cx = (a.x + b.x) / 2.0;
    double cy = (a.y + b.y) / 2.0;
    Point p = Point(cx + (a.y - b.y), cy + (b.x - a.x));
    return Line(Point(cx, cy),p);
}
 
Point crosspointLL(const Line &a, const Line &b)
{
    Vector va = a.t - a.s, vb = b.t - b.s;
    double d = cross(vb, va);
    if (abs(d) < EPS) return b.s;
    return a.s+va*cross(vb, b.t - a.s) * (1.0 / d);
}
 
int main()
{
    Point p[3];
    int N;
    cin >> N;
    while (N--) {
        for (int i = 0; i < 3; i++) {
            cin >> p[i].x >> p[i].y;
        }
        Line l[2];
        for (int i = 0; i < 2; i++) {
            l[i] = getPerpendicularBisector(p[i], p[i+1]);
        }
        Point c = crosspointLL(l[0], l[1]);
        double r = abs(c - p[0]);
        printf("%.3f %.3f %.3f\n", c.x, c.y, r);
    }
    return 0;
}