优化
This commit is contained in:
@@ -40,6 +40,10 @@ namespace 头罩视野.Services
|
||||
// 只处理亮灯的情况
|
||||
if (lightData[i] == 1)
|
||||
{
|
||||
if (lightPositions.Count < lightData.Count())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
var (m, n) = lightPositions[i];
|
||||
|
||||
// 关键:只取下爪灯条(n == 1),因为只有它才对应下方的垂直视野
|
||||
@@ -114,8 +118,14 @@ namespace 头罩视野.Services
|
||||
List<System.Drawing.Point> brightPoints = new List<System.Drawing.Point>();
|
||||
for (int i = 0; i < totalLights; i++)
|
||||
{
|
||||
if (totalLights > lightData.Count())
|
||||
{
|
||||
|
||||
}
|
||||
if (lightData[i] == 1)
|
||||
{
|
||||
|
||||
|
||||
var (m, n) = lightPositions[i];
|
||||
System.Drawing.Point p = GetLightPoint(m, n);
|
||||
brightPoints.Add(p);
|
||||
@@ -166,7 +176,7 @@ namespace 头罩视野.Services
|
||||
int n = points.Count;
|
||||
if (n < 5)
|
||||
//throw new Exception("至少需要5个点来拟合椭圆");
|
||||
return new (0,0,0,0,0) ;
|
||||
return new(0, 0, 0, 0, 0);
|
||||
|
||||
// 这里是正确写法
|
||||
var M = MathNetMatrix.Build.Dense(n, 5);
|
||||
|
||||
@@ -42,7 +42,6 @@ namespace 头罩视野.Views
|
||||
private double currentAngle;
|
||||
#endregion
|
||||
|
||||
|
||||
private double _leftTotalArea = 0; // 左目总视野面积
|
||||
private double _rightTotalArea = 0; // 右目总视野面积
|
||||
private double _binocularTotalArea = 0; // 双目总视野面积
|
||||
@@ -69,13 +68,18 @@ namespace 头罩视野.Views
|
||||
MessageBox.Show("未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 硬件固定参数(提前定义好,不要改)
|
||||
private const int LightsPerStrip = 81; // 单条灯条81个灯
|
||||
private const int HalfLights = (LightsPerStrip - 1) / 2; // 40,给左右灯条用
|
||||
double stepAngle;
|
||||
|
||||
|
||||
bool isLeftOnly = false;
|
||||
bool isRightOnly = false;
|
||||
bool isBinocular = false;
|
||||
protected readonly object _lock = new object();
|
||||
private List<(int m, int n)> _lightPositions;
|
||||
private void InitLightPositions()
|
||||
{
|
||||
@@ -213,30 +217,11 @@ namespace 头罩视野.Views
|
||||
}
|
||||
//测试btn 测试按钮:读取数据,存入共享列表
|
||||
private async void Button_Click_Test(object sender, RoutedEventArgs e)
|
||||
|
||||
{
|
||||
|
||||
|
||||
ma.BtnClickFunction(Function.ButtonType.复归型, 100);
|
||||
ButtonTest.Content = "测试中....";
|
||||
testTimer.Start();
|
||||
|
||||
|
||||
double stepAngle;
|
||||
double.TryParse(fbspeed.Text.Trim(), out double val);
|
||||
|
||||
// 范围判断:必须在 0 ~ 180 之间
|
||||
if (val <= 0 || val > 180)
|
||||
{
|
||||
stepAngle = 10.0; // 超出范围用默认值
|
||||
}
|
||||
else
|
||||
{
|
||||
stepAngle = val; // 正常就用输入值
|
||||
}
|
||||
// 1. 读取输入框
|
||||
// 分辨角度 例:10
|
||||
|
||||
bool isLeftOnly = btnLeft.Content.ToString() == "左眼开" && btnRight.Content.ToString() == "右眼关";
|
||||
bool isRightOnly = btnRight.Content.ToString() == "右眼开" && btnLeft.Content.ToString() == "左眼关";
|
||||
bool isBinocular = btnLeft.Content.ToString() == "左眼开" && btnRight.Content.ToString() == "右眼开";
|
||||
@@ -254,9 +239,133 @@ namespace 头罩视野.Views
|
||||
_binocularTotalArea = 0;
|
||||
|
||||
}
|
||||
}
|
||||
//页面渲染值
|
||||
|
||||
public void UpdateVisionResults(double BotViAn)
|
||||
{
|
||||
zmsyarea.Text = _leftTotalArea.ToString("0.00"); // 左目
|
||||
ymsyarea.Text = _rightTotalArea.ToString("0.00"); // 右目
|
||||
smsyarea.Text = _binocularTotalArea.ToString("0.00"); // 双目
|
||||
|
||||
// 3. 计算空白区视野面积(双目时才有效)
|
||||
if (double.TryParse(smsyarea.Text, out double binocularTotalArea))
|
||||
{
|
||||
double blankArea = GetArea.GetBlankViewArea(binocularTotalArea);
|
||||
kbsyarea.Text = blankArea.ToString("0.00"); // 空白视野面积
|
||||
}
|
||||
//// 4. 计算下方视野面积
|
||||
int botViAnInt = (int)Math.Round(BotViAn);
|
||||
xfsyarea.Text = botViAnInt.ToString("0.0"); // 下方视野
|
||||
|
||||
// 5. 计算视野保存率(双目)
|
||||
if (double.TryParse(smsyarea.Text, out double totalAreaForRate))
|
||||
{
|
||||
double binocularRate = GetArea.CalcVisionRate(totalAreaForRate);
|
||||
sybhl.Text = binocularRate.ToString("0.00"); // 视野保存率
|
||||
}
|
||||
}
|
||||
|
||||
//读取灯泡的数据
|
||||
|
||||
private async Task ReadLightBarData()
|
||||
{
|
||||
// 无连接直接返回
|
||||
if (_modbusMaster == null || !ModbusHelper.TcpClient.Connected)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
DataList.Clear();
|
||||
// 读取灯条寄存器(地址350,长度15)
|
||||
ushort[] registers = await _modbusMaster.ReadHoldingRegistersAsync(1, 350, 15);
|
||||
|
||||
// 每个 ushort 是16位,低位在前
|
||||
foreach (ushort reg in registers)
|
||||
{
|
||||
for (int bit = 0; bit < 16; bit++)
|
||||
{
|
||||
// 取第bit位的值:0或1
|
||||
int lightBit = (reg & (1 << bit)) != 0 ? 1 : 0;
|
||||
lock (_lock)
|
||||
{
|
||||
DataList.Add(lightBit);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
// 调试:打印转换后的数据长度
|
||||
System.Diagnostics.Debug.WriteLine($"灯条二进制数据总长度:{DataList.Count}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"灯条数据读取失败:{ex.Message}");
|
||||
//DataList.Clear(); // 出错时清空数据
|
||||
}
|
||||
}
|
||||
private async void Timer_Tick(object sender, EventArgs e)
|
||||
|
||||
{
|
||||
//System.Diagnostics.Debug.WriteLine("定时器触发了!" + DateTime.Now);
|
||||
// 调用你原来的读取方
|
||||
//await ReadAddr262DataAsync();
|
||||
await calCurrentangle();
|
||||
// 组装当前数据
|
||||
var data = new TestDataStore.TestRecord
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
LeftEyeArea = double.TryParse(zmsyarea.Text, out var l) ? l : 0,
|
||||
RightEyeArea = double.TryParse(ymsyarea.Text, out var r) ? r : 0,
|
||||
BinocularArea = double.TryParse(smsyarea.Text, out var b) ? b : 0,
|
||||
LowerVision = double.TryParse(xfsyarea.Text, out var lv) ? lv : 0,
|
||||
VisionRetentionRate = double.TryParse(sybhl.Text, out var vr) ? vr : 0
|
||||
};
|
||||
|
||||
|
||||
// ==================== 去重判断 ====================
|
||||
if (_lastRecord != null &&
|
||||
data.LeftEyeArea == _lastRecord.LeftEyeArea &&
|
||||
data.RightEyeArea == _lastRecord.RightEyeArea &&
|
||||
data.BinocularArea == _lastRecord.BinocularArea &&
|
||||
data.LowerVision == _lastRecord.LowerVision &&
|
||||
data.VisionRetentionRate == _lastRecord.VisionRetentionRate)
|
||||
{
|
||||
return; // 一样就不添加
|
||||
}
|
||||
//原来存的数据清空 切换页面会清空
|
||||
//TestDataStore.Records.Clear();
|
||||
// 不一样 → 插入表格
|
||||
TestDataStore.AddNewRecord(data);
|
||||
_lastRecord = data;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task calCurrentangle()
|
||||
{
|
||||
|
||||
double.TryParse(fbspeed.Text.Trim(), out double val);
|
||||
|
||||
//// 范围判断:必须在 0 ~ 180 之间
|
||||
//if (val <= 0 || val > 180)
|
||||
//{
|
||||
// stepAngle = 10.0; // 超出范围用默认值
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// stepAngle = val; // 正常就用输入值
|
||||
//}
|
||||
// 1. 读取输入框
|
||||
// 分辨角度 例:10
|
||||
|
||||
|
||||
|
||||
// 2. 从0转到180,每 stepAngle 执行一次
|
||||
for (double current = stepAngle; current <= 180; current += stepAngle)
|
||||
for (double current = stepAngle; current < 180; current += stepAngle)
|
||||
{
|
||||
|
||||
await ReadLightBarData();
|
||||
@@ -264,6 +373,10 @@ namespace 头罩视野.Views
|
||||
// 读完再转数组
|
||||
int[] lightData = DataList.Cast<int>().ToArray();
|
||||
|
||||
if (lightData.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//开始计算视野面积
|
||||
double singleArea = GetArea.CalculateEllipseArea(lightData, _lightPositions);
|
||||
|
||||
@@ -298,103 +411,6 @@ namespace 头罩视野.Views
|
||||
// minBottomViewAngle = bottomViewAngle;
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
//页面渲染值
|
||||
|
||||
public void UpdateVisionResults(double BotViAn)
|
||||
{
|
||||
zmsyarea.Text = _leftTotalArea.ToString("0.00"); // 左目
|
||||
ymsyarea.Text = _rightTotalArea.ToString("0.00"); // 右目
|
||||
smsyarea.Text = _binocularTotalArea.ToString("0.00"); // 双目
|
||||
|
||||
// 3. 计算空白区视野面积(双目时才有效)
|
||||
if (double.TryParse(smsyarea.Text, out double binocularTotalArea))
|
||||
{
|
||||
double blankArea = GetArea.GetBlankViewArea(binocularTotalArea);
|
||||
kbsyarea.Text = blankArea.ToString("0.00"); // 空白视野面积
|
||||
}
|
||||
|
||||
//// 4. 计算下方视野面积
|
||||
int botViAnInt = (int)Math.Round(BotViAn);
|
||||
xfsyarea.Text = botViAnInt.ToString("0.0"); // 下方视野
|
||||
|
||||
// 5. 计算视野保存率(双目)
|
||||
if (double.TryParse(smsyarea.Text, out double totalAreaForRate))
|
||||
{
|
||||
double binocularRate = GetArea.CalcVisionRate(totalAreaForRate);
|
||||
sybhl.Text = binocularRate.ToString("0.00"); // 视野保存率
|
||||
}
|
||||
}
|
||||
|
||||
//读取灯泡的数据
|
||||
|
||||
private async Task ReadLightBarData()
|
||||
{
|
||||
// 无连接直接返回
|
||||
if (_modbusMaster == null || !ModbusHelper.TcpClient.Connected)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
DataList.Clear();
|
||||
// 读取灯条寄存器(地址350,长度15)
|
||||
ushort[] registers = await _modbusMaster.ReadHoldingRegistersAsync(1, 350, 15);
|
||||
|
||||
// 每个 ushort 是16位,低位在前
|
||||
foreach (ushort reg in registers)
|
||||
{
|
||||
for (int bit = 0; bit < 16; bit++)
|
||||
{
|
||||
// 取第bit位的值:0或1
|
||||
int lightBit = (reg & (1 << bit)) != 0 ? 1 : 0;
|
||||
DataList.Add(lightBit);
|
||||
}
|
||||
}
|
||||
|
||||
// 调试:打印转换后的数据长度
|
||||
System.Diagnostics.Debug.WriteLine($"灯条二进制数据总长度:{DataList.Count}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"灯条数据读取失败:{ex.Message}");
|
||||
//DataList.Clear(); // 出错时清空数据
|
||||
}
|
||||
}
|
||||
private async void Timer_Tick(object sender, EventArgs e)
|
||||
|
||||
{
|
||||
//System.Diagnostics.Debug.WriteLine("定时器触发了!" + DateTime.Now);
|
||||
// 调用你原来的读取方
|
||||
//await ReadAddr262DataAsync();
|
||||
|
||||
// 组装当前数据
|
||||
var data = new TestDataStore.TestRecord
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
LeftEyeArea = double.TryParse(zmsyarea.Text, out var l) ? l : 0,
|
||||
RightEyeArea = double.TryParse(ymsyarea.Text, out var r) ? r : 0,
|
||||
BinocularArea = double.TryParse(smsyarea.Text, out var b) ? b : 0,
|
||||
LowerVision = double.TryParse(xfsyarea.Text, out var lv) ? lv : 0,
|
||||
VisionRetentionRate = double.TryParse(sybhl.Text, out var vr) ? vr : 0
|
||||
};
|
||||
|
||||
// ==================== 去重判断 ====================
|
||||
if (_lastRecord != null &&
|
||||
data.LeftEyeArea == _lastRecord.LeftEyeArea &&
|
||||
data.RightEyeArea == _lastRecord.RightEyeArea &&
|
||||
data.BinocularArea == _lastRecord.BinocularArea &&
|
||||
data.LowerVision == _lastRecord.LowerVision &&
|
||||
data.VisionRetentionRate == _lastRecord.VisionRetentionRate)
|
||||
{
|
||||
return; // 一样就不添加
|
||||
}
|
||||
//原来存的数据清空 切换页面会清空
|
||||
//TestDataStore.Records.Clear();
|
||||
// 不一样 → 插入表格
|
||||
TestDataStore.AddNewRecord(data);
|
||||
_lastRecord = data;
|
||||
}
|
||||
|
||||
//打印
|
||||
@@ -408,7 +424,7 @@ namespace 头罩视野.Views
|
||||
//试样测试
|
||||
|
||||
|
||||
private void TbTest_Checked(object sender, RoutedEventArgs e)
|
||||
private async void TbTest_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 选中 → 试样测试
|
||||
|
||||
@@ -417,16 +433,16 @@ namespace 头罩视野.Views
|
||||
|
||||
tbTest.Background = System.Windows.Media.Brushes.LightSkyBlue;
|
||||
System.Diagnostics.Debug.WriteLine($"1232312312");
|
||||
_modbusMaster.WriteSingleCoilAsync(1, 41, true);
|
||||
await _modbusMaster.WriteSingleCoilAsync(1, 41, true);
|
||||
}
|
||||
|
||||
private void TbTest_Unchecked(object sender, RoutedEventArgs e)
|
||||
private async void TbTest_Unchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// 取消 → 空白测试
|
||||
|
||||
tbTest.Content = "试样测试";
|
||||
tbTest.Background = System.Windows.Media.Brushes.LightGray;
|
||||
_modbusMaster.WriteSingleCoilAsync(1, 41, false);
|
||||
await _modbusMaster.WriteSingleCoilAsync(1, 41, false);
|
||||
}
|
||||
private void Button_Click_home(object sender, RoutedEventArgs e)
|
||||
{
|
||||
@@ -470,7 +486,7 @@ namespace 头罩视野.Views
|
||||
//ReadAndUpdateFloatAsync(210 ,2, ymsyarea, "F2", " "),
|
||||
ReadAndUpdateFloatRangeAsync(200, 12, "F2", "°"),
|
||||
//ReadAndUpdateFloatAsync(424 ,2, kbsyarea, "F2", "cm²"),
|
||||
ReadAndUpdateFloatAsync(310, 2, zdangle, "F2", "°/S"),
|
||||
ReadAndUpdateFloatAsync(310, 2, zdangle, "F2", ""),
|
||||
//ReadAndUpdateFloatAsync(430 ,2, sybhl, "F2", " "),
|
||||
|
||||
//前1从站地址,后1是长度
|
||||
@@ -624,9 +640,6 @@ namespace 头罩视野.Views
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user