14 KiB
测试数据管理
**本文档引用的文件** - [TdManager.cpp](file://cpp/Managers/TdManager.cpp) - [TdManager.h](file://h/TdManager.h) - [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp) - [TestingData.h](file://h/TestingData.h) - [TdChannel.cpp](file://cpp/ProblemZone/TdChannel.cpp) - [TdChannel.h](file://h/TdChannel.h) - [TdRecord.cpp](file://cpp/ProblemZone/TdRecord.cpp) - [TdRecord.h](file://h/TdRecord.h) - [excel.cpp](file://cpp/Tools/excel.cpp) - [excel.h](file://h/excel.h) - [DevManager.h](file://h/DevManager.h) - [IOManager.h](file://h/IOManager.h) - [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)目录
- 引言
- CTdManager类核心功能分析
- 测试数据模型与字段解析
- 测试数据在列表控件中的展示逻辑
- 测试数据导出功能实现
- 时间窗口(Time Window)配置管理
- 与其他管理器的协作关系
- 大数据量场景下的性能优化
引言
本文档深入分析了GeomativeStudio项目中测试数据管理模块的实现细节。重点阐述了CTdManager类如何管理测试数据的采集、存储和展示,详细解释了测试数据模型中各关键字段的含义及其计算公式,描述了数据在用户界面中的格式化展示逻辑,并提供了数据导出和时间窗口配置的实现机制。同时,文档还分析了测试数据管理器与设备管理器、IO管理器的协作关系,以及在处理大数据量时的性能优化策略。
CTdManager类核心功能分析
CTdManager类是测试数据管理的核心,负责协调测试数据的整个生命周期。该类通过ADO数据库连接(_ConnectionPtr)与后端数据库交互,使用m_tdLinkList链表在内存中管理所有测试数据对象。
核心功能包括:
- 数据展示:提供
ShowTdListByProject和ShowTdListByTz等方法,根据项目或测区句柄从数据库查询测试数据,并将其填充到CListCtrl控件中。查询语句会联查td、tz、cm等表,以获取完整的测试数据信息,包括测试名称、位置、设备序列号、装置类型、测量模式等,并通过cm表进行多语言标签转换。 - 数据获取:通过
GetTestingData方法,根据句柄从内存链表中快速检索CTestingData对象,实现高效的数据访问。 - 内存管理:在析构函数中遍历并删除链表中的所有
CTestingData对象,确保资源的正确释放。
classDiagram
class CTdManager {
+_ConnectionPtr m_pConnection
+CLinkList<CTestingData*> m_tdLinkList
+ShowTdListByProject(DWORD dwProHandle, CListCtrl& tdList)
+ShowTdListByTz(DWORD dwTzHandle, CListCtrl& tdList)
+GetTestingData(DWORD dwHandle) CTestingData*
}
class CTestingData {
+DWORD m_dwID
+CString m_szTdName
+int m_iSType
+int m_iTType
+float m_fESpace
+CString m_szEDistance
+ShowConListByPage(CListCtrl &tdConList, int iSType)
+SaveTdToExcelFile(CString f_szFileName)
+SaveTdToCsvFile(CString f_szFileName)
}
CTdManager --> CTestingData : "管理"
Diagram sources
Section sources
测试数据模型与字段解析
测试数据模型由CTestingData类定义,它封装了单次测试任务的所有元数据和测量结果。核心字段及其含义如下:
元数据字段:
m_szTdName/m_szTdCN: 测试任务的名称和编号。m_iSType: 测量类型,如2D、3D或1D(CE)。m_iTType: 数据类型,区分电阻率(Resistivity)、激电(IP)和自电位(SP)。m_iTMode: 测量模式,如常规、自电位等。m_iEAmount: 电极数量。m_iTPAmount: 测点数量。m_fESpace: 电极步长(单位:米)。m_szEDistance: 电极间距(字符串,可能包含单位)。m_iCLayout: 装置类型,如温纳(α)、偶极-偶极等,其值定义在TestingData.h中(如AR_WENNER_ALPHA = 1)。m_iTRWave: 供电波形类型,如"0+-0"、"+0-0"等。m_iTRFrequency: 供电频率。m_iIFrequency: 工频干扰频率(50Hz或60Hz)。m_iSAFrequency: 采样频率。m_fTemperature,m_fHumidity,m_fHeight: 环境参数(温度、湿度、海拔)。m_szCDate,m_szCTime,m_szTDate,m_szTTime: 创建和测试的日期与时间。
测量结果字段:
m_fI: 测量电流(单位:mA)。m_fV: 测量电压(单位:mV)。m_fR0: 视电阻率(单位:Ω·m),计算公式为R0 = (V / I) * K,其中K为装置系数。m_fSP: 自电位(单位:mV)。
计算公式:
- 视电阻率 (R0):
R0 = (ΔV / I) * KΔV: 电位差(电压)I: 供电电流K: 装置系数,由电极的几何排列决定。
- 自电位 (SP): 直接测量的电位值,单位为毫伏(mV)。
erDiagram
TEST_DATA {
string TDname
string Tlocation
int Stype
int Ttype
int Tmode
int Eamount
float Espace
string EDistance
int Clayout
float temperature
float humidity
float height
float R0
float SP
float I
float V
}
TEST_DATA ||--o{ TIME_WINDOW : "包含"
TEST_DATA ||--o{ RAW_DATA : "包含"
Diagram sources
Section sources
测试数据在列表控件中的展示逻辑
测试数据在列表控件(CListCtrl)中的展示主要通过CTestingData::ShowConListByPage方法实现,该方法支持分页加载,以应对大数据量场景。
展示逻辑流程:
- 分页查询:方法接收一个
g_ui32PageCount全局变量作为页码,结合ONE_PAGE_DATA_NUMBER常量(定义为100),构建SQL查询的LIMIT子句,实现分页。 - SQL查询:根据
iSType(测量类型)动态构建SQL语句,从td2dcon、td3dcon或td1dcon表中查询数据。查询结果包含原始测量值(I,V)和计算结果(R0,SP)。 - 数据格式化:
- 使用
CString::Format将浮点数转换为字符串,并指定小数位数(如%.4f)。 - 对于
R(电阻)字段,如果I为0,则显示为0,避免除零错误。 - 特殊值处理:如温度或湿度为
-9999时,视为空值不显示。
- 使用
- 单位转换:代码中直接使用测量值,单位转换(如将电压从mV转为V)通常在显示层或导出时处理。
- 异常值处理:在
LoadOrgData系列方法中,对原始数据进行处理。例如,在TdRecord.cpp中,会检查Vrawdata和Irawdata的长度,若为空则不进行后续处理。同时,通过SetMaxR0AndMinR0方法在加载数据时动态计算R0的最大值和最小值,用于后续的色彩映射。
flowchart TD
A[开始] --> B[接收页码和列表控件]
B --> C[构建分页SQL查询]
C --> D[执行数据库查询]
D --> E{查询结果为空?}
E --> |否| F[遍历每条记录]
E --> |是| G[结束]
F --> H[格式化数值为字符串]
H --> I[处理异常值 e.g., I=0]
I --> J[设置列表项文本]
J --> K[继续下一条]
K --> F
G --> L[结束]
Section sources
测试数据导出功能实现
系统提供了将测试数据导出为Excel、CSV等格式的功能,主要由CTestingData类中的方法实现。
导出功能分析:
- Excel导出:
SaveTdToExcelFile方法是虚函数,其具体实现位于excel.cpp。该文件使用MFC的COleDispatchDriver包装类(如_Application,_Workbook,_Worksheet)来自动化Excel应用程序。通过GetRange、SetItem等方法将数据写入工作表的指定单元格。 - CSV导出:
SaveTdToCsvFile方法同样是虚函数,其实现逻辑与Excel类似,但更简单,直接将数据按逗号分隔写入文本文件。 - 其他格式:还支持导出为Res2D、Res3D、ResCE等专业格式,以及TXT和URF格式。
- 调用流程:导出操作通常由
CDataOperator类触发。例如,在DataOperator.cpp中,ExportRspCETdToExcel方法会获取当前选中的测试数据句柄,然后调用CTdManager->GetTestingData(dwTdHandle)->SaveTdToExcelFile(f_szFileName)来执行导出。
sequenceDiagram
participant UI as 用户界面
participant DataOp as CDataOperator
participant TdManager as CTdManager
participant TestingData as CTestingData
participant Excel as Excel Application
UI->>DataOp : 触发导出操作
DataOp->>TdManager : GetTestingData(dwTdHandle)
TdManager-->>DataOp : 返回 CTestingData 对象
DataOp->>TestingData : SaveTdToExcelFile(f_szFileName)
TestingData->>Excel : 启动Excel并创建工作簿
loop 写入每一行数据
TestingData->>Excel : GetRange().SetItem()
end
Excel-->>TestingData : 完成
TestingData-->>DataOp : 导出成功/失败
DataOp-->>UI : 返回结果
Diagram sources
Section sources
时间窗口(Time Window)配置管理
时间窗口配置是激电测量中的关键环节,用于计算激电参数(如视极化率M和充电率η)。该功能由CTestingData类中的CalculateTWInfo和CalculateTimeWindows等方法实现。
管理机制:
- 数据结构:使用
_WaveCount、_WinTimeList和_WinTime结构体来存储复杂的时窗信息。_WaveCount包含两次放电的时窗数据,_WinTimeList包含多个时窗(最多10个)和Vp(充电电压)值,_WinTime则定义了单个时窗的起始时间、宽度、积分值、V2(时窗中点电压)等。 - 计算流程:
- 获取原始数据:从ORG文件或数据库中读取原始电压和电流数据。
- 多项式拟合:
CalculateTWInfo方法使用get_fit_equation函数对放电阶段的电压数据进行多项式拟合,以平滑噪声。 - 计算积分和平均值:使用
get_integral_area和get_fit_equation_value函数计算每个时窗内的电压积分(wintime_Integral)和中点电压(wintime_V2)。 - 计算激电参数:
- 视极化率 (M):
M = Integral / Vp - 充电率 (η):
η = (V2 / Vp) * 100%
- 视极化率 (M):
- 参数验证:在计算前会检查
Vp是否为0,若为0则弹出错误提示,防止除零错误。
Section sources
与其他管理器的协作关系
测试数据管理器(CTdManager)与设备管理器(CDevManager)和IO管理器(CIOManager)紧密协作,共同完成数据的采集、同步和导入导出。
协作关系分析:
-
与设备管理器(CDevManager)的协作:
- 数据采集:当从设备上载数据时,
CTdManager的Upload2DTdFromDev等方法会接收一个CDevice*指针,通过该指针与设备通信,获取原始数据文件(如ORG文件)。 - 设备信息:
CTestingData对象持有m_pDevice指针,可以直接访问设备的序列号、状态等信息。 - 依赖关系:
CTdManager依赖CDevManager来获取和管理CDevice对象。
- 数据采集:当从设备上载数据时,
-
与IO管理器(CIOManager)的协作:
- 数据导入导出:
CIOManager负责更高层次的批量导入导出操作。例如,ExportProjectToAccdbFile方法会调用CTdManager的相关功能来导出整个项目的测试数据。 - 职责分离:
CTdManager专注于单个测试数据的管理,而CIOManager则负责项目、测区等更大范围的数据迁移和格式转换。
- 数据导入导出:
classDiagram
class CTdManager {
+CDevManager* m_pDevManager
+CIOManager* m_pIOManager
}
class CDevManager {
+CLinkList<CDevice*> m_devLinkList
}
class CIOManager {
+ExportProjectToAccdbFile(...)
+ImportProjectToDB(...)
}
class CDevice {
+CString m_szDevSN
+ReceiveFile(...)
}
CTdManager ..> CDevManager : "依赖"
CTdManager ..> CIOManager : "协作"
CTdManager --> CDevice : "通过 m_pDevice"
CIOManager --> CTdManager : "调用导出功能"
Diagram sources
Section sources
大数据量场景下的性能优化
系统在处理大量测试数据时,采用了多种策略来优化性能:
- 分页加载:这是最核心的优化。
ShowConListByPage方法通过g_ui32PageCount和ONE_PAGE_DATA_NUMBER实现分页查询,避免一次性加载数万条记录导致界面卡顿或内存溢出。 - 内存缓存:
CTdManager使用m_tdLinkList在内存中缓存CTestingData对象。GetTestingData方法通过句柄直接访问,避免了重复的数据库查询,提高了数据访问速度。 - 预计算与缓存:在
CTdChannel::LoadRsp2DTdData等方法中,加载数据的同时调用SetMaxR0AndMinR0来预先计算R0的最大值和最小值。这个值被缓存(m_fMaxR0,m_fMinR0),用于后续的色彩映射,避免了每次渲染时都进行全量扫描。 - 高效的数据库操作:使用
_CommandPtr执行参数化SQL语句(adCmdText),比直接拼接字符串更安全高效。对于批量插入,虽然代码中是逐条插入,但可以通过事务(Transaction)来进一步优化性能。 - 延迟加载:测试数据的原始数据(
Vrawdata,Irawdata)和详细记录(TdRecord)并非在初始化CTestingData时就全部加载,而是在需要时(如查看原始数据曲线)才从数据库加载,减少了初始内存占用。
Section sources