Files
sunvpy-docs/docs/content/3-di-ge-jiao-ben-cha-xun-di-wu-shu-xing.md

457 lines
17 KiB
Markdown
Raw Permalink Normal View History

2026-04-10 13:47:53 +08:00
本页面将引导您编写第一个 SunvStation Python 脚本,从最基础的地物属性查询开始。通过实际案例,您将学习如何使用选择集过滤地物对象,并读取它们的属性信息。这是所有数据处理和编辑操作的基础起点。
## 脚本功能概览
我们的第一个脚本将实现以下完整流程:在当前地图中按照编码条件筛选地物对象,然后遍历选择集中的每个对象,读取并显示其核心属性信息。这个示例涵盖了脚本开发的四个核心环节——准备工作、筛选对象、遍历结果、输出信息。
Sources: [PySSProcess.py](PySSProcess.py#L110-L140)
## 完整工作流程
让我们先通过一个流程图理解整个脚本的数据流转过程,这有助于把握各步骤之间的逻辑关系:
```mermaid
flowchart LR
A[初始化 SSProcess<br>获取工作空间与地图] --> B[清除旧选择集<br>clearSelection]
B --> C[清除旧选择条件<br>clearSelectCondition]
C --> D[设置筛选条件<br>setSelectCondition]
D --> E[执行过滤查询<br>selectFilter]
E --> F{选择集非空?}
F -->|是| G[获取对象数量<br>getSelGeoCount]
F -->|否| H[脚本结束]
G --> I[循环遍历对象]
I --> J[获取对象属性<br>getSelGeoValue]
J --> K[输出属性信息]
K --> L{还有对象?}
L -->|是| I
L -->|否| H
```
这个流程图展示了脚本的核心执行路径,其中每个节点对应一个关键的 API 调用。接下来的详细教程将逐步解析每个节点的具体实现。
Sources: [PySSProcess.py](PySSProcess.py#L110-L140)
## 步骤一:准备环境与初始化
在编写任何脚本之前,首先需要导入 sunvpy 模块中的核心类 `SSProcess`。这是一个全局单例对象,封装了工作空间、地图、选择集以及所有地物操作的核心功能。初始化完成后,`SSProcess` 会自动获取当前 SunvStation 系统的工作空间和活动地图实例,为后续操作做好准备。
```python
from sunvpy import SSProcess
```
这个简单的导入语句就完成了所有必要的准备工作。`SSProcess` 内部维护了 `WorkSpace`(工作空间)和 `ScaleMap`(比例尺地图)两个核心对象,以及 `GeoBaseList`(地物列表)、`SSearchHelper`(搜索助手)等辅助对象,共同构成了脚本运行的基础环境。
Sources: [PySSProcess.py](PySSProcess.py#L35-L70)
## 步骤二:清理选择集与条件
在开始新的查询之前,良好的习惯是清理之前可能残留的选择集和选择条件。这确保了脚本的执行结果不受上一次操作的影响,提高了脚本的可重复性和可靠性。
```python
SSProcess.clearSelection() # 清除脚本选择集中的所有对象
SSProcess.clearSelectCondition() # 清除之前设置的选择条件
```
`clearSelection()` 会清空 `selGeoList`(点线面地物列表)和 `selNoteList`(注记对象列表),而 `clearSelectCondition()` 则会清空 `searchHelper` 中存储的过滤条件。这两个方法都是无参数的简单调用,为后续操作提供一个干净的开始状态。
Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L28-L50)
## 步骤三:设置选择条件
选择条件定义了我们要筛选地物的规则。SunvStation 支持三种类型的属性:基本属性、几何特性和扩展属性,它们通过不同的前缀标识符来区分。
### 条件类型说明
| 属性类型 | 前缀标识 | 示例 | 说明 |
|---------|---------|------|------|
| 基本属性 | `SSObj_` | `SSObj_Code` | 以 SSObj_ 开头的系统内置属性 |
| 几何特性 | `< >` | `<Overlap>` | 用尖括号括住的几何判断条件 |
| 扩展属性 | `[ ]` | `[JG]` | 用方括号括住的自定义扩展属性 |
### 操作符支持
系统提供了丰富的比较操作符,满足各种查询需求:
| 操作符 | 含义 | 示例 |
|--------|------|------|
| `==` | 等于 | `SSObj_Code == "3103013"` |
| `>` | 大于 | `SSObj_Length > "100"` |
| `<` | 小于 | `SSObj_Area < "500"` |
| `<>` | 不等于 | `SSObj_Type <> "NOTE"` |
| `LIKE` | 模糊匹配 | `SSObj_Name LIKE "%道路%"` |
| `NOT LIKE` | 不匹配 | `SSObj_Name NOT LIKE "%临时%"` |
| `CompareNoCase` | 忽略大小写比较 | `SSObj_Name CompareNoCase "MAIN"` |
| `Dec` | 小数位比较 | `SSObj_Area Dec 2` |
### 设置选择条件代码
在我们的第一个脚本中,我们将按照地物编码进行筛选:
```python
SSProcess.setSelectCondition("SSObj_Code", "==", "3103013")
```
这行代码会调用 `searchHelper.addCondition()` 方法,将条件添加到过滤条件列表中。地物编码 `3103013` 是一个具体的编码值,表示我们要筛选出编码为 3103013 的所有地物对象。
Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L52-L110)
## 步骤四:执行过滤查询
设置好选择条件后,需要调用 `selectFilter()` 方法来实际执行查询。这个方法会在当前数据源中查找符合所有设置条件的对象,并将它们添加到脚本选择集中。
```python
SSProcess.selectFilter()
```
`selectFilter()` 方法执行以下操作流程:
1. 调用 `searchHelper.getFilterObj()` 获取初步过滤的对象列表
2. 调用 `searchHelper.filterObj()` 进行精确过滤
3. 将过滤结果根据对象类型分别添加到 `selGeoList``selNoteList`
4. 在整个过程中显示进度条,提升用户体验
执行完成后,所有符合条件的对象都存储在 `SSProcess` 的内部选择集列表中,可以通过索引访问它们。
Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L112-L133)
## 步骤五:获取选择集对象数量
在遍历选择集之前,通常需要先了解查询到了多少对象,这有助于后续的逻辑判断和循环控制。
```python
geo_count = SSProcess.getSelGeoCount()
print(f"选择集中的点线面对象数量: {geo_count}")
```
`getSelGeoCount()` 方法返回 `selGeoList` 的长度,即当前选择集中的点、线、面对象总数。如果还有注记对象,可以使用 `getSelNoteCount()` 方法获取注记对象的数量。了解对象数量可以帮助我们判断查询结果是否符合预期,或者避免在空选择集上执行不必要的操作。
Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L152-L162)
## 步骤六:遍历选择集并读取属性
现在我们进入了脚本的核心部分——遍历选择集中的每个对象,并读取它们的属性值。这需要使用 `getSelGeoValue()` 方法,它接受两个参数:对象在选择集中的索引和属性名称。
### 常用地物属性速查表
| 属性名称 | 属性说明 | 数据类型 | 示例值 |
|---------|---------|---------|--------|
| `SSObj_ID` | 对象唯一标识 | 整数 | 1001 |
| `SSObj_Code` | 地物编码 | 整数 | 3103013 |
| `SSObj_LayerName` | 所在图层名 | 字符串 | "Default_A" |
| `SSObj_Type` | 对象类型 | 字符串 | "POINT", "LINE", "AREA", "NOTE" |
| `SSObj_Color` | 颜色值 | 整数 | 16777215 (白色) |
| `SSObj_LineType` | 线型 | 整数 | 1 |
| `SSObj_LineWidth` | 线宽 | 整数 | 2 |
| `SSObj_Name` | 对象名称 | 字符串 | "道路1" |
| `SSObj_Byname` | 对象别名 | 字符串 | "主路" |
| `SSObj_Area` | 面积 | 浮点数 | 1234.56 |
| `SSObj_Length` | 长度 | 浮点数 | 567.89 |
| `SSObj_PointCount` | 坐标点数量 | 整数 | 5 |
| `SSObj_X` | X坐标 | 浮点数 | 12345.67 |
| `SSObj_Y` | Y坐标 | 浮点数 | 54321.09 |
### 遍历代码示例
以下代码展示了如何遍历选择集的前10个对象并读取它们的多个属性
```python
# 定义要读取的属性列表
fields = [
"SSObj_ID", "SSObj_Code", "SSObj_LayerName", "SSObj_Type", "SSObj_Color",
"SSObj_LineType", "SSObj_LineWidth", "SSObj_Name", "SSObj_Byname",
"SSObj_Area", "SSObj_Length", "SSObj_X", "SSObj_Y"
]
# 遍历选择集最多显示前10个对象
for i in range(min(10, geo_count)):
print(f"第 {i} 个对象属性:")
for field in fields:
value = SSProcess.getSelGeoValue(i, field)
print(f" {field}: {value}")
print("-" * 40)
```
`getSelGeoValue()` 方法内部会根据属性名的前缀判断属性类型:
- 如果属性名以 `[` 开头,则调用 `map.getExtentAttr()` 获取扩展属性
- 否则,调用 `objBaseAttr.getGeoValue()` 获取基本属性
这种设计使得属性读取接口对用户保持统一,而内部实现则根据属性类型自动适配。
Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L189-L261)
## 完整示例脚本
将上述所有步骤组合起来,我们就得到了一个完整可运行的第一个脚本:
```python
from sunvpy import SSProcess
# 1. 清理选择集和条件
SSProcess.clearSelection()
SSProcess.clearSelectCondition()
# 2. 设置筛选条件:按编码筛选
SSProcess.setSelectCondition("SSObj_Code", "==", "3103013")
# 3. 执行过滤查询
SSProcess.selectFilter()
# 4. 获取选择集对象数量
geo_count = SSProcess.getSelGeoCount()
print(f"选择集中的点线面对象数量: {geo_count}")
# 5. 定义要读取的属性列表
fields = [
"SSObj_ID", "SSObj_Code", "SSObj_LayerName", "SSObj_Type", "SSObj_Color",
"SSObj_LineType", "SSObj_LineWidth", "SSObj_Name", "SSObj_Byname",
"SSObj_Area", "SSObj_Length", "SSObj_PointCount", "SSObj_X", "SSObj_Y"
]
# 6. 遍历选择集并读取属性
for i in range(min(10, geo_count)):
print(f"第 {i} 个对象属性:")
for field in fields:
value = SSProcess.getSelGeoValue(i, field)
print(f" {field}: {value}")
print("-" * 40)
```
运行这个脚本后,您将在控制台看到每个选中对象的详细属性信息,格式化输出为清晰的键值对形式,便于查看和调试。
Sources: [PySSProcess.py](PySSProcess.py#L110-L140)
## 脚本执行结果示例
假设我们的地图中有3个编码为3103013的地物对象脚本执行后的输出可能如下
```
选择集中的点线面对象数量: 3
第 0 个对象属性:
SSObj_ID: 1001
SSObj_Code: 3103013
SSObj_LayerName: Default_A
SSObj_Type: LINE
SSObj_Color: 16777215
SSObj_LineType: 1
SSObj_LineWidth: 1
SSObj_Name: 道路1
SSObj_Byname: 主路
SSObj_Area: 0.0
SSObj_Length: 567.89
SSObj_PointCount: 5
SSObj_X: 12345.67
SSObj_Y: 54321.09
----------------------------------------
第 1 个对象属性:
SSObj_ID: 1002
SSObj_Code: 3103013
SSObj_LayerName: Default_A
SSObj_Type: LINE
SSObj_Color: 16777215
SSObj_LineType: 1
SSObj_LineWidth: 1
SSObj_Name: 道路2
SSObj_Byname: 支路
SSObj_Area: 0.0
SSObj_Length: 234.56
SSObj_PointCount: 3
SSObj_X: 13000.00
SSObj_Y: 55000.00
----------------------------------------
第 2 个对象属性:
SSObj_ID: 1003
SSObj_Code: 3103013
SSObj_LayerName: Default_A
SSObj_Type: AREA
SSObj_Color: 16711680
SSObj_LineType: 2
SSObj_LineWidth: 2
SSObj_Name: 区域1
SSObj_Byname: 核心区
SSObj_Area: 1234.56
SSObj_Length: 150.00
SSObj_PointCount: 6
SSObj_X: 12500.00
SSObj_Y: 54500.00
----------------------------------------
```
从输出结果可以看出我们成功查询到了3个符合条件的对象包括2个线型对象和1个面对象每个对象的属性都清晰地显示出来。
## 常见问题与解决方案
### 问题1选择集为空
**现象**:运行脚本后显示"选择集中的点线面对象数量: 0"
**可能原因**
- 指定的编码在当前地图中不存在
- 当前数据源中没有符合条件的对象
- 选择条件设置不正确
**解决方案**:尝试使用更宽泛的条件,例如按图层筛选:
```python
SSProcess.setSelectCondition("SSObj_LayerName", "==", "Default_A")
```
或者不设置任何条件,查询所有对象:
```python
# 不调用 setSelectCondition直接执行 selectFilter
SSProcess.selectFilter()
```
### 问题2属性值为空
**现象**:某些属性显示为空字符串
**可能原因**
- 该属性对于当前对象类型不适用(例如,点对象的 `SSObj_Area` 总是为 0
- 扩展属性 `[ ]` 在当前对象上不存在
**解决方案**:根据对象类型选择合适的属性。例如,对于线对象,查询 `SSObj_Length`;对于面对象,查询 `SSObj_Area`
### 问题3扩展属性无法读取
**现象**:使用 `[扩展属性名]` 格式读取时返回空值
**可能原因**
- 扩展属性名称拼写错误
- 当前对象没有该扩展属性
**解决方案**:先查询对象的扩展属性列表:
```python
# 获取对象的扩展属性字段名
SSProcess.curSelGeoFields.clear()
SSProcess.curSelGeoValues.clear()
SSProcess.map.getExtentAttr(geo, SSProcess.curSelGeoFields, SSProcess.curSelGeoValues)
# 打印所有扩展属性
for i in range(SSProcess.curSelGeoFields.size()):
print(f"{SSProcess.curSelGeoFields[i]}: {SSProcess.curSelGeoValues[i]}")
```
Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L189-L261)
## 架构原理补充说明
### SSProcess 的内部结构
`SSProcessManager` 类采用了**Mixin 设计模式**,将不同功能模块分离到独立的 Mixin 类中,然后通过多重继承组合成一个功能完整的管理器:
```mermaid
classDiagram
class SSProcessManager {
-workspace: WorkSpace
-map: ScaleMap
-selGeoList: GeoBaseList
-selNoteList: GeoBaseList
-searchHelper: SSearchHelper
+clearSelection()
+clearSelectCondition()
+setSelectCondition()
+selectFilter()
+getSelGeoCount()
+getSelGeoValue()
}
class SelectionMixin {
+clearSelection()
+clearSelectCondition()
+setSelectCondition()
+selectFilter()
+getSelGeoCount()
+getSelGeoValue()
}
class GeoEditMixin {
+createGeo()
+deleteGeo()
+updateGeo()
}
class ProjectMixin {
+getWorkspace()
+getMap()
}
class LogMixin {
+log()
+logger
}
class ProgressMixin {
+startProgress()
+stepProgress()
+closeProgress()
}
SSProcessManager --|> SelectionMixin
SSProcessManager --|> GeoEditMixin
SSProcessManager --|> ProjectMixin
SSProcessManager --|> LogMixin
SSProcessManager --|> ProgressMixin
```
这种架构设计的优势在于:
- **关注点分离**:每个 Mixin 只负责一个特定的功能领域
- **代码复用**:不同功能的代码可以独立维护和测试
- **扩展性强**:新增功能只需添加新的 Mixin 类
- **清晰的职责边界**:便于理解和使用
Sources: [PySSProcess.py](PySSProcess.py#L35-L70)
### 属性读取机制
SunvStation 支持三种属性类型,它们在底层有不同的存储和访问机制:
```mermaid
flowchart LR
A[getSelGeoValue 调用] --> B{属性名前缀判断}
B -->|基本属性| C[调用 objBaseAttr.getGeoValue]
B -->|几何特性| D[调用 searchHelper 几何判断]
B -->|扩展属性| E[调用 map.getExtentAttr]
C --> F[返回基本属性值]
D --> G[返回几何特性结果]
E --> H[返回扩展属性值]
F --> I[统一返回字符串]
G --> I
H --> I
```
基本属性存储在 C++ 对象的内部结构中,通过 `ObjBaseAttr` 类的索引机制快速访问;扩展属性存储在数据库或附加结构中,通过地图接口动态获取;几何特性则是实时计算的判断结果。
Sources: [ObjBaseAttr.py](ObjBaseAttr.py#L1-L50)
## 下一步学习建议
掌握了第一个脚本的基本流程后,您可以根据自己的学习需求选择接下来的学习路径:
### 继续深入选择集与查询
如果您想了解更多选择集操作和高级查询技巧,建议阅读:
- **[使用 SSProcess 管理选择集](4-shi-yong-ssprocess-guan-li-xuan-ze-ji)** - 学习更复杂的选择集管理方法
- **[设置选择条件](12-she-zhi-xuan-ze-tiao-jian)** - 深入了解多条件组合查询
- **[遍历选择集对象](14-bian-li-xuan-ze-ji-dui-xiang)** - 掌握高效的遍历技巧
### 学习地物属性操作
如果您想学习如何修改地物属性,建议阅读:
- **[获取地物属性值](15-huo-qu-di-wu-shu-xing-zhi)** - 了解更多属性获取细节
- **[修改地物属性值](16-xiu-gai-di-wu-shu-xing-zhi)** - 学习如何批量修改属性
- **[地物基本属性详解](17-di-wu-ji-ben-shu-xing-xiang-jie)** - 查看所有可用属性的完整列表
### 探索高级功能
如果您已经掌握了基础知识,可以尝试更高级的功能:
- **[运行内置示例脚本](5-yun-xing-nei-zhi-shi-li-jiao-ben)** - 查看更多实际应用案例
- **[SunvStation 系统架构](6-sunvstation-xi-tong-jia-gou)** - 理解系统的整体设计原理
无论选择哪条路径,都建议您在实际项目中多练习,通过编写不同的脚本加深对 SunvStation Python API 的理解。每个页面都提供了详细的示例代码和源文件引用,可以作为您学习的参考手册。