页面逻辑调整。
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
|
||||
using MathNet.Numerics.LinearAlgebra;
|
||||
using MathNetMatrix = MathNet.Numerics.LinearAlgebra.Matrix<double>;
|
||||
using MathNetVector = MathNet.Numerics.LinearAlgebra.Vector<double>;
|
||||
using System.Drawing;
|
||||
namespace 头罩视野.Services
|
||||
{
|
||||
class GetArea
|
||||
@@ -182,8 +183,6 @@ namespace 头罩视野.Services
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===== 2. 传入你采集的实测面积 =====
|
||||
// leftArea:左眼实测 rightArea:右眼实测 binArea:双目重叠实测
|
||||
public static double CalcVisionRate(double leftArea, double rightArea)
|
||||
@@ -228,5 +227,95 @@ namespace 头罩视野.Services
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 设备固定参数
|
||||
private const double R = 330; // 半球半径
|
||||
private const double angleStep = 10; // 每格角度
|
||||
|
||||
// 传入:72个灯的亮灭数据(0=灭,1=亮)
|
||||
// 返回:椭圆面积
|
||||
public static double CalculateEllipseArea(int[] lightData, List<(int m, int n)> lightPositions)
|
||||
{
|
||||
if (lightData.Length != 72 || lightPositions.Count != 72)
|
||||
throw new Exception("必须是72个灯的数据");
|
||||
|
||||
// 第一步:收集所有亮灯坐标
|
||||
List<System.Drawing.Point> brightPoints = new List<System.Drawing.Point>();
|
||||
for (int i = 0; i < 72; i++)
|
||||
{
|
||||
if (lightData[i] == 1)
|
||||
{
|
||||
var (m, n) = lightPositions[i];
|
||||
System.Drawing.Point p = GetLightPoint(m, n);
|
||||
brightPoints.Add(p);
|
||||
}
|
||||
}
|
||||
|
||||
// 第二步:用亮点拟合椭圆
|
||||
var (cx, cy, a, b, area) = FitEllipse(brightPoints);
|
||||
|
||||
// 返回面积
|
||||
return area;
|
||||
}
|
||||
|
||||
// 格数 m,n → 坐标点
|
||||
private static System.Drawing.Point GetLightPoint(int m, int n)
|
||||
{
|
||||
double radH = m * angleStep * Math.PI / 180;
|
||||
double radV = n * angleStep * Math.PI / 180;
|
||||
double x = R * Math.Tan(radH);
|
||||
double y = R * Math.Tan(radV);
|
||||
return new System.Drawing.Point((int)x, (int)y);
|
||||
}
|
||||
|
||||
// 最小二乘法拟合椭圆(核心算法)
|
||||
|
||||
|
||||
private static (double cx, double cy, double a, double b, double area) FitEllipse(List<Point> points)
|
||||
{
|
||||
int n = points.Count;
|
||||
if (n < 5)
|
||||
throw new Exception("至少需要5个点来拟合椭圆");
|
||||
|
||||
// 这里是正确写法
|
||||
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;
|
||||
}
|
||||
|
||||
// 求解
|
||||
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 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)));
|
||||
|
||||
if (a < b) (a, b) = (b, a);
|
||||
double area = Math.PI * a * b;
|
||||
|
||||
return (cx, cy, a, b, area);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
7
头罩视野slove/头罩视野/Services/Matrix.cs
Normal file
7
头罩视野slove/头罩视野/Services/Matrix.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace 头罩视野.Services
|
||||
{
|
||||
internal class Matrix<T>
|
||||
{
|
||||
public static object Build { get; internal set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user