页面逻辑调整

This commit is contained in:
2026-05-04 17:42:39 +08:00
parent 35004b2fbb
commit 842eb0d67b
3 changed files with 153 additions and 275 deletions

View File

@@ -7,6 +7,15 @@ namespace 头罩视野.Services
{
class GetArea
{
// 设备固定参数
private static double R = 330; // 半球半径
private static double angleStep = 10; // 每格角度
// 定义参数(和你代码里一致)
private const int totalLights = 81;
//public const double standardArea = 140;
/// <summary>有效亮度阈值:区分有效视野和噪声/遮挡的门槛设备标定经验值≥12判定为有效视野</summary>
@@ -33,165 +42,50 @@ namespace 头罩视野.Services
//双目重叠标准
public static double StandardBinocular = 4150;
// 剔除异常值,用相邻数据插值
//空白视野面积计算
public static readonly double _standardTotalArea = 2 * Math.PI * 330 * 330;
public static List<dynamic> RemoveOutliers(List<dynamic> data)
public static double GetBlankViewArea(double binocularTotalArea)
{
for (int i = 3; i < data.Count - 1; i++)
{
if (Math.Abs(data[i] - data[i - 1]) > OutlierDiffThreshold && Math.Abs(data[i] - data[i + 1]) > OutlierDiffThreshold)
{
data[i] = (dynamic)((data[i - 1] + data[i + 1]) / 2);
}
//过滤无效信号
if (data[i] < threshold)
{
data[i] = 0;
}
}
return data;
// 公式:空白 = 标准总面积 - 双目总视野
return _standardTotalArea - binocularTotalArea;
}
//下方视野
// 固定参数:每一格灯代表 10 度(你的设备标准)
/// <summary>
/// 计算单眼视野面积
/// 计算 下方视野角度(单位:度 °)
/// </summary>
/// <param name="groupData">20组数据每组lightNum个通道</param>
/// <param name="threshold">有效亮度阈值如12</param>
/// <param name="standardArea">如140</param>
/// <returns>计算好的面积</returns>
///
public static double CalculateEyeArea(List<dynamic> groupData)
public static double CalculateBottomViewAngle(int[] lightData, List<(int m, int n)> lightPositions)
{
double[] avg = new double[lightNum];
for (int c = 0; c < lightNum; c++)
// 存所有亮灯的角度
List<double> angles = new List<double>();
for (int i = 0; i < lightData.Length; i++)
{
double sum = 0;
foreach (var g in groupData) sum += g[c];
avg[c] = sum / groupData.Count;
}
int valid = avg.Count(v => v >= threshold);
return (valid / lightNum) * standardArea;
}
//计算双目视野面积
/// <summary>
/// 计算双目视野面积(左右眼同时可见)
/// </summary>
public static double CalcBinocularArea(
List<dynamic> leftGroups,
List<dynamic> rightGroups
)
{
// 1. 左眼平均数据
double[] leftAvg = GetEyeAvgArray(leftGroups);
// 2. 右眼平均数据
double[] rightAvg = GetEyeAvgArray(rightGroups);
// 3. 双目同时有效点数(左右都亮才算)
int biValid = 0;
for (int i = 0; i < lightNum; i++)
{
if (leftAvg[i] >= threshold && rightAvg[i] >= threshold)
biValid++;
}
// 4. 双目视野面积
return (biValid / lightNum) * standardArea;
}
//下方视野角度
/// <summary>
/// GB2890-2022 计算 单眼下方视野角度
/// eyeData单眼lightNum路平均数据数组
/// threshold有效亮度阈值
/// </summary>
public static double CalcLowerAngle(double[] eyeData, double perAngle)
{
// 总lightNum点 每点5°
int totalPoint = lightNum;
// 国标最下方起始点位第54号开始为正下方
int startDownIndex = 54;
int validCount = 0;
// 从最下方向上 连续检测有效点
for (int i = 0; i < lightNum / 2; i++)
{
int idx = (startDownIndex + i) % totalPoint;
if (eyeData[idx] >= threshold)
if (lightData[i] == 1)
{
validCount++;
}
else
{
// 断开直接停止
break;
var (m, n) = lightPositions[i];
double angle = m * angleStep;
angles.Add(angle);
}
}
// 下方视野角度 = 有效点数 × 单步角度
return validCount * perAngle;
// 没有亮灯返回 0
if (angles.Count == 0)
return 0;
// 最大角度 = 最下方视野
return angles.Max();
}
/// <summary>
/// 计算单眼lightNum点通道平均值数组
/// </summary>
/// <param name="eyeGroups">多组采样数据集合</param>
/// <returns>lightNum点通道平均值数组</returns>
public static double[] GetEyeAvgArray(List<dynamic> eyeGroups)
{
if (eyeGroups == null || eyeGroups.Count == 0)
return new double[lightNum]; // 无数据时返回全0数组
double[] avg = new double[lightNum];
for (int i = 0; i < lightNum; i++)
{
double sum = 0;
foreach (var group in eyeGroups)
{
sum += group[i];
}
avg[i] = sum / eyeGroups.Count;
}
return avg;
}
//视野保存率
//double totalSaveRate = (总视野面积 / 标准总视野面积) * 100;
public static class VisionCalculator
public static double CalcVisionRate(double binocularRate)
{
/// <summary>
/// 计算视野保存率
/// </summary>
/// <param name="actualArea">实测面积</param>
/// <param name="standardArea">标准面积</param>
/// <returns>保存率 %</returns>
public static double CalculateVisionSaveRate(double actualArea)
{
return (actualArea / standardArea) * 100;
}
}
//===== 2. 传入你采集的实测面积 =====
// leftArea左眼实测 rightArea右眼实测 binArea双目重叠实测
public static double CalcVisionRate(double leftArea, double rightArea)
{
// 总视野实测 = 左+右
double totalSi = leftArea + rightArea;
// 1. 总视野保存率
double ratioTotal = totalSi / StandardTotal;
double ratioTotal = binocularRate / StandardTotal;
double gammaTotal = GetVisionGamma(ratioTotal);
double totalRate = gammaTotal * ratioTotal * 100;
return (totalRate);
@@ -230,19 +124,6 @@ namespace 头罩视野.Services
// 设备固定参数
private static double R = 330; // 半球半径
private static double angleStep = 10; // 每格角度
// 定义参数(和你代码里一致)
private const int totalLights = 81;
// 传入72个灯的亮灭数据0=灭1=亮)
// 返回:椭圆面积
public static double CalculateEllipseArea(int[] lightData, List<(int m, int n)> lightPositions)
@@ -301,7 +182,6 @@ namespace 头罩视野.Services
// 最小二乘法拟合椭圆核心算法cx椭圆中心点的 X 坐标 cy椭圆中心点的 Y 坐标 a椭圆的长半轴长度较大的那个半径b椭圆的短半轴长度较小的那个半径
private static (double cx, double cy, double a, double b, double area) FitEllipse(List<Point> points)
{
int n = points.Count;
@@ -347,20 +227,6 @@ namespace 头罩视野.Services
//
//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);
//}
}