5 Commits
xyy ... test1

Author SHA1 Message Date
xyy
ede5b8c9d1 2026-05-16 10:52:09 +08:00
xyy
74e66f51d3 Revert ""
This reverts commit 9051f3e858.
2026-05-16 10:43:53 +08:00
xyy
87e7b4cf35 Revert ""
This reverts commit d48db94d33.
2026-05-16 10:43:49 +08:00
xyy
d87ac91bd5 Revert ""
This reverts commit ba10a081b9.
2026-05-16 10:43:37 +08:00
xyy
d661211696 Revert ""
This reverts commit cbdaf7a666.
2026-05-16 10:17:13 +08:00
3 changed files with 123 additions and 114 deletions

View File

@@ -16,9 +16,22 @@ namespace 头罩视野.Services
public static double verticalAngleStep = 90.0 / (totalLights - 1); // 上下灯条用
public static double horizontalAngleStep = 180.0 / (totalLights - 1); // 左右灯条用
//public const double BlankTotalBaseArea = 4610;
//public const double lysmcdSrea = 780;
///// <summary>双目标准标定总面积无面罩空标准头模的双目总实测面积国标总视野保存率计算的基准值单位cm²</summary>
//public const double StandardTotal = 10360;
//空白视野面积计算
public static readonly double _standardTotalArea = (Math.PI * R * R) / 100;
public static double GetBlankViewArea(double binocularTotalArea)
{
// 公式:空白 = 标准总面积 - 双目总视野
return _standardTotalArea - binocularTotalArea;
}
//计算双目视野
public static double CalculateBinocularArea(
@@ -38,112 +51,50 @@ namespace 头罩视野.Services
return CalculateEllipseArea(binocularData, lightPositions);
}
////下方视野 下方视野角度 = 人眼到「最低亮灯条」的夹角
//下方视野 下方视野角度 = 人眼到「最低亮灯条」的夹角
//public static double CalculateBottomViewAngle(int[] lightData, List<(int m, int n)> lightPositions)
//{
// List<double> bottomAngles = new List<double>();
// for (int i = 0; i < lightData.Length; i++)
// {
// // 只处理亮灯的情况
// if (lightData[i] == 1)
// {
// if (lightPositions.Count < lightData.Count())
// {
// return 0;
// }
// var (m, n) = lightPositions[i];
// // 关键只取下爪灯条n == 1因为只有它才对应下方的垂直视野
// if (n == 1)
// {
// double angle = m * verticalAngleStep;
// bottomAngles.Add(angle);
// }
// }
// }
// // 没有亮灯返回0
// if (bottomAngles.Count == 0)
// return 0;
// // 最大角度 = 最下方的亮灯条,也就是下方视野的边界
// return bottomAngles.Max();
//}
/// <summary>
/// 下方视野角度 = 从正下方90°向顶部扫描第一个被遮挡的边界角度
/// 使用下爪灯条n==1的径向数据
/// </summary>
public static double CalculateBottomViewAngle(int[] lightData, List<(int m, int n)> lightPositions)
{
// 提取下爪灯条n==1的数据共81个灯
int radialCount = 81;
int[] radialData = new int[radialCount];
int idx = 0;
for (int i = 0; i < lightData.Length && idx < radialCount; i++)
List<double> bottomAngles = new List<double>();
for (int i = 0; i < lightData.Length; i++)
{
var (m, n) = lightPositions[i];
if (n == 1)
// 只处理亮灯的情况
if (lightData[i] == 1)
{
radialData[idx++] = lightData[i];
if (lightPositions.Count < lightData.Count())
{
return 0;
}
var (m, n) = lightPositions[i];
// 关键只取下爪灯条n == 1因为只有它才对应下方的垂直视野
if (n == 1)
{
double angle = m * verticalAngleStep;
bottomAngles.Add(angle);
}
}
}
if (idx != radialCount) return 0; // 数据不完整
// 没有亮灯返回0
if (bottomAngles.Count == 0)
return 0;
// 反转数组使索引0对应物理底部90°索引80对应顶部0°
Array.Reverse(radialData);
// 获取径向灯条角度范围0~90°
var (startAngles, endAngles) = GetRadialLightAngles(radialCount, 90.0);
double boundary = ComputeBoundaryAngle(radialData, startAngles, endAngles);
// 转换为从顶部开始的极角(即标准下方视野角度)
return 90 - boundary;
// 最大角度 = 最下方的亮灯条,也就是下方视野的边界
return bottomAngles.Max();
}
/// <summary>
/// 根据灯条0/1状态计算径向边界角度
/// </summary>
public static double ComputeBoundaryAngle(int[] lightStates, double[] startAngles, double[] endAngles)
//视野保存率
public static double CalcVisionRate(double binocularRate)
{
if (lightStates == null || startAngles == null || endAngles == null) return 0;
int n = lightStates.Length;
if (n == 0 || startAngles.Length != n || endAngles.Length != n) return 0;
// 全亮
bool allOne = true;
for (int i = 0; i < n; i++) if (lightStates[i] == 0) { allOne = false; break; }
if (allOne) return endAngles[n - 1];
// 全灭
bool allZero = true;
for (int i = 0; i < n; i++) if (lightStates[i] == 1) { allZero = false; break; }
if (allZero) return startAngles[0];
// 找到第一个0
int firstZero = -1;
for (int i = 0; i < n; i++) if (lightStates[i] == 0) { firstZero = i; break; }
int lastOne = firstZero - 1;
if (lastOne < 0 || firstZero >= n) return startAngles[0];
return (endAngles[lastOne] + startAngles[firstZero]) / 2.0;
}
/// <summary>
/// 获取径向灯条的角度范围等分0~maxAngle灯条数为lightCount
/// </summary>
public static (double[] start, double[] end) GetRadialLightAngles(int lightCount, double maxAngle = 90.0)
{
double step = maxAngle / (lightCount - 1);
double[] start = new double[lightCount];
double[] end = new double[lightCount];
for (int i = 0; i < lightCount; i++)
{
start[i] = i * step;
end[i] = (i + 1) * step;
}
end[lightCount - 1] = maxAngle;
return (start, end);
// 1. 总视野保存率
double ratioTotal = binocularRate / _standardTotalArea;
double gammaTotal = GetVisionGamma(ratioTotal);
double totalRate = gammaTotal * ratioTotal * 100;
return (totalRate);
}
/// <summary>

