Files
hoodFieldOfView/头罩视野slove/头罩视野/ModbusHelper.cs
2026-04-23 10:31:17 +08:00

240 lines
7.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Modbus.Device;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Windows;
using .Services.Data;
public static class ModbusHelper
{
// 全局唯一连接,所有页面共用
public static TcpClient TcpClient => ModbusResourceManager.Instance.TcpClient;
// 统一连接方法(全项目只调用一次)
public static bool Connect(string ip, int port = 502)
{
return ModbusResourceManager.Instance.Init(ip, port);
}
// 判断是否连接成功
public static bool IsConnected => TcpClient != null && TcpClient.Connected;
// <summary>
/// 公共保存方法(用户自选文件夹)
/// </summary>
/// <param name="dataList">你的数据集合</param>
/// <param name="defaultFileName">默认文件名</param>
public static void SaveToCsv(List<dynamic> dataList, string defaultFileName)
{
if (dataList == null || dataList.Count == 0)
{
MessageBox.Show("无数据可保存!");
return;
}
// 选择文件夹
var folderDialog = new OpenFolderDialog
{
Title = "请选择保存路径"
};
if (folderDialog.ShowDialog() != true)
return;
string folderPath = folderDialog.FolderName;
string filePath = Path.Combine(folderPath, defaultFileName);
// 写入 CSV
using (var sw = new StreamWriter(filePath, false, Encoding.UTF8))
{
var firstRow = (IDictionary<string, object>)dataList[0];
sw.WriteLine(string.Join(",", firstRow.Keys));
foreach (var item in dataList)
{
var dict = (IDictionary<string, object>)item;
sw.WriteLine(string.Join(",", dict.Values));
}
}
MessageBox.Show("保存成功!\n" + filePath);
}
/// <summary>
/// 计算单眼视野面积
/// </summary>
/// <param name="groupData">20组数据每组72个通道</param>
/// <param name="threshold">有效亮度阈值如80</param>
/// <param name="standardTotalArea">标准视野面积如120</param>
/// <returns>计算好的面积</returns>
///
public static double CalculateEyeArea(List<double[]> groupData, double threshold, double standardArea)
{
double[] avg = new double[72];
for (int c = 0; c < 72; c++)
{
double sum = 0;
foreach (var g in groupData) sum += g[c];
avg[c] = sum / groupData.Count;
}
int valid = avg.Count(v => v >= threshold);
return (valid / 72.0) * standardArea;
}
//计算单眼面积调用的方法
//double leftArea = CalculateEyeArea(
// leftEye20Groups, // 左眼20组数据
// 80, // 阈值
// 120 // 标准面积
//);
//double rightArea = .CalculateEyeArea(
// rightEye20Groups, // 右眼20组数据
// 80, // 阈值
// 120 // 标准面积
//);
//计算双目视野面积
/// <summary>
/// 计算双目视野面积(左右眼同时可见)
/// </summary>
public static double CalcBinocularArea(
List<double[]> leftGroups,
List<double[]> rightGroups,
double threshold,
double standardArea)
{
// 1. 左眼平均数据
double[] leftAvg = new double[72];
for (int i = 0; i < 72; i++)
{
double sum = 0;
foreach (var g in leftGroups) sum += g[i];
leftAvg[i] = sum / leftGroups.Count;
}
// 2. 右眼平均数据
double[] rightAvg = new double[72];
for (int i = 0; i < 72; i++)
{
double sum = 0;
foreach (var g in rightGroups) sum += g[i];
rightAvg[i] = sum / rightGroups.Count;
}
// 3. 双目同时有效点数(左右都亮才算)
int biValid = 0;
for (int i = 0; i < 72; i++)
{
if (leftAvg[i] >= threshold && rightAvg[i] >= threshold)
biValid++;
}
// 4. 双目视野面积
return (biValid / 72.0) * standardArea;
}
//调用公式
// 你从Modbus拿到的20组数据
//List<double[]> left20Groups = ...;
//List<double[]> right20Groups = ...;
//double threshold = 80;
//double standardArea = 120;
//// 左眼
//double left = VisionCalculator.CalcEyeArea(left20Groups, threshold, standardArea);
//// 右眼
//double right = VisionCalculator.CalcEyeArea(right20Groups, threshold, standardArea);
//// 双目视野面积
//double binocular = VisionCalculator.CalcBinocularArea(left20Groups, right20Groups, threshold, standardArea);
//// 总视野面积
//double total = left + right - binocular;
//下方视野面积
public static double CalcLowerEyeArea(
List<double[]> eyeGroups,
double threshold,
double standardLowerArea)
{
// 1. 每个通道求20组平均
double[] avg = new double[72];
for (int i = 0; i < 72; i++)
{
double sum = 0;
foreach (var g in eyeGroups) sum += g[i];
avg[i] = sum / eyeGroups.Count;
}
// 2. 只统计下半 36 个通道(下方视野)
int validCount = 0;
for (int i = 36; i < 72; i++) // 36~71 是下半区
{
if (avg[i] >= threshold)
validCount++;
}
// 3. 计算下方视野面积
return (validCount / 36.0) * standardLowerArea;
}
// 总下方视野面积调用
//double totalLower = leftLower + rightLower - binocularLower;
//空白视野面积计算
//空白视野面积 = 标准视野总面积 实测总视野面积
//总视野面积 = 左眼面积 + 右眼面积 双目重叠面积
// 前面已经算出来的
//double leftArea = ...;
//double rightArea = ...;
//double binocularArea = ...;
//// 总视野
//double totalVisionArea = leftArea + rightArea - binocularArea;
//// 标准总面积(设备固定值,比如 120
//double standardTotalArea = 120;
//// 空白视野面积
//double blankArea = standardTotalArea - totalVisionArea;
//视野保存率
//double totalSaveRate = (总视野面积 / 标准总视野面积) * 100;
public static class VisionCalculator
{
/// <summary>
/// 计算视野保存率
/// </summary>
/// <param name="actualArea">实测面积</param>
/// <param name="standardArea">标准面积</param>
/// <returns>保存率 %</returns>
public static double CalculateVisionSaveRate(double actualArea, double standardArea)
{
if (standardArea == 0) return 0;
return (actualArea / standardArea) * 100;
}
}
//double totalSaveRate = VisionCalculator.CalculateVisionSaveRate(totalVisionArea, standardTotalArea);
}