# 测试数据管理
**本文档引用的文件**
- [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)