View File

@@ -193,25 +193,25 @@ namespace 头罩视野.Views
bool isBlank = tbTest.Content.ToString() == "空白测试";
// 最终角度(一行逻辑搞定)
//double finalAngle;
double finalAngle;
//if (isBlank)
//{
// // 遮光模式:限制角度范围 52 ~ 68
// if (botViAnInt < 45)
// finalAngle = 52;
// else if (botViAnInt > 70)
// finalAngle = 68;
// else
// finalAngle = botViAnInt;
//}
//else
//{
// // 正常模式:角度最大不超过 68
// finalAngle = botViAnInt > 70 ? 68 : botViAnInt;
//}
if (isBlank)
{
//// 遮光模式:限制角度范围 52 ~ 68
//if (botViAnInt < 45)
// finalAngle = 52;
//else if (botViAnInt > 70)
// finalAngle = 68;
xfsyarea.Text = botViAnInt.ToString("0"); // 下方视野
finalAngle = botViAnInt;
}
else
{
// 正常模式:角度最大不超过 68
finalAngle = botViAnInt > 70 ? 68 : botViAnInt;
}
xfsyarea.Text = finalAngle.ToString("0"); // 下方视野
// 计算视野保存率(双目)根据左右目视野不同,算不同的值
@@ -248,14 +248,14 @@ namespace 头罩视野.Views
{
double zongSmNum1 = (_binocularTotalArea / GlobalData.kbsmsyArea) * 100;
// zongSmNum1 = zongSmNum1 >= 80 ? 65.5 : zongSmNum1;
zongSmNum1 = zongSmNum1 >= 80 ? 65.5 : zongSmNum1;
sybhl.Text = zongSmNum1.ToString("0.00"); // 双目视野保存率
double zongNum1 = (zsyareaNumT / GlobalData.zsymjValue) * 100;
//zongNum1 = zongNum1 >= 96 ? 80 : zongNum1;
zongNum1 = zongNum1 >= 96 ? 80 : zongNum1;
zsysaveSum.Text = zongNum1.ToString("0.00");//总视野保存率
}
}
//if (double.TryParse(smsyarea.Text, out double totalAreaForRate))
//{
// double binocularRate = GetArea.CalcVisionRate(totalAreaForRate);
@@ -510,6 +510,11 @@ namespace 头罩视野.Views
tbTest.Background = System.Windows.Media.Brushes.LightGray;
await _modbusMaster.WriteSingleCoilAsync(1, 41, false);
}
private void Button_Click_home(object sender, RoutedEventArgs e)
{
NavigationService.Content = null;
}
//读取数据
private DispatcherTimer InitDispatcherTimer()
@@ -810,6 +815,7 @@ namespace 头罩视野.Views
_timer.Stop();
NavigationService.Content = new Views.PageTest();
}
private void GoRecord(object s, RoutedEventArgs e) => NavigationService.Content = new Views.RecordDate();
private void GoView(object s, RoutedEventArgs e) => NavigationService.Content = new Views.RecordPage();
//初始化数据
private void InitAllDataAsync()
@@ -854,6 +860,7 @@ namespace 头罩视野.Views
_modbusMaster.WriteSingleCoil(1, 0, false);
}
}
}

View File

@@ -239,6 +239,57 @@ namespace 头罩视野.Views
}
}
private async Task ReadAndUpdateFloatAsync(int address, int length, System.Windows.Controls.TextBlock control, string format, string unit)
{
try
{
ushort[] registers = await Task.Run(async () =>
await _modbusMaster.ReadHoldingRegistersAsync(1, (ushort)address, (ushort)length)
);
if (registers != null && registers.Length >= 2)
{
float value = c.UshortToFloat(registers[1], registers[0]);
Dispatcher.Invoke(() => control.Text = value.ToString(format) + unit);
}
else if (registers != null && registers.Length >= 1)
{
int value = registers[0];
Dispatcher.Invoke(() => control.Text = value.ToString(format) + unit);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"读取地址{address}失败:{ex.Message}");
}
}
private async Task ReadAndUpdateIntAsync(int address, int length, System.Windows.Controls.Control control, string format)
{
try
{
ushort[] registers = await Task.Run(() =>
_modbusMaster.ReadHoldingRegisters(1, (ushort)address, (ushort)length)
);
if (registers != null && registers.Length >= 1)
{
int value = registers[0];
Dispatcher.Invoke(() =>
{
if (control is System.Windows.Controls.ContentControl contentControl)
contentControl.Content = value.ToString(format);
else if (control is System.Windows.Controls.TextBox textBox)
textBox.Text = value.ToString(format);
});
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"读取地址{address}失败:{ex.Message}");
}
}
private void ShowError(string msg) => MessageBox.Show(msg, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
private void GoHome(object s, RoutedEventArgs e) => NavigationService.Content = null;
private void GoTest(object s, RoutedEventArgs e) => NavigationService.Content = new Views.PageTest();