This commit is contained in:
2026-05-06 15:00:54 +08:00
parent 07caa61a39
commit 32b149cea9
2 changed files with 178 additions and 155 deletions

View File

@@ -40,6 +40,10 @@ namespace 头罩视野.Services
// 只处理亮灯的情况
if (lightData[i] == 1)
{
if (lightPositions.Count < lightData.Count())
{
return 0;
}
var (m, n) = lightPositions[i];
// 关键只取下爪灯条n == 1因为只有它才对应下方的垂直视野
@@ -63,7 +67,7 @@ namespace 头罩视野.Services
//视野保存率
public static double CalcVisionRate(double binocularRate)
{
// 1. 总视野保存率
double ratioTotal = binocularRate / _standardTotalArea;
double gammaTotal = GetVisionGamma(ratioTotal);
@@ -114,8 +118,14 @@ namespace 头罩视野.Services
List<System.Drawing.Point> brightPoints = new List<System.Drawing.Point>();
for (int i = 0; i < totalLights; i++)
{
if (totalLights > lightData.Count())
{
}
if (lightData[i] == 1)
{
var (m, n) = lightPositions[i];
System.Drawing.Point p = GetLightPoint(m, n);
brightPoints.Add(p);
@@ -127,7 +137,7 @@ namespace 头罩视野.Services
// 返回面积
return area;
}
}
/// 生成设备全部243盏灯的(m,n)位置 上爪1条、下爪1条、左右共用1条各81灯
public static System.Drawing.Point GetLightPoint(int m, int n)
{
@@ -162,45 +172,45 @@ namespace 头罩视野.Services
// 最小二乘法拟合椭圆核心算法cx椭圆中心点的 X 坐标 cy椭圆中心点的 Y 坐标 a椭圆的长半轴长度较大的那个半径b椭圆的短半轴长度较小的那个半径
public static (double cx, double cy, double a, double b, double area) FitEllipse(List<Point> points)
{
int n = points.Count;
{
int n = points.Count;
if (n < 5)
//throw new Exception("至少需要5个点来拟合椭圆");
return new (0,0,0,0,0) ;
return new(0, 0, 0, 0, 0);
// 这里是正确写法
var M = MathNetMatrix.Build.Dense(n, 5);
var Y = MathNetVector.Build.Dense(n, i => -1.0);
for (int i = 0; i < n; i++)
{
double x = points[i].X;
double y = points[i].Y;
M[i, 0] = x * x;
M[i, 1] = x * y;
M[i, 2] = y * y;
M[i, 3] = x;
M[i, 4] = y;
}
{
double x = points[i].X;
double y = points[i].Y;
M[i, 0] = x * x;
M[i, 1] = x * y;
M[i, 2] = y * y;
M[i, 3] = x;
M[i, 4] = y;
}
// 求解
Vector<double> sol = M.QR().Solve(Y);
double A = sol[0], B = sol[1], C = sol[2], D = sol[3], E = sol[4], F = 1;
// 求解
Vector<double> sol = M.QR().Solve(Y);
double A = sol[0], B = sol[1], C = sol[2], D = sol[3], E = sol[4], F = 1;
// 椭圆中心
double cx = (2 * C * D - B * E) / (B * B - 4 * A * C);
double cy = (2 * A * E - B * D) / (B * B - 4 * A * C);
// 椭圆中心
double cx = (2 * C * D - B * E) / (B * B - 4 * A * C);
double cy = (2 * A * E - B * D) / (B * B - 4 * A * C);
// 半轴
double term1 = 2 * (A * E * E + C * D * D - B * D * E + (B * B - 4 * A * C) * F);
double term2 = (A + C) + Math.Sqrt((A - C) * (A - C) + B * B);
double term3 = (A + C) - Math.Sqrt((A - C) * (A - C) + B * B);
// 半轴
double term1 = 2 * (A * E * E + C * D * D - B * D * E + (B * B - 4 * A * C) * F);
double term2 = (A + C) + Math.Sqrt((A - C) * (A - C) + B * B);
double term3 = (A + C) - Math.Sqrt((A - C) * (A - C) + B * B);
double a = Math.Sqrt(Math.Abs(term1 / ((B * B - 4 * A * C) * term3)));
double b = Math.Sqrt(Math.Abs(term1 / ((B * B - 4 * A * C) * term2)));
double a = Math.Sqrt(Math.Abs(term1 / ((B * B - 4 * A * C) * term3)));
double b = Math.Sqrt(Math.Abs(term1 / ((B * B - 4 * A * C) * term2)));
if (a < b) (a, b) = (b, a);
double area = Math.PI * a * b;
if (a < b) (a, b) = (b, a);
double area = Math.PI * a * b;
return (cx, cy, a, b, area);
}