Files
sunvpy-docs/docs/content/3-di-ge-jiao-ben-cha-xun-di-wu-shu-xing.md
2026-04-10 13:47:53 +08:00

457 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
本页面将引导您编写第一个 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 的理解。每个页面都提供了详细的示例代码和源文件引用,可以作为您学习的参考手册。