a
This commit is contained in:
@@ -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)
|
||||
Reference in New Issue
Block a user