圆弧三点拟合圆
旋转标定的数学公式
一 旋转中心标定
public class CircleFitter
{
/// <summary>
/// 通过三个点计算圆心坐标
/// </summary>
/// <param name="point1">第一个点 (x1, y1)</param>
/// <param name="point2">第二个点 (x2, y2)</param>
/// <param name="point3">第三个点 (x3, y3)</param>
/// <returns>圆心坐标 (cx, cy)</returns>
public static (double cx, double cy) FitCircleFromThreePoints((double x, double y) point1,
(double x, double y) point2,
(double x, double y) point3)
{
// 解法基于三点确定一个圆的几何原理
// 设圆心为 (cx, cy),则有:
// (x1-cx)² + (y1-cy)² = (x2-cx)² + (y2-cy)² = (x3-cx)² + (y3-cy)² = r²
double x1 = point1.x, y1 = point1.y;
double x2 = point2.x, y2 = point2.y;
double x3 = point3.x, y3 = point3.y;
// 计算中间变量
double A = x2 - x1;
double B = y2 - y1;
double C = x3 - x1;
double D = y3 - y1;
double E = A * (x1 + x2) + B * (y1 + y2);
double F = C * (x1 + x3) + D * (y1 + y3);
double G = 2 * (A * (y3 - y1) - B * (x3 - x1));
// 避免除以零(三点共线的情况)
if (Math.Abs(G) < 1e-10)
{
throw new ArgumentException("三点共线,无法确定唯一的圆");
}
// 计算圆心坐标
double cx = (D * E - B * F) / G;
double cy = (A * F - C * E) / G;
return (cx, cy);
}
/// <summary>
/// 计算圆的半径
/// </summary>
public static double CalculateRadius((double x, double y) center, (double x, double y) point)
{
double dx = point.x - center.x;
double dy = point.y - center.y;
return Math.Sqrt(dx * dx + dy * dy);
}
}
二 使用
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
// 拟合圆的三个点坐标
var point1 = (x: 3332.24, y: 1807.67);
var point2 = (x: 3099.6, y: 1922.86);
var point3 = (x: 2838.07, y: 2000.45);
// 计算圆心
var center = CircleFitter.FitCircleFromThreePoints(point1, point2, point3);
MessageBox.Show($"圆心坐标: ({center.cx:F4}, {center.cy:F4})");
// 计算半径(使用第一个点)
double radius = CircleFitter.CalculateRadius(center, point1);
MessageBox.Show($"圆的半径: {radius:F4}");
}
catch (ArgumentException ex)
{
Console.WriteLine($"错误: {ex.Message}");
}
}
}
我来详细解释这段代码中每行数学公式对应的几何意义:

主函数 FitCircleFromThreePoints
1. 输入点坐标
double x1 = point1.x, y1 = point1.y;
double x2 = point2.x, y2 = point2.y;
double x3 = point3.x, y3 = point3.y;
几何意义:三个点的笛卡尔坐标,它们都位于所求的圆上。
2. 中间变量计算(向量表示)
double A = x2 - x1; // 向量P1P2的x分量
double B = y2 - y1; // 向量P1P2的y分量
double C = x3 - x1; // 向量P1P3的x分量
double D = y3 - y1; // 向量P1P3的y分量
几何意义:
(A, B)是从点1指向点2的向量 P1P2⃗\vec{P_1P_2}P1P2(C, D)是从点1指向点3的向量 P1P3⃗\vec{P_1P_3}P1P3
3. 垂径定理的应用
double E = A * (x1 + x2) + B * (y1 + y2);
几何意义:
(x1+x2)/2, (y1+y2)/2是弦P1P2的中点坐标(A, B)是弦P1P2的方向向量- 根据垂径定理:圆心在弦的垂直平分线上
- 垂直平分线的点法式方程:
A*(x - (x1+x2)/2) + B*(y - (y1+y2)/2) = 0 - 展开后得到:
A*x + B*y = (A*(x1+x2) + B*(y1+y2))/2 E就是等式右边的两倍:E = 2*(A*x + B*y)
double F = C * (x1 + x3) + D * (y1 + y3);
几何意义:
- 同理,这是弦P1P3的垂直平分线方程的右边两倍
- 表示:
C*x + D*y = (C*(x1+x3) + D*(y1+y3))/2
4. 行列式(判断共线性和求解)
double G = 2 * (A * (y3 - y1) - B * (x3 - x1));
= 2 * (A * D - B * C) // 因为 y3-y1 = D, x3-x1 = C
几何意义:
A*D - B*C是向量 P1P2⃗\vec{P_1P_2}P1P2 和 P1P3⃗\vec{P_1P_3}P1P3 的叉积的z分量- 叉积的大小 =
|P1P2| * |P1P3| * sin(夹角) - 当G=0时,sin(夹角)=0,表示三点共线(夹角为0°或180°)
G实际上等于两倍的这个叉积值
5. 求解圆心坐标
double cx = (D * E - B * F) / G;
double cy = (A * F - C * E) / G;
几何意义:
这是解二元一次方程组的结果:
A*x + B*y = E/2 (弦P1P2的垂直平分线)
C*x + D*y = F/2 (弦P1P3的垂直平分线)
解这个方程组得到两条垂直平分线的交点,即圆心。
用克莱姆法则求解:
- 系数行列式 =
A*D - B*C = G/2 - cx的分子行列式 =
(E/2)*D - B*(F/2) = (D*E - B*F)/2 - 所以
cx = [(D*E - B*F)/2] / (G/2) = (D*E - B*F)/G
辅助函数 CalculateRadius
double dx = point.x - center.x;
double dy = point.y - center.y;
return Math.Sqrt(dx * dx + dy * dy);
几何意义:
- 计算圆心到圆上任意一点的欧几里得距离
- 根据圆的定义,这个距离就是圆的半径
- 使用了勾股定理:r=(x−xc)2+(y−yc)2r = \sqrt{(x-x_c)^2 + (y-y_c)^2}r=(x−xc)2+(y−yc)2
核心几何原理总结
整个算法基于两个几何定理:
- 圆的定义:圆上任意点到圆心的距离相等
- 垂径定理:圆上任意弦的垂直平分线经过圆心
通过两条弦的垂直平分线相交,唯一确定圆心位置。
弦是几何学中连接圆上任意两点的线段,经过圆心的弦称为直径,且直径为圆内最长的弦。


2933

被折叠的 条评论
为什么被折叠?



