本页面将引导您编写第一个 SunvStation Python 脚本,从最基础的地物属性查询开始。通过实际案例,您将学习如何使用选择集过滤地物对象,并读取它们的属性信息。这是所有数据处理和编辑操作的基础起点。 ## 脚本功能概览 我们的第一个脚本将实现以下完整流程:在当前地图中按照编码条件筛选地物对象,然后遍历选择集中的每个对象,读取并显示其核心属性信息。这个示例涵盖了脚本开发的四个核心环节——准备工作、筛选对象、遍历结果、输出信息。 Sources: [PySSProcess.py](PySSProcess.py#L110-L140) ## 完整工作流程 让我们先通过一个流程图理解整个脚本的数据流转过程,这有助于把握各步骤之间的逻辑关系: ```mermaid flowchart LR A[初始化 SSProcess
获取工作空间与地图] --> B[清除旧选择集
clearSelection] B --> C[清除旧选择条件
clearSelectCondition] C --> D[设置筛选条件
setSelectCondition] D --> E[执行过滤查询
selectFilter] E --> F{选择集非空?} F -->|是| G[获取对象数量
getSelGeoCount] F -->|否| H[脚本结束] G --> I[循环遍历对象] I --> J[获取对象属性
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_ 开头的系统内置属性 | | 几何特性 | `< >` | `` | 用尖括号括住的几何判断条件 | | 扩展属性 | `[ ]` | `[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 的理解。每个页面都提供了详细的示例代码和源文件引用,可以作为您学习的参考手册。