canvasで三角形の外接円を描く
canvasで三角形の外接円を描く必要があったのでその際のサンプルコードをアップいたします。
動作サンプルはこちら(Chromeでしか動作確認していません)。
See the Pen 三角形の外接円を描画 by Kazuma Nishihata (@to-r) on CodePen.
400 x 400のcanvas要素の中心に200 x 200のステージ(青枠)を置き、その中にランダムな3角形(緑)を配置し、その外接円(赤)を描画しています。
外接円の中心座標はTercel::Diary: ProcessingでDelaunay分割(解説篇)のページ中部にある【三角形の外接円】という箇所を参考にしています。
次に、3点 (x1, y1), (x2, y2), (x3, y3) で定義される任意の三角形の外接円の求め方について述べる。
ここで、外接円の中心を (x, y) とすると、円の定義より以下が成り立つ。
(x1 - x)2 + (y1 - y)2 = (x2 - x)2 + (y2 - y)2 = (x3 - x)2 + (y3 - y)2
この方程式を x と y について解くと、
x = { (y3 - y1)(x22 - x12 + y22 - y12) + (y1 - y2)(x32 - x12 + y32 - y12) } / c
y = { (x1 - x3)(x22 - x12 + y22 - y12) + (x2 - x1)(x32 - x12 + y32 - y12) } / cとなり、中心座標が得られる。ただし
c = 2 { (x2 - x1)(y3 - y1) - (y2 - y1)(x3 - x1) }
である。
サンプルではTriangleクラスのgetCircumscribedCircleメソッドで定義しており、以下の様なスクリプトになっております。
/**
* 三角形オブジェクト
* @param {Array} points 座標情報
*/
class Triangle extends Polygon{
/**
* 外接円の取得
*/
getCircumscribedCircle() {
//未定義の場合は定義
if(!this._circumscribedCircle){
var x1 = this.points[0].x;
var y1 = this.points[0].y;
var x2 = this.points[1].x;
var y2 = this.points[1].y;
var x3 = this.points[2].x;
var y3 = this.points[2].y;
//各座標の2乗を取得
var x1pow2 = Math.pow(x1,2);
var x2pow2 = Math.pow(x2,2);
var x3pow2 = Math.pow(x3,2);
var y1pow2 = Math.pow(y1,2);
var y2pow2 = Math.pow(y2,2);
var y3pow2 = Math.pow(y3,2);
//公式より中心座標を取得
var c = 2 * ((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1));
var x = ((y3 - y1) * (x2pow2 - x1pow2 + y2pow2 - y1pow2) + (y1 - y2) * (x3pow2 - x1pow2 + y3pow2 - y1pow2)) / c;
var y = ((x1 - x3) * (x2pow2 - x1pow2 + y2pow2 - y1pow2) + (x2 - x1) * (x3pow2 - x1pow2 + y3pow2 - y1pow2)) / c;
//外接円の半径rは、中心から三角形の任意の頂点(x1,y1)までの距離
var r = Math.sqrt(Math.pow(x1 - x,2) + Math.pow(y1 - y,2));
this._circumscribedCircle = new Circle(new Point(x,y),r);
}
return this._circumscribedCircle;
}
}
次はこれを発展させドロネー三角形分割を描いてみます。