using System;
using System.Collections.Generic;
using System.Linq;
namespace 头罩视野.Services
{
public static class GetArea
{
// 灯条参数
public const int totalLights = 81; // 每条灯条81个灯
public static double verticalAngleStep = 90.0 / (totalLights - 1); // 1.125°
public static double CalculateBottomViewAngle(int[] lightData, List<(int m, int n)> lightPositions)
{
int bottomLampCount = 0;
for (int i = 0; i < lightData.Length && i < lightPositions.Count; i++)
{
if (lightPositions[i].n == 1 && lightData[i] == 1)
bottomLampCount++;
}
return (double)bottomLampCount / 81 * 90.0;
}
///
/// 根据径向灯条0/1数据计算边界角度(极角,度)
///
/// 从上到下的灯条状态,索引0=顶部0°,索引80=底部90°
public static double ComputeBoundaryAngle(int[] lightStates)
{
if (lightStates == null || lightStates.Length != totalLights) return 0;
int firstZero = -1;
for (int i = 0; i < totalLights; i++)
{
if (lightStates[i] == 0)
{
firstZero = i;
break;
}
}
if (firstZero == -1) return 90.0; // 全亮
if (firstZero == 0) return 0.0; // 顶部即被遮
// 边界角度 = 上一个灯条的结束角 = (firstZero) * verticalAngleStep
return firstZero * verticalAngleStep;
}
///
/// 极坐标梯形法积分面积(半径数组单位:度,步长单位:度)
///
public static double IntegrateArea(double[] radiiDeg, double deltaThetaDeg)
{
if (radiiDeg == null || radiiDeg.Length < 2) return 0;
double deltaRad = deltaThetaDeg * Math.PI / 180.0;
double sum = 0.0;
for (int i = 0; i < radiiDeg.Length - 1; i++)
{
double r1 = radiiDeg[i];
double r2 = radiiDeg[i + 1];
double avgRSq = (r1 * r1 + r2 * r2) / 2.0;
sum += avgRSq * deltaRad;
}
return 0.5 * sum;
}
///
/// 根据左右眼边界半径数组,计算总视野(并集)和双目视野(交集)面积
///
public static (double totalArea, double biArea) ComputeTotalAndBinocularArea(double[] leftRadii, double[] rightRadii, double deltaThetaDeg)
{
int len = Math.Min(leftRadii.Length, rightRadii.Length);
double[] totalRadii = new double[len];
double[] biRadii = new double[len];
for (int i = 0; i < len; i++)
{
totalRadii[i] = Math.Max(leftRadii[i], rightRadii[i]);
biRadii[i] = Math.Min(leftRadii[i], rightRadii[i]);
}
double totalArea = IntegrateArea(totalRadii, deltaThetaDeg);
double biArea = IntegrateArea(biRadii, deltaThetaDeg);
return (totalArea, biArea);
}
///
/// 保存率计算公式(带γ校正)
///
public static double ComputePreservation(double measuredArea, double standardArea, double gamma)
{
if (standardArea <= 0) return 0;
return gamma * (measuredArea / standardArea) * 100.0;
}
///
/// 根据面积比获取γ校正系数(GB 2890-2022 图D.4)
///
public static double GetGammaByRatio(double ratio)
{
double[] x = { 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
double[] y = { 1.22, 1.18, 1.14, 1.10, 1.06, 1.03, 1.02, 1.01, 1.00 };
if (ratio <= x[0]) return y[0];
if (ratio >= x.Last()) return y.Last();
for (int i = 0; i < x.Length - 1; i++)
{
if (ratio >= x[i] && ratio <= x[i + 1])
{
double t = (ratio - x[i]) / (x[i + 1] - x[i]);
return y[i] + t * (y[i + 1] - y[i]);
}
}
return 1.0;
}
}
}