3点を通る円の中心と半径を求める
点 $A(x_1,y_1)$、点 $B(x_2,y_2)$、点 $C(x_3,y_3)$ を通る円の中心 $P$ と半径 $r$ を求める。
求め方
3点を通る円の中心は、その三点を頂点とする三角形の外心となる。
(求める円はその三点を頂点とする三角形の外接円)
三角形の各辺の垂直二等分線の交点がその三角形の外心となる。
外心は3つの頂点から等距離にある。
その外心から各点の頂点の距離が円の半径となる。
外心の求め方
- 点 $A$ と点 $B$ の中点 $D$ を求める
- 点 $A$ と点 $B$ を通る直線に垂直な 点 $D$ を通る直線 $L_1$ を求める
- 点 $A$ と点 $C$ の中点 $E$ を求める
- 点 $A$ と点 $C$ を通る直線に垂直な 点 $E$ を通る直線 $L_2$ を求める
- 直線 $L_1$ と直線 $L_2$ の交点を求める
求める
点 $A$ と点 $B$ の中点 $D$ は、
$$D=\left(\frac{x_1+x_2}{2},\frac{y_1+y_2}{2}\right)$$
点 $A$ と点 $B$ を通る直線の方程式は、(直線の方程式 参照)
$$(y_2-y_1)x+(x_1-x_2)y+(x_2y_1-x_1y_2)=0$$
この直線の法線ベクトルは、$\{(y_2-y_1),(x_1-x_2)\}$ なので、
点 $A$ と点 $B$ を通る直線に垂直な直線の傾きは、 $\dfrac{x_1-x_2}{y_2-y_1}$
よって、直線 $L_1$ の方程式は、1点と傾きが与えられた直線の方程式の公式により、
$$y-\frac{y_1+y_2}{2}=\frac{x_1-x_2}{y_2-y_1}\left(x-\frac{x_1+x_2}{2}\right)$$
右辺を展開して、
$$y-\frac{y_1+y_2}{2}=\frac{x(x_1-x_2)}{y_2-y_1}-\frac{(x_1+x_2)(x_1-x_2)}{2(y_2-y_1)}$$
$$y-\frac{y_1+y_2}{2}=\frac{2x(x_1-x_2)-(x_1+x_2)(x_1-x_2)}{2(y_2-y_1)}$$
両辺に $2(y_2-y_1)$ を掛けて、
$$2y(y_2-y_1)-(y_1+y_2)(y_2-y_1)=2x(x_1-x_2)-(x_1+x_2)(x_1-x_2)$$
片方の辺に集めて、
$$2x(x_1-x_2)+2y(y_1+y_2)+\{(x_2+x_1)(x_2-x_1)+(y_2+y_1)(y_2-y_1)\}=0$$
よって、
$$L_1 : (x_1-x_2)x+(y_1-y_2)y+\frac{x_2^2-x_1^2+y_2^2-y_1^2}{2}=0\ \cdots \ ①$$
同じ要領で、点 $A$ と点 $C$ を通る直線に垂直な 中点 $E$ を通る直線 $L_2$ を求めると、
$$L_2 : (x_1-x_3)x+(y_1-y_3)y+\frac{x_3^2-x_1^2+y_3^2-y_1^2}{2}=0\ \cdots \ ②$$
2直線の交点を求める 公式を使って、$L_1$ と $L_2$ の交点を求める。
交点を $P$ とし、その座標を $(x_p,y_p)$ とすると、
$$x_p=\frac{(y_1-y_2)(x_3^2-x_1^2+y_3^2-y_1^2)-(y_1-y_3)(x_2^2-x_1^2+y_2^2-y_1^2)}{2(x_1-x_2)(y_1-y_3)-2(x_1-x_3)(y_1-y_2)}$$
$$y_p=\frac{(x_1-x_3)(x_2^2-x_1^2+y_2^2-y_1^2)-(x_1-x_2)(x_3^2-x_1^2+y_3^2-y_1^2)}{2(x_1-x_2)(y_1-y_3)-2(x_1-x_3)(y_1-y_2)}$$
となる。
また、半径 $r$ は、点 $A$ から点 $P$ までの距離を、2点間の距離の公式を使って求めると、
$$ r = \sqrt{(x_p - x_1)^2 + (y_p - y_1)^2}$$
となる。
3点を指示して円を作成するプログラム
;; 3点を指示して円を作成
(defun c:ThreePointCircle (/ p1 p2 p3 c)
(setq p1 (getpoint "\n1点目を指示")
p2 (getpoint "\n2点目を指示")
p3 (getpoint "\n3点目を指示")
c (circle:3Points p1 p2 p3)
)
(entmake:Circle (car c) (cadr c))
(princ)
)
;; == sub functions ==
;; 3点を通る円の中心と半径を求める
(defun circle:3Points (p1 p2 p3
/ x1 x2 x3 y1 y2 y3 x1-x2 x1-x3y1-y2 y1-y3 a b c c1 c2 xp yp)
(setq x1 (car p1)
y1 (cadr p1)
x2 (car p2)
y2 (cadr p2)
x3 (car p3)
y3 (cadr p3)
)
(setq x1-x2 (- x1 x2)
x1-x3 (- x1 x3)
y1-y2 (- y1 y2)
y1-y3 (- y1 y3)
c1 (- (+ (- (* x2 x2)(* x1 x1))(* y2 y2))(* y1 y1))
c2 (- (+ (- (* x3 x3)(* x1 x1))(* y3 y3))(* y1 y1))
a (- (* 2 x1-x2 y1-y3)(* 2 x1-x3 y1-y2))
b (- (* y1-y2 c2) (* y1-y3 c1))
c (- (* x1-x3 c1) (* x1-x2 c2))
)
(setq xp (/ b a)
yp (/ c a))
(list (list xp yp) (sqrt (+ (* (- xp x1) (- xp x1))(* (- yp y1) (- yp y1)))))
)
;; 中心と半径を指定して円を作成
(defun entmake:CircleBase (c r) (list '(000 . "CIRCLE") (cons 10 c) (cons 40 r)))
(defun entmake:Circle (c r) (entmake (entmake:CircleBase c r)) (entlast))
3点を指示して円を作成するプログラム(AutoLISP関数使用)
;; 3点を指示して円を作成
(defun c:ThreePointCircle2 (/ p1 p2 p3)
(setq p1 (getpoint "\n1点目を指示")
p2 (getpoint "\n2点目を指示")
p3 (getpoint "\n3点目を指示")
)
(entmake:CircleFrom3Points p1 p2 p3)
(princ)
)
;; == sub functions ==
;; 円周上の3点から円の中心を求める(AutoLISP関数使用)
(defun circle:GetCenterPointFrom3Points (p1 p2 p3 / ma mb va vb)
(if (setq ma (mapcar '(lambda (a b) (/ (+ a b) 2.)) p1 p2)
va (mapcar '- p2 p1)
mb (mapcar '(lambda (a b) (/ (+ a b) 2.)) p2 p3)
vb (mapcar '- p3 p2)
)
(inters ma (mapcar '+ ma (list (- (cadr va)) (car va) 0))
mb (mapcar '+ mb (list (- (cadr vb)) (car vb) 0))
nil
)
)
)
;; 中心と半径を指定して円を作成
(defun entmake:CircleBase (c r) (list '(000 . "CIRCLE") (cons 10 c) (cons 40 r)))
(defun entmake:Circle (c r) (entmake (entmake:CircleBase c r)) (entlast))
;; 3点を指定して円を作成
(defun entmake:CircleFrom3Points (p1 p2 p3 / cp)
(entmake:Circle
(setq cp (circle:GetCenterPointFrom3Points p1 p2 p3))
(distance cp p1)
)
)