三角形の外接円の中心を求めるコード

ただなんとなく学校のJavaの課題のコードがあまりにも計算機パワーに頼りがちなコードだったので、これを 外接円の中心は2つの垂直二等分線の交点 という基礎的な事実に基づいてコードを書いてみた。

ちなみに a2*a6-a3*a5 が0に近づいたときなどのエラー処理はおこなってない。

あと、l: y = \alpha xm: y = \beta x で、lmが直交するとき、\alpha \times \beta = -1 になる理屈がちょっと分からなくて混乱した。まあ、\tanを使えば簡単に分かったけど。

circle.c (私が書いたやつ)

#include <stdio.h>

typedef struct __Point {
	double x;
	double y;
} Point;

void CalcPoint(Point p, Point q, Point r, Point *ret)
{
	double a1 = q.y + r.y;
	double a4 = q.x + r.x;
	double a7 = p.x + q.x;
	double a8 = p.y + q.y;
	double a2 = q.x - r.x;
	double a3 = q.y - r.y;
	double a5 = p.x - q.x;
	double a6 = p.y - q.y;
	
	ret->x = (a1*a3*a6+a2*a4*a6-a3*a5*a7-a3*a6*a8)/(a2*a6-a3*a5)/2.0;
	ret->y = -a5/a6 * ret->x + a8/2.0 + (a5*a7)/(a6*2.0);
	
	return;
}

int main(int argc, char *argv[])
{
	Point p;
	Point q;
	Point r;
	
	Point ans;
	
	/* 点(15, 1) */
	p.x = 15, p.y = 1;
	
	/* 点(1, 5) */
	q.x = 1, q.y = 5;
	
	/* 点(4, 0) */
	r.x = 4, r.y = 0;
	
	CalcPoint(p, q, r, &ans);
	
	printf("x = %.15lf, y = %.15lf\n", ans.x, ans.y);

	return 0;
}

また、学校で使われたコードを載せてみようと思う。Javaなので関係するメソッドだけを抜粋する。それにしても、あんまりだよなあ、と感じる。

Point.java (一部分)

	/**
	 * 自分自身と引数で指定された2つの点の合計3点から、
	 * ほぼ同一の距離にある点を近似的に計算して求める
	 * 
	 * calculate approximate center point of this, p1 and p2
	 * 
	 * @param p1
	 *            destination1
	 * @param p2
	 *            destination2
	 * @return approximate center point
	 */
	public Point center(Point p1, Point p2) {
		// define candidate point
		Point p = center(p1).center(p2);
		Point[] pp = new Point[] { this, p1, p2 };
		double[] dist = new double[pp.length];

		int count = 0;
		double maxdiff;
		do {
			// calculate distances from candidate to 3 points
			double avg = 0;
			for (int i = 0; i < pp.length; i++) {
				dist[i] = p.distanceTo(pp[i]);
				avg += dist[i];
			}
			avg /= pp.length;

			// edge up
			double dx = 0.0, dy = 0.0, dz = 0.0;
			maxdiff = 0.0;
			for (int i = 0; i < pp.length; i++) {
				dist[i] /= avg;
				if (maxdiff < Math.abs(dist[i] - 1.0)) {
					maxdiff = Math.abs(dist[i] - 1.0);
				}
				dx += (Math.sqrt(dist[i]) - 1.0) * (pp[i].x - p.x);
				dy += (Math.sqrt(dist[i]) - 1.0) * (pp[i].y - p.y);
				dz += (Math.sqrt(dist[i]) - 1.0) * (pp[i].z - p.z);
			}
			p.x += dx;
			p.y += dy;
			p.z += dz;

			count++;
		} while (maxdiff > 1.0E-15 && count < 3000);

		return p;
	}