a
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
# 测试数据管理
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [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)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
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<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**
|
||||
- [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<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**
|
||||
- [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)
|
||||
Reference in New Issue
Block a user