Files
hoodFieldOfView/头罩视野slove/头罩视野/Services/GetArea.cs

111 lines
4.3 KiB
C#
Raw Normal View History

2026-05-25 13:56:11 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
2026-04-27 16:45:06 +08:00
namespace .Services
{
2026-05-25 13:56:11 +08:00
public static class GetArea
2026-04-27 16:45:06 +08:00
{
2026-05-25 13:56:11 +08:00
// 灯条参数
public const int totalLights = 81; // 每条灯条81个灯
public static double verticalAngleStep = 90.0 / (totalLights - 1); // 1.125°
2026-05-23 19:59:49 +08:00
2026-05-04 17:42:39 +08:00
public static double CalculateBottomViewAngle(int[] lightData, List<(int m, int n)> lightPositions)
2026-04-27 16:45:06 +08:00
{
2026-05-25 13:56:11 +08:00
int bottomLampCount = 0;
for (int i = 0; i < lightData.Length && i < lightPositions.Count; i++)
2026-04-27 16:45:06 +08:00
{
2026-05-25 13:56:11 +08:00
if (lightPositions[i].n == 1 && lightData[i] == 1)
bottomLampCount++;
2026-04-27 16:45:06 +08:00
}
2026-05-25 13:56:11 +08:00
return (double)bottomLampCount / 81 * 90.0;
2026-04-27 16:45:06 +08:00
}
/// <summary>
2026-05-25 13:56:11 +08:00
/// 根据径向灯条0/1数据计算边界角度极角
2026-04-27 16:45:06 +08:00
/// </summary>
2026-05-25 13:56:11 +08:00
/// <param name="lightStates">从上到下的灯条状态索引0=顶部0°索引80=底部90°</param>
public static double ComputeBoundaryAngle(int[] lightStates)
2026-04-27 16:45:06 +08:00
{
2026-05-25 13:56:11 +08:00
if (lightStates == null || lightStates.Length != totalLights) return 0;
int firstZero = -1;
for (int i = 0; i < totalLights; i++)
2026-04-27 16:45:06 +08:00
{
2026-05-25 13:56:11 +08:00
if (lightStates[i] == 0)
2026-04-27 16:45:06 +08:00
{
2026-05-25 13:56:11 +08:00
firstZero = i;
break;
2026-04-27 16:45:06 +08:00
}
}
2026-05-25 13:56:11 +08:00
if (firstZero == -1) return 90.0; // 全亮
if (firstZero == 0) return 0.0; // 顶部即被遮
// 边界角度 = 上一个灯条的结束角 = (firstZero) * verticalAngleStep
return firstZero * verticalAngleStep;
2026-04-27 16:45:06 +08:00
}
2026-04-30 08:46:44 +08:00
2026-05-25 13:56:11 +08:00
/// <summary>
/// 极坐标梯形法积分面积(半径数组单位:度,步长单位:度)
/// </summary>
public static double IntegrateArea(double[] radiiDeg, double deltaThetaDeg)
2026-05-06 19:52:40 +08:00
{
2026-05-25 13:56:11 +08:00
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++)
2026-05-06 19:52:40 +08:00
{
2026-05-25 13:56:11 +08:00
double r1 = radiiDeg[i];
double r2 = radiiDeg[i + 1];
double avgRSq = (r1 * r1 + r2 * r2) / 2.0;
sum += avgRSq * deltaRad;
2026-05-06 19:52:40 +08:00
}
2026-05-25 13:56:11 +08:00
return 0.5 * sum;
2026-05-06 19:52:40 +08:00
}
2026-05-06 20:01:54 +08:00
2026-05-25 13:56:11 +08:00
/// <summary>
/// 根据左右眼边界半径数组,计算总视野(并集)和双目视野(交集)面积
/// </summary>
public static (double totalArea, double biArea) ComputeTotalAndBinocularArea(double[] leftRadii, double[] rightRadii, double deltaThetaDeg)
2026-04-30 08:46:44 +08:00
{
2026-05-25 13:56:11 +08:00
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++)
2026-05-04 10:25:31 +08:00
{
2026-05-25 13:56:11 +08:00
totalRadii[i] = Math.Max(leftRadii[i], rightRadii[i]);
biRadii[i] = Math.Min(leftRadii[i], rightRadii[i]);
2026-05-04 10:25:31 +08:00
}
2026-05-25 13:56:11 +08:00
double totalArea = IntegrateArea(totalRadii, deltaThetaDeg);
double biArea = IntegrateArea(biRadii, deltaThetaDeg);
return (totalArea, biArea);
2026-04-30 08:46:44 +08:00
}
2026-05-25 13:56:11 +08:00
/// <summary>
/// 保存率计算公式(带γ校正)
/// </summary>
public static double ComputePreservation(double measuredArea, double standardArea, double gamma)
2026-05-06 15:00:54 +08:00
{
2026-05-25 13:56:11 +08:00
if (standardArea <= 0) return 0;
return gamma * (measuredArea / standardArea) * 100.0;
}
2026-04-30 08:46:44 +08:00
2026-05-25 13:56:11 +08:00
/// <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++)
2026-05-06 15:00:54 +08:00
{
2026-05-25 13:56:11 +08:00
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]);
}
2026-05-06 15:00:54 +08:00
}
2026-05-25 13:56:11 +08:00
return 1.0;
2026-04-30 08:46:44 +08:00
}
2026-05-04 10:25:31 +08:00
}
2026-05-25 13:56:11 +08:00
}