# 2D脚本生成
**本文档引用文件**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
- [Script.cpp](file://cpp/ProblemZone/Script.cpp)
- [Script2D.cpp](file://cpp/ProblemZone/Script2D.cpp)
- [MediumA.cpp](file://cpp/ProblemZone/MediumA.cpp)
- [MediumW.cpp](file://cpp/ProblemZone/MediumW.cpp)
- [MediumBasicWenAndSch.cpp](file://cpp/ProblemZone/MediumBasicWenAndSch.cpp)
- [MediumStrongWenAndSch.cpp](file://cpp/ProblemZone/MediumStrongWenAndSch.cpp)
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp)
- [DialCustomSptInput.cpp](file://cpp/Operator/DialCustomSptInput.cpp)
- [Script.h](file://h/Script.h)
- [Script2D.h](file://h/Script2D.h)
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概述](#架构概述)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 引言
本文档详细阐述了Geomative Studio软件中2D测量脚本的生成机制。重点分析了`CSptManager::Create2DSConInDB`和`CScript`类在脚本创建过程中的协作,描述了从MediumA到MediumW等2D介质模型的电极排列算法和测量序列生成逻辑。文档还说明了脚本参数配置界面(如DialNew2DTask和OpCreateSptDlg)如何收集用户输入并生成XML格式的脚本结构,提供了从项目创建到脚本导出的完整流程,并分析了2D脚本与测试数据管理器的集成方式。
## 项目结构
Geomative Studio项目是一个用于地球物理测量的软件系统,其核心功能围绕测量脚本的创建、管理和执行。项目结构清晰地分离了管理层、操作层和问题区域(ProblemZone)的代码。
```mermaid
graph TD
subgraph "管理层"
SptManager["SptManager.cpp
脚本管理"]
ProManager["ProManager.cpp
项目管理"]
TdManager["TdManager.cpp
测试数据管理"]
end
subgraph "操作层"
DialNew2DTask["DialNew2DTask.cpp
2D任务创建对话框"]
DialCustomSptInput["DialCustomSptInput.cpp
自定义脚本输入"]
end
subgraph "问题区域"
Script["Script.cpp
脚本基类"]
Script2D["Script2D.cpp
2D脚本实现"]
MediumA["MediumA.cpp
温纳装置模型"]
MediumW["MediumW.cpp
偶极-偶极装置模型"]
MediumBasicWenAndSch["MediumBasicWenAndSch.cpp
施伦贝谢基础模型"]
MediumStrongWenAndSch["MediumStrongWenAndSch.cpp
施伦贝谢强模型"]
end
SptManager --> Script2D
SptManager --> MediumA
SptManager --> MediumW
DialNew2DTask --> SptManager
DialCustomSptInput --> SptManager
```
**图源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp)
- [Script2D.cpp](file://cpp/ProblemZone/Script2D.cpp)
- [MediumA.cpp](file://cpp/ProblemZone/MediumA.cpp)
- [MediumW.cpp](file://cpp/ProblemZone/MediumW.cpp)
**本节源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp)
## 核心组件
2D脚本生成的核心组件包括`CSptManager`、`CScript2D`和各种`CMedium`派生类。`CSptManager`负责协调脚本的创建流程,`CScript2D`作为2D脚本的数据容器,而`CMedium`系列类则封装了不同测量装置的电极排列算法。
**本节源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
- [Script2D.cpp](file://cpp/ProblemZone/Script2D.cpp)
- [MediumA.cpp](file://cpp/ProblemZone/MediumA.cpp)
## 架构概述
2D脚本生成的架构遵循典型的MVC(模型-视图-控制器)模式。用户通过视图(如`DialNew2DTask`)输入参数,控制器(`CSptManager`)接收请求并协调模型(`CScript2D`和`CMedium`)进行处理,最终将结果持久化到数据库。
```mermaid
sequenceDiagram
participant User as "用户"
participant View as "DialNew2DTask"
participant Controller as "CSptManager"
participant Model as "CScript2D / CMedium"
participant DB as "数据库"
User->>View : 输入参数电极数、测量类型等
View->>Controller : 调用Create2DSConInDB
Controller->>Model : 创建CScript2D实例
Controller->>Model : 调用介质模型的GenerateSptRecElecVal
Model-->>Controller : 返回生成的测量序列
Controller->>DB : 将脚本数据写入scon、channel、script2d表
DB-->>Controller : 确认写入成功
Controller-->>View : 返回成功状态
View-->>User : 显示创建成功消息
```
**图源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp#L257-L486)
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp#L414-L664)
- [Script2D.cpp](file://cpp/ProblemZone/Script2D.cpp)
## 详细组件分析
### CSptManager与CScript的协作机制
`CSptManager::Create2DSConInDB`是创建2D脚本的核心方法。它首先创建一个`COpCreateSptDlg`对话框来收集用户输入,然后根据输入创建一个`CScript2D`对象。该方法与`CScript`类的协作体现在`CScript2D`作为`CScript`的派生类,继承了基本的脚本属性和方法。
```mermaid
classDiagram
class CScript {
+DWORD m_dwID
+int m_iEAmount
+int m_iSType
+int m_iAR
+_ConnectionPtr m_pConnection
+CScript(DWORD dwID, _ConnectionPtr& pConnection)
+virtual ~CScript()
}
class CScript2D {
+CPtrList m_chaList
+bool ShowSptConInfo(CListCtrl& sptConList)
+bool ShowSptDetailInfo(CListCtrl& sptDetailList)
+bool ShowChannelList(CListCtrl& sptChannelList)
+void AdjustRecListColumn(int iAR, CListCtrl& sptConListInfo)
+CScript2D(DWORD dwID, _ConnectionPtr& pConnection)
+virtual ~CScript2D()
}
class CSptManager {
+UINT Create2DSConInDB(DWORD& dwSConID)
+void Delete2DSConInDB(DWORD dwSConID)
+CScript* GetScript(DWORD dwHandle)
+void DeleteObjInMem(DWORD dwHandle)
}
CScript2D --|> CScript : 继承
CSptManager --> CScript2D : 创建实例
CSptManager --> COpCreateSptDlg : 显示对话框
```
**图源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp#L257-L486)
- [Script.cpp](file://cpp/ProblemZone/Script.cpp)
- [Script2D.cpp](file://cpp/ProblemZone/Script2D.cpp)
- [Script.h](file://h/Script.h)
- [Script2D.h](file://h/Script2D.h)
**本节源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp#L257-L486)
- [Script.cpp](file://cpp/ProblemZone/Script.cpp)
- [Script2D.cpp](file://cpp/ProblemZone/Script2D.cpp)
### 2D介质模型的电极排列算法
不同的2D介质模型(如MediumA、MediumW)实现了各自的`GenerateSptRecElecVal`方法来生成特定的测量序列。
#### MediumA(温纳装置)算法
`CMediumA`类实现了温纳装置的电极排列算法。其核心逻辑是根据电极总数计算最大层数,并生成相应的测量序列。
```mermaid
flowchart TD
Start([开始]) --> CheckInput["验证输入参数"]
CheckInput --> CalcMaxSpace["计算最大间距 iMaxSpace = (iEAmount-1)/3"]
CalcMaxSpace --> LoopLayer["循环每一层 iMMVal"]
LoopLayer --> CalcPositions["计算A, B, M, N电极位置"]
CalcPositions --> CreateRecord["创建CSptRecord并设置参数"]
CreateRecord --> AddToArray["将记录添加到pSptRecArray"]
AddToArray --> CalcK["计算K值: fK = 2*π*(iN-iM)"]
CalcK --> CalcLevel["计算层数: iN-iM"]
CalcLevel --> InnerLoop["内部循环: 电极向右平移"]
InnerLoop --> UpdatePositions["更新A, B, M, N位置"]
UpdatePositions --> CreateInnerRecord["创建新的CSptRecord"]
CreateInnerRecord --> AddInnerRecord["添加到pSptRecArray"]
AddInnerRecord --> CheckEnd["检查是否到达电极末端"]
CheckEnd --> |否| UpdatePositions
CheckEnd --> |是| NextLayer["进入下一层"]
NextLayer --> LoopLayer
LoopLayer --> |完成| SetOutput["设置输出参数 *pMaxLevel 和 *pPtAmount"]
SetOutput --> End([结束])
```
**图源**
- [MediumA.cpp](file://cpp/ProblemZone/MediumA.cpp#L30-L167)
**本节源**
- [MediumA.cpp](file://cpp/ProblemZone/MediumA.cpp#L30-L167)
#### MediumW(偶极-偶极装置)算法
`CMediumW`类使用了一个外部的脚本生成库(scr_)来处理复杂的偶极-偶极装置的测量序列生成。
```mermaid
flowchart TD
Start([开始]) --> Init["初始化scr对象"]
Init --> SetRect["设置测量区域矩形"]
SetRect --> SetPoleStart["设置起始电极号"]
SetPoleStart --> SetZone["设置测量区域"]
SetZone --> Generate["调用scr_generate生成序列"]
Generate --> GetPoints["获取生成的测量点列表"]
GetPoints --> LoopPoints["循环每个测量点"]
LoopPoints --> CreateRecord["创建CSptRecord并填充A,B,M,N,K值"]
CreateRecord --> AddToArray["添加到pSptRecArray"]
AddToArray --> NextPoint["下一个点"]
NextPoint --> LoopPoints
LoopPoints --> |完成| Return["返回成功"]
Return --> End([结束])
```
**图源**
- [MediumW.cpp](file://cpp/ProblemZone/MediumW.cpp#L27-L62)
**本节源**
- [MediumW.cpp](file://cpp/ProblemZone/MediumW.cpp#L27-L62)
#### MediumBasicWenAndSch(施伦贝谢基础模型)算法
该模型实现了施伦贝谢装置的测量序列,其特点是AM间距和MN间距按特定规则递增。
```mermaid
flowchart TD
Start([开始]) --> LoopLayer["循环每一层 iLayer"]
LoopLayer --> CalcTailor["计算调整层数 iTailorLayer = (iLayer-1)/5"]
CalcTailor --> CalcAM["计算AM间距: iLayer - iTailorLayer"]
CalcAM --> CalcMN["计算MN间距: 1 + iTailorLayer*2"]
CalcMN --> SetInitialPos["设置初始电极位置"]
SetInitialPos --> CheckEnd["检查B电极是否超出范围"]
CheckEnd --> |是| Break["跳出循环"]
CheckEnd --> |否| LoopMeasure["循环测量"]
LoopMeasure --> CreateRecord["创建CSptRecord"]
CreateRecord --> CalcK["计算K值"]
CalcK --> AddToArray["添加到pSptRecArray"]
AddToArray --> MoveRight["电极向右平移1"]
MoveRight --> CheckEnd
LoopLayer --> |完成| SetOutput["设置输出参数"]
SetOutput --> End([结束])
```
**图源**
- [MediumBasicWenAndSch.cpp](file://cpp/ProblemZone/MediumBasicWenAndSch.cpp#L43-L118)
**本节源**
- [MediumBasicWenAndSch.cpp](file://cpp/ProblemZone/MediumBasicWenAndSch.cpp#L43-L118)
### 脚本参数配置界面
`DialNew2DTask`对话框是用户创建2D测量任务的主要界面,它收集了任务名称、测试地点、测量类型、电极间距等关键参数。
```mermaid
flowchart TD
A[任务名称] --> B[测试地点]
B --> C[测量类型]
C --> D[装置类型]
D --> E[脚本选择]
E --> F[电缆布线方式]
F --> G[发射周期]
G --> H[电极间距]
H --> I[采样间隔]
I --> J[起始/结束电极]
J --> K[验证输入]
K --> L[创建任务]
```
**本节源**
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp)
### 自定义脚本输入
`DialCustomSptInput`对话框允许用户手动输入或从Excel导入自定义的测量序列。
```mermaid
flowchart TD
A[手动输入] --> B[验证A,B,M,N,K值]
B --> C[计算K值(可选)]
C --> D[添加到列表]
D --> E[修改/删除列表项]
E --> F[从Excel导入]
F --> G[选择追加或替换]
G --> H[解析Excel数据]
H --> I[添加到列表]
I --> J[完成]
```
**本节源**
- [DialCustomSptInput.cpp](file://cpp/Operator/DialCustomSptInput.cpp)
## 依赖关系分析
2D脚本生成模块依赖于数据库连接、对话框界面和各种介质模型。
```mermaid
graph TD
SptManager --> Script2D
SptManager --> MediumA
SptManager --> MediumB
SptManager --> MediumC
SptManager --> MediumD
SptManager --> MediumE
SptManager --> MediumK
SptManager --> MediumQ
SptManager --> MediumR
SptManager --> MediumS
SptManager --> MediumT
SptManager --> MediumU
SptManager --> MediumV
SptManager --> MediumW
SptManager --> MediumX
SptManager --> MediumY
SptManager --> MediumZ
SptManager --> MediumZA
SptManager --> MediumZB
SptManager --> MediumZC
SptManager --> MediumLogging
SptManager --> MediumStrongWenAndSch
SptManager --> MediumBasicWenAndSch
SptManager --> MediumAM
SptManager --> MediumAMN
SptManager --> MediumCustom2D
SptManager --> MediumUnityProfile
SptManager --> MediumEdgeGradient
SptManager --> MeidumBipoleUpHole
SptManager --> MediumTwoSideAMN
SptManager --> MediumMidGardientScan
SptManager --> MediumStrongGradient
SptManager --> MediumCrossHoleGeomative
SptManager --> MediumCrossHoleGeomativeAM
SptManager --> MediumLandfillAdjacent
SptManager --> MediumLandfillDiagonally
SptManager --> MediumS3P
SptManager --> opcreatesptdlg.h
SptManager --> opcreatecesptdlg.h
SptManager --> OpCreate3DSptDlg.h
SptManager --> GD10OperCmd.h
SptManager --> MediumCustom2D.h
SptManager --> DialCreateNew3DSpt.h
DialNew2DTask --> SptManager
DialCustomSptInput --> SptManager
```
**图源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp#L10-L51)
**本节源**
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp#L10-L51)
## 性能考虑
在生成大型2D测量脚本时,性能主要受电极总数和层数的影响。`CMediumA`和`CMediumBasicWenAndSch`的算法复杂度为O(n²),其中n为电极数量。对于非常大的测量区域,建议分段创建脚本。
## 故障排除指南
常见问题及解决方案:
1. **电极冲突检测**:在`CMediumA::GenerateSptRecElecVal`中,通过检查`iAM`, `iAN`, `iBM`, `iBN`是否为零来避免电极位置重叠。
2. **测量序列优化**:`CMediumBasicWenAndSch::ReSortPoint`方法实现了优化的跑极顺序,以减少电极移动距离。
3. **K值计算错误**:在`CalculateK`方法中,当分母为零时会弹出错误提示,防止生成无效的K值。
4. **脚本名称重复**:在`CSptManager::Create2DSConInDB`中,通过查询数据库检查是否存在同名脚本,避免重复创建。
**本节源**
- [MediumA.cpp](file://cpp/ProblemZone/MediumA.cpp#L531-L538)
- [MediumBasicWenAndSch.cpp](file://cpp/ProblemZone/MediumBasicWenAndSch.cpp#L309-L384)
- [DialCustomSptInput.cpp](file://cpp/Operator/DialCustomSptInput.cpp#L505-L517)
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp#L334-L351)
## 结论
Geomative Studio的2D脚本生成系统是一个功能强大且灵活的框架。通过`CSptManager`统一管理,结合多种`CMedium`模型实现不同的测量装置,为用户提供了一个从参数配置到脚本生成的完整解决方案。该系统设计良好,易于扩展,能够满足各种复杂的地球物理测量需求。