# 测试数据管理 **本文档引用的文件** - [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) ## 目录 1. [引言](#引言) 2. [CTdManager类核心功能分析](#ctdmanager类核心功能分析) 3. [测试数据模型与字段解析](#测试数据模型与字段解析) 4. [测试数据在列表控件中的展示逻辑](#测试数据在列表控件中的展示逻辑) 5. [测试数据导出功能实现](#测试数据导出功能实现) 6. [时间窗口(Time Window)配置管理](#时间窗口time-window配置管理) 7. [与其他管理器的协作关系](#与其他管理器的协作关系) 8. [大数据量场景下的性能优化](#大数据量场景下的性能优化) ## 引言 本文档深入分析了GeomativeStudio项目中测试数据管理模块的实现细节。重点阐述了CTdManager类如何管理测试数据的采集、存储和展示,详细解释了测试数据模型中各关键字段的含义及其计算公式,描述了数据在用户界面中的格式化展示逻辑,并提供了数据导出和时间窗口配置的实现机制。同时,文档还分析了测试数据管理器与设备管理器、IO管理器的协作关系,以及在处理大数据量时的性能优化策略。 ## CTdManager类核心功能分析 CTdManager类是测试数据管理的核心,负责协调测试数据的整个生命周期。该类通过ADO数据库连接(`_ConnectionPtr`)与后端数据库交互,使用`m_tdLinkList`链表在内存中管理所有测试数据对象。 **核心功能包括**: - **数据展示**:提供`ShowTdListByProject`和`ShowTdListByTz`等方法,根据项目或测区句柄从数据库查询测试数据,并将其填充到CListCtrl控件中。查询语句会联查`td`、`tz`、`cm`等表,以获取完整的测试数据信息,包括测试名称、位置、设备序列号、装置类型、测量模式等,并通过`cm`表进行多语言标签转换。 - **数据获取**:通过`GetTestingData`方法,根据句柄从内存链表中快速检索`CTestingData`对象,实现高效的数据访问。 - **内存管理**:在析构函数中遍历并删除链表中的所有`CTestingData`对象,确保资源的正确释放。 ```mermaid classDiagram class CTdManager { +_ConnectionPtr m_pConnection +CLinkList 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** - [TdManager.h](file://h/TdManager.h#L30-L106) - [TestingData.h](file://h/TestingData.h#L158-L273) **Section sources** - [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L57-L406) - [TdManager.h](file://h/TdManager.h#L30-L106) ## 测试数据模型与字段解析 测试数据模型由`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)。 ```mermaid 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** - [TestingData.h](file://h/TestingData.h#L178-L223) - [TdRecord.h](file://h/TdRecord.h#L21-L27) **Section sources** - [TestingData.h](file://h/TestingData.h#L178-L223) - [TdRecord.h](file://h/TdRecord.h#L21-L27) ## 测试数据在列表控件中的展示逻辑 测试数据在列表控件(CListCtrl)中的展示主要通过`CTestingData::ShowConListByPage`方法实现,该方法支持分页加载,以应对大数据量场景。 **展示逻辑流程**: 1. **分页查询**:方法接收一个`g_ui32PageCount`全局变量作为页码,结合`ONE_PAGE_DATA_NUMBER`常量(定义为100),构建SQL查询的`LIMIT`子句,实现分页。 2. **SQL查询**:根据`iSType`(测量类型)动态构建SQL语句,从`td2dcon`、`td3dcon`或`td1dcon`表中查询数据。查询结果包含原始测量值(`I`, `V`)和计算结果(`R0`, `SP`)。 3. **数据格式化**: - 使用`CString::Format`将浮点数转换为字符串,并指定小数位数(如`%.4f`)。 - 对于`R`(电阻)字段,如果`I`为0,则显示为0,避免除零错误。 - 特殊值处理:如温度或湿度为`-9999`时,视为空值不显示。 4. **单位转换**:代码中直接使用测量值,单位转换(如将电压从mV转为V)通常在显示层或导出时处理。 5. **异常值处理**:在`LoadOrgData`系列方法中,对原始数据进行处理。例如,在`TdRecord.cpp`中,会检查`Vrawdata`和`Irawdata`的长度,若为空则不进行后续处理。同时,通过`SetMaxR0AndMinR0`方法在加载数据时动态计算`R0`的最大值和最小值,用于后续的色彩映射。 ```mermaid 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** - [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L97-L252) - [TdRecord.cpp](file://cpp/ProblemZone/TdRecord.cpp#L34-L211) ## 测试数据导出功能实现 系统提供了将测试数据导出为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)`来执行导出。 ```mermaid 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** - [TestingData.h](file://h/TestingData.h#L230-L234) - [excel.h](file://h/excel.h#L7-L379) - [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L1807-L1834) **Section sources** - [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L270-L278) - [excel.cpp](file://cpp/Tools/excel.cpp#L1-L800) - [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L1807-L1834) ## 时间窗口(Time Window)配置管理 时间窗口配置是激电测量中的关键环节,用于计算激电参数(如视极化率M和充电率η)。该功能由`CTestingData`类中的`CalculateTWInfo`和`CalculateTimeWindows`等方法实现。 **管理机制**: - **数据结构**:使用`_WaveCount`、`_WinTimeList`和`_WinTime`结构体来存储复杂的时窗信息。`_WaveCount`包含两次放电的时窗数据,`_WinTimeList`包含多个时窗(最多10个)和`Vp`(充电电压)值,`_WinTime`则定义了单个时窗的起始时间、宽度、积分值、`V2`(时窗中点电压)等。 - **计算流程**: 1. **获取原始数据**:从ORG文件或数据库中读取原始电压和电流数据。 2. **多项式拟合**:`CalculateTWInfo`方法使用`get_fit_equation`函数对放电阶段的电压数据进行多项式拟合,以平滑噪声。 3. **计算积分和平均值**:使用`get_integral_area`和`get_fit_equation_value`函数计算每个时窗内的电压积分(`wintime_Integral`)和中点电压(`wintime_V2`)。 4. **计算激电参数**: - **视极化率 (M)**: `M = Integral / Vp` - **充电率 (η)**: `η = (V2 / Vp) * 100%` - **参数验证**:在计算前会检查`Vp`是否为0,若为0则弹出错误提示,防止除零错误。 **Section sources** - [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L463-L567) - [TestingData.h](file://h/TestingData.h#L12-L31) ## 与其他管理器的协作关系 测试数据管理器(CTdManager)与设备管理器(CDevManager)和IO管理器(CIOManager)紧密协作,共同完成数据的采集、同步和导入导出。 **协作关系分析**: - **与设备管理器(CDevManager)的协作**: - **数据采集**:当从设备上载数据时,`CTdManager`的`Upload2DTdFromDev`等方法会接收一个`CDevice*`指针,通过该指针与设备通信,获取原始数据文件(如ORG文件)。 - **设备信息**:`CTestingData`对象持有`m_pDevice`指针,可以直接访问设备的序列号、状态等信息。 - **依赖关系**:`CTdManager`依赖`CDevManager`来获取和管理`CDevice`对象。 - **与IO管理器(CIOManager)的协作**: - **数据导入导出**:`CIOManager`负责更高层次的批量导入导出操作。例如,`ExportProjectToAccdbFile`方法会调用`CTdManager`的相关功能来导出整个项目的测试数据。 - **职责分离**:`CTdManager`专注于单个测试数据的管理,而`CIOManager`则负责项目、测区等更大范围的数据迁移和格式转换。 ```mermaid classDiagram class CTdManager { +CDevManager* m_pDevManager +CIOManager* m_pIOManager } class CDevManager { +CLinkList m_devLinkList } class CIOManager { +ExportProjectToAccdbFile(...) +ImportProjectToDB(...) } class CDevice { +CString m_szDevSN +ReceiveFile(...) } CTdManager ..> CDevManager : "依赖" CTdManager ..> CIOManager : "协作" CTdManager --> CDevice : "通过 m_pDevice" CIOManager --> CTdManager : "调用导出功能" ``` **Diagram sources** - [TdManager.h](file://h/TdManager.h#L93) - [DevManager.h](file://h/DevManager.h#L16-L68) - [IOManager.h](file://h/IOManager.h#L15-L51) **Section sources** - [TdManager.h](file://h/TdManager.h#L93) - [DevManager.h](file://h/DevManager.h#L16-L68) - [IOManager.h](file://h/IOManager.h#L15-L51) ## 大数据量场景下的性能优化 系统在处理大量测试数据时,采用了多种策略来优化性能: 1. **分页加载**:这是最核心的优化。`ShowConListByPage`方法通过`g_ui32PageCount`和`ONE_PAGE_DATA_NUMBER`实现分页查询,避免一次性加载数万条记录导致界面卡顿或内存溢出。 2. **内存缓存**:`CTdManager`使用`m_tdLinkList`在内存中缓存`CTestingData`对象。`GetTestingData`方法通过句柄直接访问,避免了重复的数据库查询,提高了数据访问速度。 3. **预计算与缓存**:在`CTdChannel::LoadRsp2DTdData`等方法中,加载数据的同时调用`SetMaxR0AndMinR0`来预先计算`R0`的最大值和最小值。这个值被缓存(`m_fMaxR0`, `m_fMinR0`),用于后续的色彩映射,避免了每次渲染时都进行全量扫描。 4. **高效的数据库操作**:使用`_CommandPtr`执行参数化SQL语句(`adCmdText`),比直接拼接字符串更安全高效。对于批量插入,虽然代码中是逐条插入,但可以通过事务(Transaction)来进一步优化性能。 5. **延迟加载**:测试数据的原始数据(`Vrawdata`, `Irawdata`)和详细记录(`TdRecord`)并非在初始化`CTestingData`时就全部加载,而是在需要时(如查看原始数据曲线)才从数据库加载,减少了初始内存占用。 **Section sources** - [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L97-L252) - [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L81-L406) - [TdChannel.cpp](file://cpp/ProblemZone/TdChannel.cpp#L515-L584)