This commit is contained in:
coco
2026-07-03 16:05:30 +08:00
commit df489d5640
1101 changed files with 779140 additions and 0 deletions
@@ -0,0 +1,166 @@
# 数据导出
<cite>
**本文档引用的文件**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [excel.cpp](file://cpp/Tools/excel.cpp)
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [Rsp2DTd.cpp](file://cpp/ProblemZone/Rsp2DTd.cpp)
- [RspCETd.cpp](file://cpp/ProblemZone/RspCETd.cpp)
- [SP2DTd.cpp](file://cpp/ProblemZone/SP2DTd.cpp)
- [TdManager.h](file://h/TdManager.h)
- [IOManager.h](file://h/IOManager.h)
- [excel.h](file://h/excel.h)
- [OperTxtFile.h](file://h/OperTxtFile.h)
- [OperUrfFile.h](file://h/OperUrfFile.h)
- [ioexpdlg.cpp](file://cpp/Views/ioexpdlg.cpp)
- [ioexpdmsdlg.cpp](file://cpp/Views/ioexpdmsdlg.cpp)
- [ioexpsptdlg.cpp](file://cpp/Views/ioexpsptdlg.cpp)
- [ioexpdlg.h](file://h/ioexpdlg.h)
- [ioexpdmsdlg.h](file://h/ioexpdmsdlg.h)
- [ioexpsptdlg.h](file://h/ioexpsptdlg.h)
</cite>
## 目录
1. [引言](#引言)
2. [核心组件分析](#核心组件分析)
3. [数据导出格式与数据结构映射](#数据导出格式与数据结构映射)
4. [Excel导出功能实现](#excel导出功能实现)
5. [用户自定义导出选项处理](#用户自定义导出选项处理)
6. [导出过程中的进度反馈与错误处理](#导出过程中的进度反馈与错误处理)
7. [大文件生成的内存优化方案](#大文件生成的内存优化方案)
## 引言
本文档旨在全面文档化Geomative Studio软件中测试数据导出功能的实现。该功能主要由`CTdManager``CIOManager`两个核心管理类协同工作,支持将测试数据导出为Excel、CSV、TXT、URF等多种格式。文档将详细阐述其技术细节,包括不同格式的数据结构映射规则、用户自定义选项的处理逻辑、Excel导出中`excel.cpp`类库的使用流程,以及导出过程中的进度反馈、错误处理和内存优化策略。
## 核心组件分析
`CTdManager``CIOManager`是实现数据导出功能的两个核心类。
`CTdManager`类(位于`cpp/Managers/TdManager.cpp`)是测试数据的管理核心。它负责从数据库中获取测试数据,并提供将数据保存为特定文件格式的接口。例如,`CRsp2DTd``CRspCETd`等具体的数据类型类继承自`CTestingData`,并实现了`SaveTdToExcelFile``SaveTdToCsvFile`等方法,这些方法定义了如何将特定类型的数据组织并写入文件。
`CIOManager`类(位于`cpp/Managers/IOManager.cpp`)则负责更高层次的导出流程控制。其`Export`方法启动导出流程,创建一个导出对话框(`CIOExpDlg`),用户可以在其中选择要导出的项目、测区和具体的测试数据。`CIOManager`根据用户的选择,调用`CTdManager`提供的接口来执行实际的数据导出操作。
**Section sources**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [TdManager.h](file://h/TdManager.h)
- [IOManager.h](file://h/IOManager.h)
## 数据导出格式与数据结构映射
系统支持将测试数据导出为四种主要格式:Excel、CSV、TXT和URF。每种格式都有其特定的数据结构映射规则。
对于**Excel和CSV**格式,数据通常被组织成多个工作表或数据块。以`CRsp2DTd`类为例,其`SaveTdToExcelFile`方法会创建一个Excel工作簿,并包含三个工作表:
1. **Head (头部信息)**: 包含测试任务的元数据,如任务名称、位置、日期、设备信息等。
2. **DAT (数据信息)**: 包含核心的测量数据,如电极配置(A, B, M, N)、视电阻率(Ro)、电压(V)、电流(I)等。
3. **GR (接地电阻)**: 包含各电极的接地电阻测量值。
**TXT**格式的导出由`COperTxtFile`类(位于`cpp/Tools/OperTxtFile.cpp`)处理。该类提供了一个可配置的文本文件写入器,通过`SetParamWidth`方法设置每列的宽度,并使用`WriteFileContent`方法将字符串数组按固定宽度写入文件,确保数据在文本编辑器中对齐。
**URF**Universal Resistivity data File)是一种专用于电阻率数据的通用格式。其导出由`COperUrfFile`类(位于`cpp/Tools/OperUrfFile.cpp`)负责。URF文件的结构包括一个头部注释,然后是电极坐标信息,最后是测量数据。`COperUrfFile`类提供了针对不同电极阵列(如温纳装置、施伦贝谢装置、跨孔装置等)生成电极坐标的专用方法,如`WriteElecByWenSch``WriteElecByCrossHoleGeomative`,确保导出的URF文件符合特定的地质勘探软件要求。
**Section sources**
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp)
- [Rsp2DTd.cpp](file://cpp/ProblemZone/Rsp2DTd.cpp)
- [RspCETd.cpp](file://cpp/ProblemZone/RspCETd.cpp)
- [OperTxtFile.h](file://h/OperTxtFile.h)
- [OperUrfFile.h](file://h/OperUrfFile.h)
## Excel导出功能实现
Excel导出功能的核心是`excel.cpp``excel.h`文件。这两个文件是通过Visual C++的ClassWizard工具从Microsoft Excel的类型库生成的C++包装类,它们提供了对Excel应用程序对象模型的COM接口访问。
导出过程遵循以下操作流程:
1. **创建Excel应用实例**:
```cpp
_Application* pComApp = new _Application;
```
这行代码创建了一个Excel应用程序的COM对象实例。
2. **创建和获取工作簿与工作表**:
```cpp
Workbooks comBooks;
_Workbook comBook;
Sheets comSheets;
_Worksheet comSheet01;
```
通过`_Application`对象,可以获取`Workbooks`集合,进而创建一个新的工作簿(`comBook`),并从工作簿中获取`Sheets`集合来操作具体的工作表。
3. **创建工作表并命名**:
```cpp
comSheet01 = comSheets.GetItem(COleVariant((short)1));
comSheet01.SetName(_T("Head"));
```
使用`GetItem`方法获取第一个工作表,并使用`SetName`方法将其重命名为"Head"。
4. **写入数据**:
具体的数据写入逻辑由`CTestingData`的派生类(如`CRsp2DTd`)实现。这些类会调用`SaveTdHeadToExcelFile`等方法,通过遍历数据库记录集(`_RecordsetPtr`),并将数据逐行写入到`_Worksheet`对象的单元格中。
5. **应用样式和公式**:
虽然在提供的代码片段中未直接体现,但`_Worksheet`和`Range`对象提供了丰富的属性和方法来设置单元格格式(如字体、颜色、边框)和应用公式。例如,可以通过`GetRange`方法获取一个单元格区域,然后设置其`NumberFormat`属性来定义数字显示格式。
6. **保存并清理**:
```cpp
comBook.SaveAs(COleVariant(f_szFileName), covOptional, ...);
...
pComApp->Quit();
delete pComApp;
```
使用`SaveAs`方法将工作簿保存到指定路径。最后,必须显式调用`Quit`方法退出Excel应用,并释放所有COM对象指针,以避免内存泄漏。
**Section sources**
- [excel.cpp](file://cpp/Tools/excel.cpp)
- [excel.h](file://h/excel.h)
- [Rsp2DTd.cpp](file://cpp/ProblemZone/Rsp2DTd.cpp)
- [RspCETd.cpp](file://cpp/ProblemZone/RspCETd.cpp)
## 用户自定义导出选项处理
用户自定义导出选项主要通过导出对话框(`CIOExpDlg`)来处理。该对话框由`CIOManager`在`Export`方法中创建。
1. **字段选择**:
对话框中的树形控件(`CTreeCtrl`)允许用户通过复选框选择要导出的具体项目、测区和测试数据。`CIOManager`通过遍历树形控件,检查每个节点的选中状态,来确定最终需要导出的数据集。
2. **时间范围和单位系统**:
在提供的代码中,时间范围和单位系统的处理逻辑并未直接体现。这些选项很可能在`CTestingData`类的`SaveTdTo...File`方法内部实现。当从数据库查询数据时,会根据用户在UI中选择的时间范围构建SQL查询语句的`WHERE`子句。单位系统(如米/英尺)的转换则可能在数据写入文件之前,在内存中对数值进行换算。
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [ioexpdlg.cpp](file://cpp/Views/ioexpdlg.cpp)
- [ioexpdlg.h](file://h/ioexpdlg.h)
## 导出过程中的进度反馈与错误处理
### 进度反馈
在提供的代码中,导出过程是同步执行的,没有明确的进度条或百分比反馈机制。整个过程在用户点击“确定”后,直到完成或出错才会返回控制权。更完善的实现可能需要在`CIOManager`或`CTdManager`中引入后台线程,并通过Windows消息或回调函数向UI发送进度更新。
### 错误处理
系统采用了多层次的错误处理策略:
1. **文件操作错误**: 在打开或写入文件时,会检查返回值(如`fopen`是否返回`NULL`)。如果失败,会通过`AfxMessageBox`或`MessageBoxEx`向用户显示错误信息,包括错误代码(`GetLastError()`)。
2. **数据库操作错误**: 使用`try-catch`块捕获`_com_error`异常,当执行数据库查询或操作失败时,会弹出错误对话框。
3. **逻辑错误**: 在执行关键操作前进行参数验证。例如,`COperTxtFile::SetParamWidth`会检查输入的宽度是否在有效范围内(6-50),否则会提示错误。
4. **COM接口错误**: 在使用`excel.cpp`进行Excel操作时,虽然代码中没有显式捕获异常,但应假设`_Application`等对象的方法调用可能失败,需要进行返回值检查。
**Section sources**
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp)
- [Rsp2DTd.cpp](file://cpp/ProblemZone/Rsp2DTd.cpp)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
## 大文件生成的内存优化方案
对于大文件的生成,系统主要通过以下方式优化内存使用:
1. **流式写入 (Streaming)**: 所有文件导出操作都采用流式写入。无论是TXT、CSV还是URF文件,代码都是在打开文件后,一边从数据库读取记录,一边立即写入文件流(`fwrite`),然后立即处理下一条记录。这种方式避免了将整个数据集加载到内存中,从而将内存占用保持在较低水平。
2. **分块处理**: 数据库查询使用`_RecordsetPtr`,它本质上是一个游标,允许逐行遍历结果集,而不是一次性将所有数据加载到内存。
3. **及时释放资源**: 在操作完成后,代码会显式关闭文件句柄(`fclose`)、关闭数据库记录集(`Close()`)并释放COM对象(`ReleaseDispatch()`),确保资源被及时回收。
**Section sources**
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp)
- [Rsp2DTd.cpp](file://cpp/ProblemZone/Rsp2DTd.cpp)
@@ -0,0 +1,230 @@
# 数据展示与分析
<cite>
**本文档引用的文件**
- [appdatatdlistview.cpp](file://cpp/Views/appdatatdlistview.cpp)
- [appdatatdgrlistview.cpp](file://cpp/Views/appdatatdgrlistview.cpp)
- [appdatatdlistview.h](file://h/appdatatdlistview.h)
- [appdatatdgrlistview.h](file://h/appdatatdgrlistview.h)
- [appdataipsp2dtdview.cpp](file://cpp/Views/appdataipsp2dtdview.cpp)
- [appdatarsp2dtdview.cpp](file://cpp/Views/appdatarsp2dtdview.cpp)
- [appdatarspcetdview.cpp](file://cpp/Views/appdatarspcetdview.cpp)
- [DataMngStruct.h](file://h/DataMngStruct.h)
</cite>
## 目录
1. [项目结构](#项目结构)
2. [核心组件](#核心组件)
3. [架构概述](#架构概述)
4. [详细组件分析](#详细组件分析)
5. [依赖分析](#依赖分析)
## 项目结构
Geomative Studio项目是一个地质勘探数据处理软件,其核心功能包括测试数据的展示与分析。项目结构清晰地分为多个模块,其中与数据展示直接相关的文件主要位于`cpp/Views``h`目录下。关键的测试数据展示组件包括列表视图(appdatatdlistview)和图形化视图(appdatatdgrlistview),这些组件负责渲染测试数据、处理用户交互以及实现数据可视化。
```mermaid
graph TB
subgraph "视图层"
A[appdatatdlistview] --> |继承| B[CListView]
C[appdatatdgrlistview] --> |继承| B
D[appdataipsp2dtdview] --> |继承| E[CView]
F[appdatarsp2dtdview] --> |继承| E
G[appdatarspcetdview] --> |继承| E
end
subgraph "数据管理"
H[DataMngStruct]
end
A --> H
C --> H
D --> A
D --> C
F --> A
F --> C
G --> A
C --> G
```
**图表来源**
- [appdatatdlistview.h](file://h/appdatatdlistview.h#L16)
- [appdatatdgrlistview.h](file://h/appdatatdgrlistview.h#L16)
- [appdataipsp2dtdview.cpp](file://cpp/Views/appdataipsp2dtdview.cpp#L23)
- [appdatarsp2dtdview.cpp](file://cpp/Views/appdatarsp2dtdview.cpp#L22)
- [appdatarspcetdview.cpp](file://cpp/Views/appdatarspcetdview.cpp#L24)
- [DataMngStruct.h](file://h/DataMngStruct.h#L14)
**章节来源**
- [appdatatdlistview.h](file://h/appdatatdlistview.h#L1-L68)
- [appdatatdgrlistview.h](file://h/appdatatdgrlistview.h#L1-L63)
## 核心组件
测试数据展示功能的核心组件包括`CAppDataTdListView``CAppDataTdGrListView`,分别负责以列表和图形化方式展示测试数据。`CAppDataTdListView`提供了数据的表格化展示,支持列排序、批量导出和删除等操作。`CAppDataTdGrListView`则通过自定义绘制实现了数据的颜色编码,能够根据测量状态(如短路、开路、大电阻等)以不同颜色显示数据项,便于用户快速识别异常情况。
**章节来源**
- [appdatatdlistview.cpp](file://cpp/Views/appdatatdlistview.cpp#L24-L485)
- [appdatatdgrlistview.cpp](file://cpp/Views/appdatatdgrlistview.cpp#L23-L189)
## 架构概述
系统的数据展示架构采用MVC模式,视图层由多个继承自MFC框架的视图类组成。`CAppDataTdListView``CAppDataTdGrListView`作为具体的视图实现,通过消息映射机制响应用户交互事件。不同测量模式(如2D、3D、CE)的数据展示通过专门的视图类(如`CAppDataIpsp2DTdView``CAppDataRsp2DTdView``CAppDataRspCETdView`)来实现,这些视图类通过分割窗口将详细信息、内容列表和图形化视图组织在一起,形成统一的用户界面。
```mermaid
classDiagram
class CAppDataTdListView {
+OnInitialUpdate()
+OnColumnclick()
+OnDblclk()
+OnBatchexport()
+OnBatchDelData()
}
class CAppDataTdGrListView {
+OnInitialUpdate()
+OnColumnclick()
+OnCustomDrawList()
}
class CAppDataIpsp2DTdView {
+Create()
+OnSize()
}
class CAppDataRsp2DTdView {
+Create()
+OnSize()
}
class CAppDataRspCETdView {
+Create()
+OnSize()
}
CAppDataTdListView <|-- CAppDataIpsp2DTdView
CAppDataTdListView <|-- CAppDataRsp2DTdView
CAppDataTdListView <|-- CAppDataRspCETdView
CAppDataTdGrListView <|-- CAppDataIpsp2DTdView
CAppDataTdGrListView <|-- CAppDataRsp2DTdView
CAppDataTdGrListView <|-- CAppDataRspCETdView
```
**图表来源**
- [appdatatdlistview.cpp](file://cpp/Views/appdatatdlistview.cpp#L24-L485)
- [appdatatdgrlistview.cpp](file://cpp/Views/appdatatdgrlistview.cpp#L23-L189)
- [appdataipsp2dtdview.cpp](file://cpp/Views/appdataipsp2dtdview.cpp#L23-L117)
- [appdatarsp2dtdview.cpp](file://cpp/Views/appdatarsp2dtdview.cpp#L22-L118)
- [appdatarspcetdview.cpp](file://cpp/Views/appdatarspcetdview.cpp#L24-L134)
## 详细组件分析
### 列表视图分析
`CAppDataTdListView`组件实现了测试数据的列表化展示,通过`OnInitialUpdate`方法初始化列标题,支持用户通过点击列标题进行排序。该组件还实现了批量导出和删除功能,通过进度条和状态提示为用户提供操作反馈。
```mermaid
flowchart TD
Start([初始化视图]) --> InsertColumns["插入列标题"]
InsertColumns --> SetExtendedStyle["设置扩展样式"]
SetExtendedStyle --> EnableSorting["启用列排序"]
EnableSorting --> EnableSelection["启用选择功能"]
EnableSelection --> End([视图准备就绪])
```
**图表来源**
- [appdatatdlistview.cpp](file://cpp/Views/appdatatdlistview.cpp#L80-L271)
**章节来源**
- [appdatatdlistview.cpp](file://cpp/Views/appdatatdlistview.cpp#L1-L485)
### 图形化视图分析
`CAppDataTdGrListView`组件通过`OnCustomDrawList`方法实现了数据项的自定义绘制,根据测量状态应用不同的文本颜色。短路和开路状态显示为红色,大电阻状态显示为蓝色,正常状态显示为黑色,这种颜色编码策略有助于用户快速识别异常测量值。
```mermaid
flowchart TD
Start([自定义绘制]) --> CheckStage["检查绘制阶段"]
CheckStage --> PrePaint{"预绘制阶段?"}
PrePaint --> |是| NotifyItemDraw["通知项目绘制"]
PrePaint --> |否| ItemPrePaint{"项目预绘制?"}
ItemPrePaint --> |是| NotifySubItemDraw["通知子项目绘制"]
ItemPrePaint --> |否| SubItemDraw{"子项目绘制?"}
SubItemDraw --> |是| GetStatus["获取状态文本"]
GetStatus --> CheckStatus{"状态为短路/开路?"}
CheckStatus --> |是| SetRed["设置红色文本"]
CheckStatus --> |否| CheckLargeRes{"状态为大电阻?"}
CheckLargeRes --> |是| SetBlue["设置蓝色文本"]
CheckLargeRes --> |否| SetBlack["设置黑色文本"]
SetRed --> End
SetBlue --> End
SetBlack --> End
```
**图表来源**
- [appdatatdgrlistview.cpp](file://cpp/Views/appdatatdgrlistview.cpp#L145-L188)
**章节来源**
- [appdatatdgrlistview.cpp](file://cpp/Views/appdatatdgrlistview.cpp#L1-L189)
### 测量模式视图分析
不同测量模式的视图类(如`CAppDataIpsp2DTdView``CAppDataRsp2DTdView``CAppDataRspCETdView`)通过创建分割窗口来组织界面布局。每个视图包含三个主要部分:详细信息面板、内容列表和图形化视图,这种一致的布局设计为用户提供了统一的操作体验。
```mermaid
sequenceDiagram
participant View as CAppDataIpsp2DTdView
participant Splitter1 as m_firstSplitter
participant Splitter2 as m_secondSplitter
participant Detail as CAppDataTdDetailListView
participant Content as CAppDataIpsp2DTdConListView
participant Graph as CAppDataTdGrListView
View->>View : Create()
View->>Splitter1 : CreateStatic(1,2)
Splitter1->>Splitter1 : CreateView(详细信息)
Splitter1->>Splitter2 : CreateStatic(2,1)
Splitter2->>Splitter2 : CreateView(内容列表)
Splitter2->>Splitter2 : CreateView(图形化视图)
Splitter2->>Splitter2 : RecalcLayout()
Splitter1->>Splitter1 : RecalcLayout()
```
**图表来源**
- [appdataipsp2dtdview.cpp](file://cpp/Views/appdataipsp2dtdview.cpp#L69-L102)
- [appdatarsp2dtdview.cpp](file://cpp/Views/appdatarsp2dtdview.cpp#L68-L103)
- [appdatarspcetdview.cpp](file://cpp/Views/appdatarspcetdview.cpp#L67-L117)
**章节来源**
- [appdataipsp2dtdview.cpp](file://cpp/Views/appdataipsp2dtdview.cpp#L1-L117)
- [appdatarsp2dtdview.cpp](file://cpp/Views/appdatarsp2dtdview.cpp#L1-L118)
- [appdatarspcetdview.cpp](file://cpp/Views/appdatarspcetdview.cpp#L1-L134)
## 依赖分析
测试数据展示组件依赖于MFC框架的`CListView``CView`基类,通过继承和重写虚函数来实现特定功能。这些组件还依赖于`DataMngStruct`类来获取和管理测试数据,形成了清晰的依赖关系。不同测量模式的视图类共享相同的列表和图形化视图组件,体现了代码的复用性。
```mermaid
graph TD
A[CAppDataTdListView] --> B[CListView]
C[CAppDataTdGrListView] --> B
D[CAppDataIpsp2DTdView] --> E[CView]
F[CAppDataRsp2DTdView] --> E
G[CAppDataRspCETdView] --> E
A --> H[DataMngStruct]
C --> H
D --> A
D --> C
F --> A
F --> C
G --> A
G --> C
```
**图表来源**
- [appdatatdlistview.h](file://h/appdatatdlistview.h#L16)
- [appdatatdgrlistview.h](file://h/appdatatdgrlistview.h#L16)
- [appdataipsp2dtdview.cpp](file://cpp/Views/appdataipsp2dtdview.cpp#L23)
- [appdatarsp2dtdview.cpp](file://cpp/Views/appdatarsp2dtdview.cpp#L22)
- [appdatarspcetdview.cpp](file://cpp/Views/appdatarspcetdview.cpp#L24)
- [DataMngStruct.h](file://h/DataMngStruct.h#L14)
**章节来源**
- [appdatatdlistview.cpp](file://cpp/Views/appdatatdlistview.cpp#L1-L485)
- [appdatatdgrlistview.cpp](file://cpp/Views/appdatatdgrlistview.cpp#L1-L189)
- [appdataipsp2dtdview.cpp](file://cpp/Views/appdataipsp2dtdview.cpp#L1-L117)
- [appdatarsp2dtdview.cpp](file://cpp/Views/appdatarsp2dtdview.cpp#L1-L118)
- [appdatarspcetdview.cpp](file://cpp/Views/appdatarspcetdview.cpp#L1-L134)
- [DataMngStruct.h](file://h/DataMngStruct.h#L1-L23)
@@ -0,0 +1,271 @@
# 数据采集与存储
<cite>
**本文档引用的文件**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [TdManager.h](file://h/TdManager.h)
- [TestingData.h](file://h/TestingData.h)
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
- [DevManager.h](file://h/DevManager.h)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp)
- [TdRecord.cpp](file://cpp/ProblemZone/TdRecord.cpp)
</cite>
## 目录
1. [引言](#引言)
2. [数据采集机制](#数据采集机制)
3. [数据存储结构](#数据存储结构)
4. [时间戳同步与采样控制](#时间戳同步与采样控制)
5. [异常数据过滤与完整性校验](#异常数据过滤与完整性校验)
6. [缓存机制与内存管理](#缓存机制与内存管理)
7. [断点续传与数据库交互](#断点续传与数据库交互)
8. [结论](#结论)
## 引言
本文档深入分析Geomative Studio软件中测试数据采集与存储机制的实现细节。系统通过CTdManager类协调设备管理器,实现对地质勘探设备的实时数据采集,包括电阻率、电流、电压、自电位等关键物理量。文档详细阐述了数据存储结构的设计原理、时间同步机制、异常数据处理策略以及与数据库的交互方式,为系统维护和功能扩展提供技术参考。
## 数据采集机制
CTdManager类作为数据采集的核心控制器,通过设备管理器获取实时测量数据。该类继承自CObject,负责管理测试数据的生命周期和采集流程。系统通过CTdManager的Upload2DTdFromDev等方法从设备上载2D数据,这些方法接收工程编号、测区编号、测试数据编号和设备指针作为参数,实现数据的远程采集。
数据采集过程中,CTdManager通过CDevice类与物理设备进行通信。CDevice类封装了设备的所有属性和操作方法,包括设备序列号(m_szDevSN)、设备名称(m_szDevName)、硬件版本(m_szHWV)和软件版本(m_szSWV)等。设备状态通过m_uState成员变量维护,支持离线(PZ_STATE_OFFLINE)、在线(PZ_STATE_ONLINE)等多种状态。
采集的数据类型由EN_DATA_TYPE枚举定义,包括电阻率测试(EN_RES_TEST_TYPE)、激电测试(EN_IP_TEST_TYPE)和自电位测试(EN_SP_TEST_TYPE)三种。系统通过不同的数据通道(tdchannel)管理不同类型的数据采集任务,确保数据的分类存储和高效处理。
**Section sources**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L57-L6839)
- [TdManager.h](file://h/TdManager.h#L16-L21)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L43-L83)
## 数据存储结构
### TestingData类设计
TestingData类是数据存储的核心数据结构,采用面向对象的设计模式,封装了测试数据的所有属性和操作方法。该类通过成员变量定义了丰富的数据字段,涵盖了测试任务的各个方面。
**核心字段定义:**
- **标识信息**m_dwID(数据ID)、m_szTdName(测试名称)、m_szTLocation(测试位置)
- **配置参数**m_iSType(装置类型)、m_iTType(测试类型)、m_iTMode(测试模式)
- **电极参数**m_iEAmount(电极数量)、m_fESpace(电极步长)、m_szEDistance(电极间距)
- **环境参数**m_iWeather(天气)、m_fTemperature(温度)、m_fHumidity(湿度)
- **时间信息**m_szCDate(创建日期)、m_szCTime(创建时间)、m_szTDate(测试日期)、m_szTTime(测试时间)
```mermaid
classDiagram
class CTestingData {
+DWORD m_dwID
+CString m_szTdName
+CString m_szTLocation
+int m_iSType
+int m_iTType
+int m_iEAmount
+float m_fESpace
+CString m_szEDistance
+int m_iWeather
+float m_fTemperature
+float m_fHumidity
+CString m_szCDate
+CString m_szCTime
+_WaveCount *m_waveCount
+bool CalculateTWInfo(CStringArray*, int)
+bool CalculateTimeWindows(struct _WinTimeList, CStringArray*, int, int, int, int, int)
+double adc_calculate(double, double, double)
+double adc_average(int*, int)
+double adc_integral(int*, int)
}
class _WaveCount {
+int WaveLength
+_WinTimeList windowList[2]
}
class _WinTimeList {
+int ListLength
+double wintime_Vp
+_WinTime timeWinList[10]
}
class _WinTime {
+int wintime_StartTime
+int wintime_width
+double wintime_V2
+double wintime_Integral
+double wintime_ETA
+double wintime_M
}
CTestingData --> _WaveCount : "包含"
_WaveCount --> _WinTimeList : "包含"
_WinTimeList --> _WinTime : "包含"
```
**Diagram sources**
- [TestingData.h](file://h/TestingData.h#L12-L31)
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L251-L273)
### 数据库表结构
系统采用关系型数据库存储测试数据,主要表结构包括:
- **td表**:存储测试任务基本信息,包含ID、TDname、Tlocation、DESN、SCCN等字段
- **tdchannel表**:存储数据通道信息,与td表通过TDID关联
- **td2dcon表**:存储2D测试数据,包含TSN、C1、C2、P1、P2、K、I、V、R0、SP等测量值
- **td1dcon表**:存储1D测试数据,结构与td2dcon类似
- **gr表**:存储接地电阻数据,包含TDID、Ecode、Mdate、Mtime、OMvalue等字段
数据存储采用分页机制,通过ONE_PAGE_DATA_NUMBER常量定义每页数据量为100条,提高大数据量下的查询效率。
**Section sources**
- [TestingData.h](file://h/TestingData.h#L176-L224)
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L29-L77)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L121-L144)
## 时间戳同步与采样控制
### 时间戳同步机制
系统通过m_szCDate和m_szCTime字段记录数据创建的时间戳,确保数据的时间一致性。时间戳采用"YYYY-MM-DD"和"HH:MM:SS"格式存储,便于数据库查询和数据分析。在数据采集过程中,系统通过Tm2LocalStr等函数将时间戳转换为本地时间格式,保证跨时区操作的一致性。
```mermaid
sequenceDiagram
participant 设备 as 地质勘探设备
participant CTdManager as CTdManager
participant 数据库 as 数据库
设备->>CTdManager : 发送测量数据包
CTdManager->>CTdManager : 解析数据包,提取时间戳
CTdManager->>CTdManager : 调用Tm2LocalStr转换为本地时间
CTdManager->>数据库 : 插入数据记录,包含时间戳
数据库-->>CTdManager : 返回插入结果
CTdManager-->>设备 : 确认数据接收
```
**Diagram sources**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L50-L51)
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L214-L217)
### 采样频率控制
采样频率由m_iIFrequency和m_iSAFrequency字段控制,分别表示工业频率和采样频率。系统通过GetSample方法根据工业频率和采样类型计算实际采样率:
```mermaid
flowchart TD
Start([开始]) --> CheckIndustrialFreq["检查工业频率"]
CheckIndustrialFreq --> |50Hz| SetSampleRate50["设置采样率: 30/60/120"]
CheckIndustrialFreq --> |60Hz| SetSampleRate60["设置采样率: 36/72/144"]
SetSampleRate50 --> ApplySampling["应用采样率"]
SetSampleRate60 --> ApplySampling
ApplySampling --> End([结束])
```
采样控制算法通过波形类型(m_iTRWave)和周期(f_Tcycle)计算每段波形的数据总量,确保采样过程的精确性和一致性。系统支持多种波形类型,通过GetWaveNum方法返回对应的波形段数。
**Section sources**
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L697-L724)
- [TestingData.h](file://h/TestingData.h#L118-L138)
## 异常数据过滤与完整性校验
### 异常数据过滤算法
系统采用多层过滤机制处理异常数据。首先在数据采集阶段,通过设备状态检查过滤无效数据;其次在数据存储阶段,通过数据库约束确保数据完整性;最后在数据显示阶段,通过条件判断过滤异常值。
对于温度和湿度等环境参数,系统采用-9999作为无效值标记。在数据显示时,如果检测到该值,则不显示任何内容:
```cpp
if (szDefault == "-9999")//若为该值则不显示东西
{
szDefault = "";
}
```
### 数据完整性校验
数据完整性校验通过以下机制实现:
1. **数据库约束**:使用NOT NULL约束确保关键字段不为空
2. **事务处理**:使用BeginTrans和CommitTrans确保数据操作的原子性
3. **外键关联**:通过ID字段建立表间关联,维护数据一致性
4. **日志记录**:通过m_pFile记录数据操作日志,便于问题追踪
在数据导入过程中,系统使用事务确保数据完整性。如果操作失败,则回滚所有更改,防止数据不一致:
```cpp
try
{
m_pConnection->BeginTrans();
// 执行数据操作
m_pConnection->CommitTrans();
}
catch (_com_error e)
{
m_pConnection->RollbackTrans();
return FALSE;
}
```
**Section sources**
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L305-L308)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L224-L277)
## 缓存机制与内存管理
### 数据缓存机制
系统采用多级缓存机制优化数据访问性能。CTdManager类通过m_tdLinkList链表缓存测试数据对象,避免频繁的数据库查询。链表采用句柄机制管理对象,通过GenerateHandle方法生成唯一句柄:
```mermaid
classDiagram
class CLinkList {
+Add(DWORD, CTestingData*)
+Get(DWORD)
+Delete(DWORD)
+Find(int)
}
class CTdManager {
+CLinkList<CTestingData*> m_tdLinkList
+CHandleProcessor m_handleProcessor
}
CTdManager --> CLinkList : "包含"
```
**Diagram sources**
- [TdManager.h](file://h/TdManager.h#L96-L97)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L61-L62)
### 内存管理策略
内存管理采用智能指针和RAII模式,确保资源的正确释放。在CTestingData类的析构函数中,系统释放动态分配的m_waveCount内存:
```cpp
CTestingData::~CTestingData()
{
delete m_waveCount;
m_waveCount = NULL;
}
```
系统通过CreateWindowsTime和FreeWindowsTime方法管理时窗数据的内存分配和释放,避免内存泄漏。在长时间连续采集场景下,系统定期清理过期数据,保持内存使用效率。
**Section sources**
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L81-L85)
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L765-L770)
## 断点续传与数据库交互
### 断点续传功能
断点续传功能通过记录数据采集进度实现。系统使用g_ui32PageCount全局变量跟踪当前页码,在ShowConListByPage方法中根据页码查询数据:
```cpp
szSql.Format(_T("select TSN,a,b,x,y,N,K,I,V,R0,SP,bUse from td1dcon where TCHID in (select ID from tdchannel where TDID = %u and TSN>%u and TSN<=%u order by TCHID) order by TSN"), m_dwID, g_ui32PageCount*ONE_PAGE_DATA_NUMBER, (g_ui32PageCount + 1)*ONE_PAGE_DATA_NUMBER);
```
当数据采集中断后,系统可以从上次的页码继续采集,避免重复工作。
### 数据库交互方式
系统通过ADO技术与数据库交互,使用_RecordsetPtr和_CommandPtr指针执行SQL操作。数据导入采用参数化查询,防止SQL注入:
```cpp
pCmdUpd->Parameters->Append(pCmdUpd->CreateParameter("Vrawdata", adBSTR, adParamInput, szSql.GetLength(), _variant_t(szVRawData.AllocSysString())));
```
数据导出支持多种格式,包括Excel、CSV、Res2D等,通过SaveTdToExcelFile、SaveTdToCsvFile等方法实现:
```cpp
virtual BOOL SaveTdToExcelFile(CString f_szFileName); // 保存数据为Excel文件
virtual BOOL SaveTdToCsvFile(CString f_szFileName); // 保存数据为Csv文件
virtual BOOL SaveTdToRes2DFile(CString f_szFileName); // 保存数据为Res2D文件
```
**Section sources**
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L97-L253)
- [TestingData.h](file://h/TestingData.h#L230-L234)
## 结论
Geomative Studio的数据采集与存储系统采用模块化设计,通过CTdManager类协调设备管理、数据采集和存储操作。系统具有完善的异常处理机制和数据完整性校验,确保数据的准确性和可靠性。多级缓存和内存管理策略优化了系统性能,特别适合长时间连续采集场景。断点续传功能提高了数据采集的容错能力,而灵活的数据库交互方式支持多种数据格式的导入导出。整体架构设计合理,为地质勘探数据的高效管理和分析提供了坚实基础。
@@ -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)