已知点求圆
已知三点求圆心
三个点可以确定一个准确的圆
/// <summary>
/// 查找圆
/// </summary>
/// <param name="pt1"></param>
/// <param name="pt2"></param>
/// <param name="pt3"></param>
/// <returns></returns>
public CircleData findCircle(Point pt1, Point pt2, Point pt3)
{
Point midPt1 = new Point();
Point midPt2 = new Point();
midPt1.X = (pt2.X + pt1.X) / 2;
midPt1.Y = (pt2.Y + pt1.Y) / 2;
midPt2.X = (pt3.X + pt1.X) / 2;
midPt2.Y = (pt3.Y + pt1.Y) / 2;
double k1 = -(pt2.X - pt1.X) / (pt2.Y - pt1.Y);
double k2 = -(pt3.X - pt1.X) / (pt3.Y - pt1.Y);
CircleData CD = new CircleData();
double asd = (midPt2.Y - midPt1.Y - k2 * midPt2.X + k1 * midPt1.X) / (k1 - k2);
CD.Center.X = (midPt2.Y - midPt1.Y - k2 * midPt2.X + k1 * midPt1.X) / (k1 - k2);
CD.Center.Y = midPt1.Y + k1 * (midPt2.Y - midPt1.Y - k2 * midPt2.X + k2 * midPt1.X) / (k1 - k2);
CD.Radius = Math.Sqrt((CD.Center.X - pt1.X) * (CD.Center.X - pt1.X) + (CD.Center.Y - pt1.Y) * (CD.Center.Y - pt1.Y));
return CD;
}
多点拟合圆
这里有用到 Math.Net包
安装方法如下:
/// <summary>
/// 二值法,多点拟合
/// </summary>
/// <param name="pointFs"></param>
/// <param name="CenterX"></param>
/// <param name="CenterY"></param>
/// <param name="CenterR"></param>
/// <returns></returns>
public static int FitCircle(List<Point> pointFs, out double CenterX, out double CenterY, out double CenterR)
{
Matrix<double> YMat;
Matrix<double> RMat;
Matrix<double> AMat;
List<double> YLit = new List<double>();
List<double[]> RLit = new List<double[]>();
//------构建Y矩阵
foreach (var pointF in pointFs)
YLit.Add(pointF.X * pointF.X + pointF.Y * pointF.Y);
double[,] Yarray = new double[YLit.Count, 1];
for (int i = 0; i < YLit.Count; i++)
Yarray[i, 0] = YLit[i];
YMat = CreateMatrix.DenseOfArray<double>(Yarray);
//构建R矩阵
foreach (var pointF in pointFs)
RLit.Add(new double[] { -pointF.X, -pointF.Y, -1 });
double[,] Rarray = new double[RLit.Count, 3];
for (int i = 0; i < RLit.Count; i++)
{
for (int j = 0; j < 3; j++)
{
Rarray[i, j] = RLit[i][j];
}
}
RMat = CreateMatrix.DenseOfArray<double>(Rarray);
Matrix<double> RTMat = RMat.Transpose();
Matrix<double> RRTInvMat = (RTMat.Multiply(RMat)).Inverse();
AMat = RRTInvMat.Multiply(RTMat.Multiply(YMat));
double[,] Aarray = AMat.ToArray();
double A = Aarray[0, 0];
double B = Aarray[1, 0];
double C = Aarray[2, 0];
CenterX = A / -2.0f;
CenterY = B / -2.0f;
CenterR = (double)(Math.Sqrt((A * A + B * B - 4 * C)) / 2.0f);
return 0x0000;
}
原理:
实验代码
using MathNet.Numerics.LinearAlgebra;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Point pt1 = new Point(0, 1);
Point pt2 = new Point(2, 5);
Point pt3 = new Point(3, 4);
List<Point> ptList = new List<Point>();
ptList.Add(pt1);
ptList.Add(pt2);
ptList.Add(pt3);
double x, y, r;
CircleData.FitCircle(ptList, out x, out y, out r);
Console.Write("原点坐标为 x:{0},y:{1},r:{2}", x, y, r);
// ///三点求圆
// double[] pt1lsit = new double[2];
// double[] pt2lsit = new double[2];
// double[] pt3lsit = new double[2];
// while (!ReadPoint(ref pt1lsit, 1))
// {
// }
// while (!ReadPoint(ref pt2lsit, 2))
// {
// }
// while (!ReadPoint(ref pt3lsit, 3))
// {
// }
// Point pt2 = new Point(pt1lsit[0], pt1lsit[1]);
// Point pt3 = new Point(pt2lsit[0], pt2lsit[1]);
// Point pt1 = new Point(pt3lsit[0], pt3lsit[1]);
// CircleData curCircle = new CircleData();
// curCircle = curCircle.findCircle(pt1, pt2, pt3);
// Console.Write("原点坐标为 x:{0},y:{1},r:{2}", curCircle.Center.X, curCircle.Center.Y, curCircle.Radius);
// string i = Console.ReadLine();
//}
//private static bool ReadPoint(ref double[] XYList, int index)
//{
// Console.WriteLine("请输入第{0}个点的坐标", index.ToString());
// string spt1 = Console.ReadLine();
// string[] sptXY = spt1.Split(',');
// int i = 0;
// try
// {
// foreach (var item in sptXY)
// {
// if (!double.TryParse(item, out XYList[i]))
// {
// Console.WriteLine("请输入有误,请重新输入,ex: 1,2");
// return false;
// }
// i++;
// }
// if (i == 1)
// {
// Console.WriteLine("请输入有误,请重新输入,ex: 1,2");
// return false;
// }
// return true;
// }
// catch (Exception)
// {
// Console.WriteLine("请输入有误,请重新输入,ex: 1,2");
// return false;
// }
//}
}
}
class Point
{
private double x;
public double X
{
get { return x; }
set { x = value; }
}
private double y;
public double Y
{
get { return y; }
set { y = value; }
}
public Point()
{
}
public Point(double x, double y)
{
this.X = x;
this.Y = y;
}
}
class PointF
{
private float x;
public float X
{
get { return x; }
set { x = value; }
}
private float y;
public float Y
{
get { return y; }
set { y = value; }
}
public PointF()
{
}
public PointF(float x, float y)
{
this.X = x;
this.Y = y;
}
}
class CircleData
{
private Point center;
/// <summary>
/// 中心电坐标
/// </summary>
internal Point Center
{
get { return center; }
set { center = value; }
}
private double radius;
/// <summary>
/// 半径
/// </summary>
public double Radius
{
get { return radius; }
set { radius = value; }
}
public CircleData()
{
Center = new Point();
}
/// <summary>
/// 查找圆
/// </summary>
/// <param name="pt1"></param>
/// <param name="pt2"></param>
/// <param name="pt3"></param>
/// <returns></returns>
public CircleData findCircle(Point pt1, Point pt2, Point pt3)
{
Point midPt1 = new Point();
Point midPt2 = new Point();
midPt1.X = (pt2.X + pt1.X) / 2;
midPt1.Y = (pt2.Y + pt1.Y) / 2;
midPt2.X = (pt3.X + pt1.X) / 2;
midPt2.Y = (pt3.Y + pt1.Y) / 2;
double k1 = -(pt2.X - pt1.X) / (pt2.Y - pt1.Y);
double k2 = -(pt3.X - pt1.X) / (pt3.Y - pt1.Y);
CircleData CD = new CircleData();
double asd = (midPt2.Y - midPt1.Y - k2 * midPt2.X + k1 * midPt1.X) / (k1 - k2);
CD.Center.X = (midPt2.Y - midPt1.Y - k2 * midPt2.X + k1 * midPt1.X) / (k1 - k2);
CD.Center.Y = midPt1.Y + k1 * (midPt2.Y - midPt1.Y - k2 * midPt2.X + k2 * midPt1.X) / (k1 - k2);
CD.Radius = Math.Sqrt((CD.Center.X - pt1.X) * (CD.Center.X - pt1.X) + (CD.Center.Y - pt1.Y) * (CD.Center.Y - pt1.Y));
return CD;
}
/// <summary>
/// 二值法,多点拟合
/// </summary>
/// <param name="pointFs"></param>
/// <param name="CenterX"></param>
/// <param name="CenterY"></param>
/// <param name="CenterR"></param>
/// <returns></returns>
public static int FitCircle(List<Point> pointFs, out double CenterX, out double CenterY, out double CenterR)
{
Matrix<double> YMat;
Matrix<double> RMat;
Matrix<double> AMat;
List<double> YLit = new List<double>();
List<double[]> RLit = new List<double[]>();
//------构建Y矩阵
foreach (var pointF in pointFs)
YLit.Add(pointF.X * pointF.X + pointF.Y * pointF.Y);
double[,] Yarray = new double[YLit.Count, 1];
for (int i = 0; i < YLit.Count; i++)
Yarray[i, 0] = YLit[i];
YMat = CreateMatrix.DenseOfArray<double>(Yarray);
//构建R矩阵
foreach (var pointF in pointFs)
RLit.Add(new double[] { -pointF.X, -pointF.Y, -1 });
double[,] Rarray = new double[RLit.Count, 3];
for (int i = 0; i < RLit.Count; i++)
{
for (int j = 0; j < 3; j++)
{
Rarray[i, j] = RLit[i][j];
}
}
RMat = CreateMatrix.DenseOfArray<double>(Rarray);
Matrix<double> RTMat = RMat.Transpose();
Matrix<double> RRTInvMat = (RTMat.Multiply(RMat)).Inverse();
AMat = RRTInvMat.Multiply(RTMat.Multiply(YMat));
double[,] Aarray = AMat.ToArray();
double A = Aarray[0, 0];
double B = Aarray[1, 0];
double C = Aarray[2, 0];
CenterX = A / -2.0f;
CenterY = B / -2.0f;
CenterR = (double)(Math.Sqrt((A * A + B * B - 4 * C)) / 2.0f);
return 0x0000;
}
}
}