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

17 KiB
Raw Blame History

本页面将引导您编写第一个 SunvStation Python 脚本,从最基础的地物属性查询开始。通过实际案例,您将学习如何使用选择集过滤地物对象,并读取它们的属性信息。这是所有数据处理和编辑操作的基础起点。

脚本功能概览

我们的第一个脚本将实现以下完整流程:在当前地图中按照编码条件筛选地物对象,然后遍历选择集中的每个对象,读取并显示其核心属性信息。这个示例涵盖了脚本开发的四个核心环节——准备工作、筛选对象、遍历结果、输出信息。

Sources: PySSProcess.py

完整工作流程

让我们先通过一个流程图理解整个脚本的数据流转过程,这有助于把握各步骤之间的逻辑关系:

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

步骤一:准备环境与初始化

在编写任何脚本之前,首先需要导入 sunvpy 模块中的核心类 SSProcess。这是一个全局单例对象,封装了工作空间、地图、选择集以及所有地物操作的核心功能。初始化完成后,SSProcess 会自动获取当前 SunvStation 系统的工作空间和活动地图实例,为后续操作做好准备。

from sunvpy import SSProcess

这个简单的导入语句就完成了所有必要的准备工作。SSProcess 内部维护了 WorkSpace(工作空间)和 ScaleMap(比例尺地图)两个核心对象,以及 GeoBaseList(地物列表)、SSearchHelper(搜索助手)等辅助对象,共同构成了脚本运行的基础环境。

Sources: PySSProcess.py

步骤二:清理选择集与条件

在开始新的查询之前,良好的习惯是清理之前可能残留的选择集和选择条件。这确保了脚本的执行结果不受上一次操作的影响,提高了脚本的可重复性和可靠性。

SSProcess.clearSelection()      # 清除脚本选择集中的所有对象
SSProcess.clearSelectCondition() # 清除之前设置的选择条件

clearSelection() 会清空 selGeoList(点线面地物列表)和 selNoteList(注记对象列表),而 clearSelectCondition() 则会清空 searchHelper 中存储的过滤条件。这两个方法都是无参数的简单调用,为后续操作提供一个干净的开始状态。

Sources: ssprocess_mixins/selection_mixin.py

步骤三:设置选择条件

选择条件定义了我们要筛选地物的规则。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

设置选择条件代码

在我们的第一个脚本中,我们将按照地物编码进行筛选:

SSProcess.setSelectCondition("SSObj_Code", "==", "3103013")

这行代码会调用 searchHelper.addCondition() 方法,将条件添加到过滤条件列表中。地物编码 3103013 是一个具体的编码值,表示我们要筛选出编码为 3103013 的所有地物对象。

Sources: ssprocess_mixins/selection_mixin.py

步骤四:执行过滤查询

设置好选择条件后,需要调用 selectFilter() 方法来实际执行查询。这个方法会在当前数据源中查找符合所有设置条件的对象,并将它们添加到脚本选择集中。

SSProcess.selectFilter()

selectFilter() 方法执行以下操作流程:

  1. 调用 searchHelper.getFilterObj() 获取初步过滤的对象列表
  2. 调用 searchHelper.filterObj() 进行精确过滤
  3. 将过滤结果根据对象类型分别添加到 selGeoListselNoteList
  4. 在整个过程中显示进度条,提升用户体验

执行完成后,所有符合条件的对象都存储在 SSProcess 的内部选择集列表中,可以通过索引访问它们。

Sources: ssprocess_mixins/selection_mixin.py

步骤五:获取选择集对象数量

在遍历选择集之前,通常需要先了解查询到了多少对象,这有助于后续的逻辑判断和循环控制。

geo_count = SSProcess.getSelGeoCount()
print(f"选择集中的点线面对象数量: {geo_count}")

getSelGeoCount() 方法返回 selGeoList 的长度,即当前选择集中的点、线、面对象总数。如果还有注记对象,可以使用 getSelNoteCount() 方法获取注记对象的数量。了解对象数量可以帮助我们判断查询结果是否符合预期,或者避免在空选择集上执行不必要的操作。

Sources: ssprocess_mixins/selection_mixin.py

步骤六:遍历选择集并读取属性

现在我们进入了脚本的核心部分——遍历选择集中的每个对象,并读取它们的属性值。这需要使用 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个对象并读取它们的多个属性

# 定义要读取的属性列表
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

完整示例脚本

将上述所有步骤组合起来,我们就得到了一个完整可运行的第一个脚本:

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

脚本执行结果示例

假设我们的地图中有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"

可能原因

  • 指定的编码在当前地图中不存在
  • 当前数据源中没有符合条件的对象
  • 选择条件设置不正确

解决方案:尝试使用更宽泛的条件,例如按图层筛选:

SSProcess.setSelectCondition("SSObj_LayerName", "==", "Default_A")

或者不设置任何条件,查询所有对象:

# 不调用 setSelectCondition直接执行 selectFilter
SSProcess.selectFilter()

问题2属性值为空

现象:某些属性显示为空字符串

可能原因

  • 该属性对于当前对象类型不适用(例如,点对象的 SSObj_Area 总是为 0
  • 扩展属性 [ ] 在当前对象上不存在

解决方案:根据对象类型选择合适的属性。例如,对于线对象,查询 SSObj_Length;对于面对象,查询 SSObj_Area

问题3扩展属性无法读取

现象:使用 [扩展属性名] 格式读取时返回空值

可能原因

  • 扩展属性名称拼写错误
  • 当前对象没有该扩展属性

解决方案:先查询对象的扩展属性列表:

# 获取对象的扩展属性字段名
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 的内部结构

SSProcessManager 类采用了Mixin 设计模式,将不同功能模块分离到独立的 Mixin 类中,然后通过多重继承组合成一个功能完整的管理器:

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

属性读取机制

SunvStation 支持三种属性类型,它们在底层有不同的存储和访问机制:

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

下一步学习建议

掌握了第一个脚本的基本流程后,您可以根据自己的学习需求选择接下来的学习路径:

继续深入选择集与查询

如果您想了解更多选择集操作和高级查询技巧,建议阅读:

学习地物属性操作

如果您想学习如何修改地物属性,建议阅读:

探索高级功能

如果您已经掌握了基础知识,可以尝试更高级的功能:

无论选择哪条路径,都建议您在实际项目中多练习,通过编写不同的脚本加深对 SunvStation Python API 的理解。每个页面都提供了详细的示例代码和源文件引用,可以作为您学习的参考手册。