111 lines
4.3 KiB
C#
111 lines
4.3 KiB
C#
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据径向灯条0/1数据计算边界角度(极角,度)
|
||
/// </summary>
|
||
/// <param name="lightStates">从上到下的灯条状态,索引0=顶部0°,索引80=底部90°</param>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 极坐标梯形法积分面积(半径数组单位:度,步长单位:度)
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据左右眼边界半径数组,计算总视野(并集)和双目视野(交集)面积
|
||
/// </summary>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存率计算公式(带γ校正)
|
||
/// </summary>
|
||
public static double ComputePreservation(double measuredArea, double standardArea, double gamma)
|
||
{
|
||
if (standardArea <= 0) return 0;
|
||
return gamma * (measuredArea / standardArea) * 100.0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据面积比获取γ校正系数(GB 2890-2022 图D.4)
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
} |