Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ede5b8c9d1 | |||
| 74e66f51d3 | |||
| 87e7b4cf35 | |||
| d87ac91bd5 | |||
| d661211696 |
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user