|
// SGMeasurementDlg.h: 头文件
|
//
|
|
#pragma once
|
#include <vector>
|
#include <numeric>
|
#include <algorithm>
|
|
// CSGMeasurementDlg 对话框
|
class CSGMeasurementDlg : public CDialogEx
|
{
|
// 构造
|
public:
|
CSGMeasurementDlg(CWnd* pParent = nullptr); // 标准构造函数
|
|
// 对话框数据
|
#ifdef AFX_DESIGN_TIME
|
enum { IDD = IDD_SGMEASUREMENT_DIALOG };
|
#endif
|
|
protected:
|
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
|
|
// 实现
|
protected:
|
HICON m_hIcon;
|
|
// 生成的消息映射函数
|
virtual BOOL OnInitDialog();
|
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
|
afx_msg void OnPaint();
|
afx_msg HCURSOR OnQueryDragIcon();
|
afx_msg void OnTimer(UINT_PTR nIDEvent);
|
afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct);
|
afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
|
afx_msg void OnClose();
|
afx_msg LRESULT OnTrayIconClick(WPARAM wParam, LPARAM lParam);
|
afx_msg void OnTrayRestore();
|
afx_msg void OnTrayExit();
|
afx_msg void OnBnClickedButtonConnect();
|
afx_msg void OnBnClickedButtonDisconnect();
|
afx_msg void OnBnClickedButtonReceiveFromCtrl();
|
afx_msg void OnBnClickedButtonSendToCtrl();
|
afx_msg void OnBnClickedButtonClearStore();
|
afx_msg void OnBnClickedButtonStartStore();
|
afx_msg void OnBnClickedButtonStopStore();
|
afx_msg void OnBnClickedButtonClearLog();
|
DECLARE_MESSAGE_MAP()
|
|
private:
|
void ExitApplication();
|
|
/**
|
* @brief 更新界面控件的可用状态。
|
*
|
* 根据设备连接状态 `bConnected` 和存储状态 `bStoring` 动态控制界面上按钮、
|
* 编辑框、下拉框等控件的可用/禁用状态。
|
*
|
* @param bConnected 设备当前是否已连接,TRUE 表示已连接,FALSE 表示未连接。
|
* @param bStoring 当前是否正在进行数据存储,TRUE 表示正在存储。
|
*/
|
void UpdateControlStatus(BOOL bConnected, BOOL bStoring = FALSE);
|
|
/**
|
* @brief 启动批量日志追加,暂停自动滚动,提高性能。
|
*/
|
void AppendLogLineBatchBegin();
|
|
/**
|
* @brief 结束批量日志追加,恢复自动滚动并刷新显示。
|
*/
|
void AppendLogLineBatchEnd();
|
|
/**
|
* @brief 限制富文本框中的最大行数,避免日志过多导致性能问题。
|
*
|
* @param maxLines 最大保留的行数,默认值为 100。
|
*/
|
void TrimRichEditLineLimit(int maxLines = 100);
|
|
/**
|
* @brief 向日志窗口追加一条带颜色样式的日志行。
|
*
|
* @param content 日志内容。
|
* @param color 字体颜色,默认为黑色。
|
*/
|
void AppendLogLineRichStyled(const CString& content, COLORREF color = RGB(0, 0, 0));
|
|
/**
|
* @brief 高亮日志中所有匹配指定字符串的部分。
|
*
|
* @param strSearch 要匹配的字符串。
|
* @param clrHighlight 高亮颜色,默认为橙色(RGB(255, 165, 0))。
|
*/
|
void HighlightAllMatches(const CString& strSearch, COLORREF clrHighlight = RGB(255, 165, 0));
|
|
/**
|
* @brief 以格式化方式输出指定通道的测量数据样本到日志。
|
*
|
* 每行输出固定数量(如 7)个浮点数据,带时间戳、通道编号标识,便于调试查看。
|
*
|
* @param nOutNo 输出端口编号,用于标识日志来源,如 OUT1、OUT2 等。
|
* @param vecBuffer 测量数据缓存,将被逐行打印到日志中。
|
*/
|
void PrintSampleData(int nOutNo, const std::vector<float>& vecBuffer);
|
|
/**
|
* @brief 尝试连接到测量设备。
|
*
|
* @return true 表示连接成功,false 表示连接失败。
|
*/
|
bool ConnectToDevice();
|
|
/**
|
* @brief 断开与测量设备的连接。
|
*
|
* @return true 表示断开成功,false 表示断开失败。
|
*/
|
bool DisconnectFromDevice();
|
|
/**
|
* @brief 原地清除无效值(如 -999.0f)并更新数据。
|
*
|
* @param nOutNo 输出通道编号,用于日志记录。
|
* @param vecData 输入输出数据容器,内部将被就地裁剪。
|
* @param fInvalid 无效值的判断阈值,默认值为 -999.0f。
|
*/
|
void CleanInvalidValuesInPlace(int nOutNo, std::vector<float>& vecData, float fInvalid = -999.0f);
|
|
/**
|
* @brief 将有效数据切割成两段玻璃数据(Glass1 与 Glass2)。
|
*
|
* @param nOutNo 输出通道编号,用于日志记录。
|
* @param validData 输入的有效数据(应已裁剪边界)。
|
* @param vecGlass1 输出第一段玻璃数据。
|
* @param vecGlass2 输出第二段玻璃数据。
|
* @param fJumpThreshold 跳变阈值,用于检测数据的明显断点。
|
* @param nWindow 跳变判断的前后窗口宽度。
|
* @param nValleyMargin valley 点之后多少个点作为实际切割点。
|
* @param nMinGlass1Count 第一段最少有效点数限制。
|
*
|
* @return true 表示切割成功,false 表示失败(例如数据不足或无明显跳变)。
|
*/
|
bool SplitGlassSegments(int nOutNo, const std::vector<float>& validData,
|
std::vector<float>& vecGlass1, std::vector<float>& vecGlass2,
|
float fJumpThreshold = 1.0f, int nWindow = 3, int nValleyMargin = 0,
|
int nMinGlass1Count = 10);
|
|
/**
|
* @brief 从输入数据中提取一个固定长度的稳定区间。
|
*
|
* @param nOutNo 输出通道编号,用于日志记录。
|
* @param vecIn 输入原始数据。
|
* @param vecOut 输出提取的稳定区域数据。
|
* @param nFixedCount 稳定区域的点数要求(必须固定数量)。
|
* @param fMaxDelta 允许的最大波动范围(最大值 - 最小值)。
|
*
|
* @return true 表示成功找到稳定区间,false 表示未找到。
|
*/
|
bool ExtractStableRegionFixed(int nOutNo,
|
const std::vector<float>& vecIn,
|
std::vector<float>& vecOut,
|
int nFixedCount = 5, float fMaxDelta = 0.05f);
|
|
/**
|
* @brief 计算两片玻璃稳定区域的平均值和偏移量。
|
*
|
* @param vecGlass1 第一段稳定数据。
|
* @param vecGlass2 第二段稳定数据。
|
* @param fAvg1 返回第一段的平均值。
|
* @param fAvg2 返回第二段的平均值。
|
* @param fOffset 返回两段的偏移值(绝对值差)。
|
*
|
* @return true 表示计算成功,false 表示输入无效(如空数据)。
|
*/
|
bool CalcGlassOffset(const std::vector<float>& vecGlass1,
|
const std::vector<float>& vecGlass2,
|
float& fAvg1, float& fAvg2, float& fOffset);
|
|
bool InitDataStorage();
|
|
bool StartDataStorage();
|
|
bool StopDataStorage();
|
|
/**
|
* @brief 分析指定端口的存储数据,并提取两段玻璃数据与稳定区,计算偏移。
|
*
|
* @param nOutNo 输出端口编号(1~4)
|
* @return float 成功返回计算出的偏移量,失败返回 -1.0f
|
*/
|
float AnalyzeStoredData(int nOutNo);
|
|
// === 系统状态与运行数据 ===
|
|
/**
|
* @brief 当前是否已连接到传感器控制器
|
*/
|
bool m_bConnected;
|
|
/**
|
* @brief 当前是否正在进行数据存储
|
*/
|
bool m_bSaving;
|
|
/**
|
* @brief 四个输出端口的当前计算结果(如偏移量或厚度等)
|
*/
|
double m_dOutValues[4];
|
|
// === 存储设置相关 ===
|
|
/**
|
* @brief 是否使用硬件触发信号(0=否,1=是)
|
*/
|
int m_nUseTrigger;
|
|
/**
|
* @brief 每次采集的数据点数量
|
*/
|
int m_nSavePointCount;
|
|
/**
|
* @brief 输出端口选择下拉框控件(用于设置采集端口)
|
*/
|
CComboBox m_comboOutputPort;
|
|
// === 跳变检测与玻璃识别参数(SplitGlassSegments 使用) ===
|
|
/**
|
* @brief 跳变阈值(例如 0.2mm),用于检测两片玻璃之间的高度跳变
|
*/
|
float m_fJumpThreshold;
|
|
/**
|
* @brief 跳变检测窗口半宽度(用于差分计算)
|
*/
|
int m_nJumpWindow;
|
|
/**
|
* @brief valley 点右移的偏移量,用于最终确定分割点
|
*/
|
int m_nValleyMargin;
|
|
/**
|
* @brief 第一片玻璃最少所需的数据点数
|
*/
|
int m_nMinGlass1Count;
|
|
// === 稳定区域提取参数(ExtractStableRegionFixed 使用) ===
|
|
/**
|
* @brief 每段稳定区域要提取的固定数据点数
|
*/
|
int m_nFixedCount;
|
|
/**
|
* @brief 最大允许波动范围(例如 0.05mm),判断是否为“稳定”区域
|
*/
|
float m_fMaxDelta;
|
|
// === 日志控件 ===
|
|
/**
|
* @brief 富文本控件,用于输出带颜色的日志信息
|
*/
|
CRichEditCtrl m_editLog;
|
|
// === 托盘图标管理 ===
|
|
/**
|
* @brief 托盘图标相关数据结构(NOTIFYICONDATA)
|
*/
|
NOTIFYICONDATA m_trayIconData;
|
|
/**
|
* @brief 托盘图标的唯一 ID
|
*/
|
UINT m_nTrayIconID;
|
|
/**
|
* @brief 标记托盘图标是否已成功创建
|
*/
|
BOOL m_bTrayIconCreated;
|
|
/**
|
* @brief 标记程序是否通过托盘图标退出
|
*/
|
BOOL m_bExitingFromTray;
|
};
|