已知点求圆

已知三点求圆心

三个点可以确定一个准确的圆

/// <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;
        }
    }

}

实验结果

在这里插入图片描述

在这里插入图片描述

明显拟合圆有精度丢失

发布了54 篇原创文章 · 获赞 14 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/bayinglong/article/details/88933504