C# 从三个点求圆心的求解方程
我正在寻找一个高精度解决方案,从画布上的3个数据点(x,y)找到圆的中心点。我在上面附带的屏幕截图中找到了这个例子,现在我使用Math.NET软件包来求解这个方程,并将结果与这个在线工具进行比较:C# 从三个点求圆心的求解方程,c#,.net,.net-core,C#,.net,.net Core,我正在寻找一个高精度解决方案,从画布上的3个数据点(x,y)找到圆的中心点。我在上面附带的屏幕截图中找到了这个例子,现在我使用Math.NET软件包来求解这个方程,并将结果与这个在线工具进行比较:https://planetcalc.com/8116/ 然而,当我计算半径时,它是完全偏离的,并且经常是负数 using MathNet.Numerics.LinearAlgebra.Double.Solvers; using MathNet.Numerics.LinearAlgebra.Double
https://planetcalc.com/8116/
然而,当我计算半径时,它是完全偏离的,并且经常是负数
using MathNet.Numerics.LinearAlgebra.Double.Solvers;
using MathNet.Numerics.LinearAlgebra.Double;
using System;
namespace ConsoleAppTestBed
{
class Program
{
static void Main(string[] args)
{
var dataPoints = new double[,]
{
{ 5, 80 },
{ 20, 100 },
{ 40, 140 }
};
var fitter = new CircleFitter();
var result = fitter.Fit(dataPoints);
var x = -result[0];
var y = -result[1];
var c = result[2];
Console.WriteLine("Center Point:");
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(c);
//// (x^2 + y^2 - c^2)
var radius = Math.Pow(x, 2) + Math.Pow(y, 2) - Math.Pow(c, 2);
//// sqrt((x^2 + y^2 - c^2))
radius = Math.Sqrt(radius);
Console.WriteLine("Radius:");
Console.WriteLine(radius);
Console.ReadLine();
}
public class CircleFitter
{
public double[] Fit(double[,] v)
{
var xy1 = new double[] { v[0,0], v[0,1] };
var xy2= new double[] { v[1, 0], v[1, 1] };
var xy3 = new double[] { v[2, 0], v[2, 1] };
// Create Left Side Matrix of Equation
var a = CreateLeftSide_(xy1);
var b = CreateLeftSide_(xy2);
var c = CreateLeftSide_(xy3);
var matrixA = DenseMatrix.OfArray(new[,]
{
{ a[0], a[1], a[2] },
{ b[0], b[1], b[2] },
{ c[0], c[1], c[2] }
});
// Create Right Side Vector of Equation
var d = CreateRightSide_(xy1);
var e = CreateRightSide_(xy2);
var f = CreateRightSide_(xy3);
double[] vector = { d, e, f };
var vectorB = Vector<double>.Build.Dense(vector);
// Solve Equation
var r = matrixA.Solve(vectorB);
var result = r.ToArray();
return result;
}
//2x, 2y, 1
public double[] CreateLeftSide_(double[] d)
{
return new double[] { (2 * d[0]), (2 * d[1]) , 1};
}
// -(x^2 + y^2)
public double CreateRightSide_(double[] d)
{
return -(Math.Pow(d[0], 2) + Math.Pow(d[1], 2));
}
}
}
}
使用MathNet.Numerics.LinearAlgebra.Double.solver;
使用MathNet.Numerics.LinearAlgebra.Double;
使用制度;
命名空间控制台桌面
{
班级计划
{
静态void Main(字符串[]参数)
{
var数据点=新的双精度[,]
{
{ 5, 80 },
{ 20, 100 },
{ 40, 140 }
};
var fitter=新的CircleFitter();
var结果=fitter.Fit(数据点);
var x=-结果[0];
变量y=-结果[1];
var c=结果[2];
控制台。写入线(“中心点:”);
控制台写入线(x);
控制台写入线(y);
控制台写入线(c);
////(x^2+y^2-c^2)
变量半径=数学功率(x,2)+数学功率(y,2)-数学功率(c,2);
////sqrt((x^2+y^2-c^2))
半径=数学Sqrt(半径);
控制台。写入线(“半径:”);
控制台写入线(半径);
Console.ReadLine();
}
公共类电路板
{
公共双[]配合(双[,]v)
{
var xy1=新的双精度[]{v[0,0],v[0,1]};
var xy2=新的双精度[]{v[1,0],v[1,1]};
var xy3=新的双精度[]{v[2,0],v[2,1]};
//创建方程的左侧矩阵
var a=CreateLeftSide_u1(xy1);
var b=CreateLeftSide_uxy2;
var c=CreateLeftSide_u3;
var matrixA=阵列密度矩阵(新[,]
{
{a[0],a[1],a[2]},
{b[0],b[1],b[2]},
{c[0],c[1],c[2]}
});
//创建方程的右侧向量
var d=CreateRightSide_u1(xy1);
var e=CreateRightSide_u2;(xy2);
var f=CreateRightSide_uxy3;
双[]向量={d,e,f};
var vectorB=Vector.Build.densite(向量);
//解方程
var r=矩阵解(向量B);
var结果=r.ToArray();
返回结果;
}
//2x,2y,1
公共双精度[]CreateLeftSide_Ud(双精度[]d)
{
返回新的双精度[]{(2*d[0]),(2*d[1]),1};
}
//-(x^2+y^2)
公共双CreateRightSide_uUd(双[]d)
{
return-(Math.Pow(d[0],2)+Math.Pow(d[1],2));
}
}
}
}
有什么想法吗
提前感谢。您的问题解决方案如下: 代码:
请定义“高精度”。。。。你可以在可能的情况下使用小数。我正在wpf画布上画圆圈和三个点。我最初是在寻找垂直线相交的地方。。但是,当计算出的圆的半径穿过某些点时,有时会出现一个或两个像素偏移。我用的是双倍自动取款机,我试试小数。
using System;
using System.Globalization;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
double x1 = 1, y1 = 1;
double x2 = 2, y2 = 4;
double x3 = 5, y3 = -3;
findCircle(x1, y1, x2, y2, x3, y3);
Console.ReadKey();
}
static void findCircle(double x1, double y1,
double x2, double y2,
double x3, double y3)
{
NumberFormatInfo setPrecision = new NumberFormatInfo();
setPrecision.NumberDecimalDigits = 3; // 3 digits after the double point
double x12 = x1 - x2;
double x13 = x1 - x3;
double y12 = y1 - y2;
double y13 = y1 - y3;
double y31 = y3 - y1;
double y21 = y2 - y1;
double x31 = x3 - x1;
double x21 = x2 - x1;
double sx13 = (double)(Math.Pow(x1, 2) -
Math.Pow(x3, 2));
double sy13 = (double)(Math.Pow(y1, 2) -
Math.Pow(y3, 2));
double sx21 = (double)(Math.Pow(x2, 2) -
Math.Pow(x1, 2));
double sy21 = (double)(Math.Pow(y2, 2) -
Math.Pow(y1, 2));
double f = ((sx13) * (x12)
+ (sy13) * (x12)
+ (sx21) * (x13)
+ (sy21) * (x13))
/ (2 * ((y31) * (x12) - (y21) * (x13)));
double g = ((sx13) * (y12)
+ (sy13) * (y12)
+ (sx21) * (y13)
+ (sy21) * (y13))
/ (2 * ((x31) * (y12) - (x21) * (y13)));
double c = -(double)Math.Pow(x1, 2) - (double)Math.Pow(y1, 2) -
2 * g * x1 - 2 * f * y1;
double h = -g;
double k = -f;
double sqr_of_r = h * h + k * k - c;
// r is the radius
double r = Math.Round(Math.Sqrt(sqr_of_r), 5);
Console.WriteLine("Center of a circle: x = " + h.ToString("N", setPrecision) +
", y = " + k.ToString("N", setPrecision));
Console.WriteLine("Radius: " + r.ToString("N", setPrecision));
}
}
}