已知a,b,c三点求过这三点的圆心坐标
a ( x 1 , y 1 ) a(x_1, y_1) a(x1,y1) 、 b ( x 2 , y 2 ) b(x_2, y_2) b(x2,y2) 、 c ( x 3 , y 3 ) c(x_3, y_3) c(x3,y3)
确认三点是否共线
叉积计算方式
v
→
(
X
1
,
Y
1
)
×
u
→
(
X
2
,
Y
2
)
=
X
1
Y
2
−
X
2
Y
1
\overrightarrow{v}(X_1, Y_1) \times \overrightarrow{u}(X_2, Y_2) = X_1Y_2 - X_2Y_1
v(X1,Y1)×u(X2,Y2)=X1Y2−X2Y1
使用叉积判断三个点是否共线
a
b
→
=
(
(
x
2
−
x
1
)
,
(
y
2
−
y
1
)
)
a
c
→
=
(
(
x
3
−
x
1
)
,
(
y
3
−
y
1
)
)
\overrightarrow{ab} = ((x_2- x_1) , (y_2- y_1)) \\ \overrightarrow{ac} = ((x_3- x_1) , (y_3- y_1))
ab=((x2−x1),(y2−y1))ac=((x3−x1),(y3−y1))
带入上方可到的:
v
a
l
u
e
=
(
x
2
−
x
1
)
(
y
3
−
y
1
)
−
(
x
3
−
x
1
)
(
y
2
−
y
1
)
v
a
l
u
e
=
x
2
y
3
−
x
2
y
1
−
x
1
y
3
+
x
1
y
1
−
x
3
y
2
+
x
3
y
1
+
x
1
y
2
−
x
1
y
1
\begin{aligned} value &= (x_2 - x_1)(y_3 - y_1) - (x_3 - x_1)(y_2 - y_1) \\ value &= x_2y_3 - x_2y_1-x_1y_3+x_1y_1-x_3y_2+x_3y_1+x_1y_2-x_1y_1 \\ \end{aligned}
valuevalue=(x2−x1)(y3−y1)−(x3−x1)(y2−y1)=x2y3−x2y1−x1y3+x1y1−x3y2+x3y1+x1y2−x1y1
整合后得到
v
a
l
u
e
=
x
1
(
y
2
−
y
3
)
+
x
2
(
y
3
−
y
1
)
+
x
3
(
y
1
−
y
2
)
value = x_1(y_2-y_3)+x_2(y_3-y_1)+x_3(y_1-y_2)
value=x1(y2−y3)+x2(y3−y1)+x3(y1−y2)
{
v
a
l
u
e
<
0
点
b
在
a
c
→
右边
v
a
l
u
e
>
0
点
b
在
a
c
→
左边
v
a
l
u
e
=
0
三点共线
\begin{cases} value & < 0 &点b在\overrightarrow{ac}右边\\ value & > 0 &点b在\overrightarrow{ac}左边\\ value & = 0 &三点共线 \\ \end{cases}
⎩
⎨
⎧valuevaluevalue<0>0=0点b在ac右边点b在ac左边三点共线
不共线的三点才可以确认一个圆
三点求解圆心
已知圆的方程为
(
x
−
x
0
)
2
+
(
y
−
y
0
)
2
=
r
2
(x-x_0)^2+(y-y_0)^2=r^2
(x−x0)2+(y−y0)2=r2
假设圆心坐标为
O
(
a
,
b
)
O(a,b)
O(a,b)带入三点可以得到下列方程
{
(
x
1
−
a
)
2
+
(
y
1
−
b
)
2
=
r
2
①
(
x
2
−
a
)
2
+
(
y
2
−
b
)
2
=
r
2
②
(
x
3
−
a
)
2
+
(
y
3
−
b
)
2
=
r
2
③
\begin{cases} (x_1 - a)^2+(y_1 - b)^2=r^2 &①\\ (x_2 - a)^2+(y_2 - b)^2=r^2 &②\\ (x_3 - a)^2+(y_3 - b)^2=r^2 &③\\ \end{cases}
⎩
⎨
⎧(x1−a)2+(y1−b)2=r2(x2−a)2+(y2−b)2=r2(x3−a)2+(y3−b)2=r2①②③
拆解后可得
{
x
1
2
−
2
x
1
a
+
a
2
+
y
1
2
−
2
y
1
b
+
b
2
=
r
2
①
x
2
2
−
2
x
2
a
+
a
2
+
y
2
2
−
2
y
2
b
+
b
2
=
r
2
②
x
3
2
−
2
x
3
a
+
a
2
+
y
3
2
−
2
y
3
b
+
b
2
=
r
2
③
\begin{cases} x_1^2 - 2x_1a+a^2 + y_1^2-2y_1b+b^2=r^2 &①\\ x_2^2 - 2x_2a+a^2 + y_2^2-2y_2b+b^2=r^2 &②\\ x_3^2 - 2x_3a+a^2 + y_3^2-2y_3b+b^2=r^2 &③\\ \end{cases}
⎩
⎨
⎧x12−2x1a+a2+y12−2y1b+b2=r2x22−2x2a+a2+y22−2y2b+b2=r2x32−2x3a+a2+y32−2y3b+b2=r2①②③
使用①-②,②-③。构造两个方程组
{
a
(
x
2
−
x
1
)
+
b
(
y
2
−
y
1
)
=
(
x
2
2
+
y
2
2
)
−
(
x
1
2
+
y
1
2
)
2
①
−
②
a
(
x
3
−
x
2
)
+
b
(
y
3
−
y
2
)
=
(
x
3
2
+
y
3
2
)
−
(
x
2
2
+
y
2
2
)
2
②
−
③
\begin{cases} a(x_2-x_1)+b(y_2-y_1)=\frac{(x_2^2+y_2^2)-(x_1^2+y_1^2)}{2} &①-②\\ a(x_3-x_2)+b(y_3-y_2)=\frac{(x_3^2+y_3^2)-(x_2^2+y_2^2)}{2} &②-③\\ \end{cases}
{a(x2−x1)+b(y2−y1)=2(x22+y22)−(x12+y12)a(x3−x2)+b(y3−y2)=2(x32+y32)−(x22+y22)①−②②−③
我们可以给计算方程简化一下
A
1
=
x
2
−
x
1
B
1
=
y
2
−
y
1
A
2
=
x
3
−
x
2
B
2
=
y
3
−
y
2
C
1
=
(
x
2
2
+
y
2
2
)
−
(
x
1
2
+
y
1
2
)
2
C
2
=
(
x
3
2
+
y
3
2
)
−
(
x
2
2
+
y
2
2
)
2
\begin{aligned} A_1 &= x_2-x_1 \\ B_1 &= y_2-y_1 \\ A_2 &= x_3-x_2 \\ B_2 &= y_3-y_2 \\ C_1 &= \frac{(x_2^2+y_2^2)-(x_1^2+y_1^2)}{2} \\ C_2 &= \frac{(x_3^2+y_3^2)-(x_2^2+y_2^2)}{2} \\ \end{aligned}
A1B1A2B2C1C2=x2−x1=y2−y1=x3−x2=y3−y2=2(x22+y22)−(x12+y12)=2(x32+y32)−(x22+y22)
则可的方程组
A
1
a
+
B
1
b
=
C
1
A
2
a
+
B
2
b
=
C
2
A_1a+B_1b=C_1 \\ A_2a+B_2b=C_2 \\
A1a+B1b=C1A2a+B2b=C2
使用矩阵求解这个方程组
(
A
1
B
1
A
2
B
2
)
(
a
b
)
=
(
C
1
C
2
)
\begin{pmatrix} A_1 & B_1 \\ A_2 & B_2 \\ \end{pmatrix} \begin{pmatrix} a \\ b \\ \end{pmatrix} = \begin{pmatrix} C_1 \\ C_2 \\ \end{pmatrix}
(A1A2B1B2)(ab)=(C1C2)
可得
(
a
b
)
=
1
A
1
B
2
−
A
2
B
1
(
B
2
−
B
1
−
A
2
A
1
)
(
C
1
C
2
)
\begin{pmatrix} a \\ b \\ \end{pmatrix} = \frac{1}{ A_1B_2-A_2B_1 } \begin{pmatrix} B_2 & -B_1 \\ -A_2 & A_1 \\ \end{pmatrix} \begin{pmatrix} C_1 \\ C_2 \\ \end{pmatrix}
(ab)=A1B2−A2B11(B2−A2−B1A1)(C1C2)
( a b ) = ( B 2 A 1 B 2 − A 2 B 1 − B 1 A 1 B 2 − A 2 B 1 − A 2 A 1 B 2 − A 2 B 1 A 1 A 1 B 2 − A 2 B 1 ) ( C 1 C 2 ) = ( B 2 C 1 − B 1 C 2 A 1 B 2 − A 2 B 1 A 1 C 2 − A 2 C 1 A 1 B 2 − A 2 B 1 ) \begin{pmatrix} a \\ b \\ \end{pmatrix} = \begin{pmatrix} \frac{B_2}{A_1B_2-A_2B_1} & \frac{-B_1}{A_1B_2-A_2B_1} \\ \frac{-A_2}{A_1B_2-A_2B_1} & \frac{A_1}{A_1B_2-A_2B_1} \\ \end{pmatrix} \begin{pmatrix} C_1 \\ C_2 \\ \end{pmatrix} = \begin{pmatrix} \frac{B_2C_1-B_1C_2}{A_1B_2-A_2B_1}\\ \frac{A_1C_2-A_2C_1}{A_1B_2-A_2B_1}\\ \end{pmatrix} (ab)=(A1B2−A2B1B2A1B2−A2B1−A2A1B2−A2B1−B1A1B2−A2B1A1)(C1C2)=(A1B2−A2B1B2C1−B1C2A1B2−A2B1A1C2−A2C1)
这样我们就得到了圆心
O
(
a
,
b
)
O(a,b)
O(a,b)的坐标,同时我们也发现了一个很奇特的现象
上面再做共线条判断的时候我们求了叉积
v
a
l
u
e
=
x
1
(
y
2
−
y
3
)
+
x
2
(
y
3
−
y
1
)
+
x
3
(
y
1
−
y
2
)
value = x_1(y_2-y_3)+x_2(y_3-y_1)+x_3(y_1-y_2)
value=x1(y2−y3)+x2(y3−y1)+x3(y1−y2)
而我们求解的a,b的分母我带入后会发现
A
1
B
2
−
A
2
B
1
=
x
1
(
y
2
−
y
3
)
+
x
2
(
y
3
−
y
1
)
+
x
3
(
y
1
−
y
2
)
A_1B_2-A_2B_1 = x_1(y_2-y_3)+x_2(y_3-y_1)+x_3(y_1-y_2)
A1B2−A2B1=x1(y2−y3)+x2(y3−y1)+x3(y1−y2)
是不是很玄学hhhhh,有知道原理的大佬欢迎评论区解答。
代码实现
typedef struct _GL2_fPoint {
float x;
float y;
} GL2_fPoint;
// 计算通过三点的圆的圆心和半径
bool circle_from_three_points(const GL2_fPoint& p1, const GL2_fPoint& p2, const GL2_fPoint& p3, float& cx, float& cy, float& r) {
float x1 = p1.x, y1 = p1.y;
float x2 = p2.x, y2 = p2.y;
float x3 = p3.x, y3 = p3.y;
float A = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2);
if (std::abs(A) < 1e-6f) {
return false;
}
float B = (x1 * x1 + y1 * y1) * (y3 - y2) + (x2 * x2 + y2 * y2) * (y1 - y3) + (x3 * x3 + y3 * y3) * (y2 - y1);
float C = (x1 * x1 + y1 * y1) * (x2 - x3) + (x2 * x2 + y2 * y2) * (x3 - x1) + (x3 * x3 + y3 * y3) * (x1 - x2);
float D = (x1 * x1 + y1 * y1) * (x3 * y2 - x2 * y3) + (x2 * x2 + y2 * y2) * (x1 * y3 - x3 * y1) + (x3 * x3 + y3 * y3) * (x2 * y1 - x1 * y2);
cx = -B / (2 * A);
cy = -C / (2 * A);
r = std::sqrt((x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy));
return true;
}