SunvStation 地理信息系统采用分层架构设计,其中工作空间与地图是理解整个系统的核心概念。本页将详细阐述这两个核心组件的职责、相互关系以及在 Python 脚本中的使用方式。掌握这些概念是高效使用 sunvpy 库进行二次开发的基础。 ## 系统架构概览 SunvStation 系统采用单例模式的工作空间作为顶级容器,管理所有地图实例和系统资源。工作空间通过 `getInstance()` 方法获取全局唯一实例,确保整个应用程序共享同一资源上下文。地图对象则表示特定比例尺的地理数据视图,包含图层、地物、数据源等子组件。 ```mermaid graph TB subgraph "应用程序级别" WS[WorkSpace 工作空间
单例实例] end subgraph "地图级别" SM1[ScaleMap 地图1
比例尺1:500] SM2[ScaleMap 地图2
比例尺1:1000] end subgraph "SM1 组件" L1[图层1] L2[图层2] DS1[数据源EPS] end subgraph "SM2 组件" L3[图层3] L4[图层4] DS2[数据源EPS] end subgraph "Python 脚本" PSS[SSProcessManager
SSProcess全局实例] end PSS --> |WorkSpace.getInstance| WS PSS --> |getCurrentScaleMap| SM1 WS --> |管理多个| SM1 WS --> |管理多个| SM2 SM1 --> |包含| L1 SM1 --> |包含| L2 SM1 --> |引用| DS1 SM2 --> |包含| L3 SM2 --> |包含| L4 SM2 --> |引用| DS2 ``` 上图展示了系统的核心架构。工作空间作为顶级容器,管理所有地图实例。每个地图对象包含一组图层和关联的数据源。Python 脚本通过 `SSProcess` 全局实例访问工作空间和当前地图,实现与系统资源的交互。 Sources: [PySSProcess.py](PySSProcess.py#L30-L60) ## 工作空间 工作空间是 SunvStation 系统的全局单例对象,负责管理整个应用程序的资源和上下文。它提供统一的入口点来访问当前活动的地图、配置信息和系统路径。 ### 核心特性 工作空间采用单例设计模式,确保整个应用程序中只有一个工作空间实例。这种设计有以下优势: - **资源统一管理**:所有地图实例和共享资源由工作空间统一分配和协调 - **全局状态一致性**:确保不同模块访问的系统状态保持一致 - **生命周期控制**:工作空间控制整个应用程序的生命周期,包括资源的创建和销毁 ### 获取工作空间实例 在 Python 脚本中,通过 `WorkSpace.getInstance()` 方法获取工作空间实例。`SSProcessManager` 在初始化时会自动获取工作空间实例并存储为成员变量 `self.workspace`。 Sources: [PySSProcess.py](PySSProcess.py#L42-L43) ### 主要职责 工作空间的核心职责包括: - **地图管理**:维护所有打开的地图实例,提供获取当前活动地图的接口 - **资源协调**:协调地图之间的资源共享和互斥访问 - **全局配置**:存储和管理全局配置信息 - **系统路径**:提供系统级路径信息(配置路径、模板路径、脚本路径等) ### 便捷访问方法 `ProjectMixin` 提供了便捷方法 `getWorkspace()` 来获取工作空间实例: Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L36-L43) ## 地图 地图对象(`ScaleMap`)表示特定比例尺的地理数据视图,是工作空间中最核心的可视化和编辑单元。每个地图包含一组图层、地物对象和关联的数据源。 ### 地图对象定义 `ScaleMap` 类定义在 `PySSMap` 模块中,通过 SWIG 从 C++ 封装而来。它是地图数据的主要容器和管理者。 Sources: [PySSMap.py](PySSMap.py#L303-L330) ### 地图组成结构 地图由以下核心组件构成: | 组件类型 | 职责 | Python 类型 | |---------|------|-----------| | 图层 | 组织和管理地物对象,控制可见性和锁定状态 | Layer | | 数据源 | 存储地物数据的底层存储(EPS 数据库) | DataSource | | 地物对象 | 点、线、面等地理要素 | GeoObject | | 选择集 | 当前选中的地物集合 | GeoBaseList | | 符号表 | 要素编码和符号样式定义 | FeatureList | ### 图层管理 图层是地图中组织地物的逻辑单元。每个图层对应特定的数据类型(点、线、面、注记),可以独立控制其可见性和编辑锁定状态。 #### 图层操作 API | 方法 | 功能描述 | |-----|---------| | `getLayerSize()` | 获取图层数量 | | `getLayerName(index)` | 获取指定索引的图层名称 | | `setLayerVisible(layerName, status)` | 设置图层可见性 | | `isLayerVisible(layerName)` | 检查图层是否可见 | | `setLayerLock(layerName, status)` | 设置图层锁定状态 | | `isLayerLock(layerName)` | 检查图层是否锁定 | Sources: [PySSMap.py](PySSMap.py#L355-L430) #### 便捷访问方法 `ProjectMixin` 提供了简化的图层访问接口: Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L180-L198) ### 数据源管理 数据源是存储地物数据的底层存储,通常是 EPS 格式的数据库。地图可以加载多个数据源,每个数据源包含多个数据集。 | 方法 | 功能描述 | |-----|---------| | `getCurrentDataSource()` | 获取当前激活的数据源 | | `setCurrentDataSource(dataSource)` | 设置当前数据源 | | `unloadDataSource(dataSource)` | 卸载指定的数据源 | | `getDataSourceSet(dataSourceSet)` | 获取所有可见图层使用的数据源集合 | Sources: [PySSMap.py](PySSMap.py#L445-L480) ### 地物搜索与检索 地图提供了强大的地物搜索功能,支持多种搜索条件: | 方法 | 功能描述 | |-----|---------| | `searchObject(objList, ...)` | 根据编码、矩形范围、点位置等条件搜索地物 | | `searchMarkNote(geoList, ...)` | 搜索注记对象 | | `getNearObject(point, range, ...)` | 获取指定点附近的地物或注记 | | `getObjectSize(objType)` | 获取指定类型的地物个数 | Sources: [PySSMap.py](PySSMap.py#L650-L1000) ### 撤销与重做 地图内置了完整的撤销/重做机制,所有可撤销操作都会被记录在命令栈中。 | 方法 | 功能描述 | |-----|---------| | `pushUndoMark(action)` | 创建撤销标记,用于分组多个操作 | | `undo(step=1)` | 执行撤销操作,step 指定步数 | | `redo(step=1)` | 执行重做操作 | | `getUndoStackSize()` | 获取撤销栈的大小 | | `getRedoStackSize()` | 获取重做栈的大小 | Sources: [PySSMap.py](PySSMap.py#L1565-L1610) ## 工作空间与地图的关系 工作空间和地图之间的关系是整体与部分的关系。工作空间作为全局容器,可以管理多个地图实例,但通常只有一个当前活动的地图。 ### 访问当前地图 通过工作空间的 `getCurrentScaleMap()` 方法获取当前活动的地图实例。在 `SSProcessManager` 初始化时,会自动获取当前地图并存储为成员变量 `self.map`。 Sources: [PySSProcess.py](PySSProcess.py#L42-L43) ### 地图切换 当用户切换地图时(例如从不同比例尺的地图视图切换),工作空间会更新当前活动的地图引用。Python 脚本可以通过以下方式获取最新的当前地图: ```python # 方法1:直接使用 SSProcess 的 map 成员 current_map = SSProcess.map # 方法2:通过工作空间获取 current_map = SSProcess.workspace.getCurrentScaleMap() # 方法3:使用便捷方法 current_map = SSProcess.getCurrentMap() ``` Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L45-L50) ## 系统路径管理 工作空间和相关组件提供了获取系统路径的接口,这些路径对于脚本操作文件和配置非常重要。 ### 路径类型表 | 模式 | 路径类型 | 说明 | |-----|---------|------| | 0 | 配置路径 | 存放系统配置文件 | | 1 | 模板路径 | 存放模板文件 | | 2 | Comm 路径 | 公共资源路径 | | 3 | Script 路径 | 脚本文件路径 | | 4 | SSTemp 路径 | 临时文件路径 | | 5 | 工程文件路径 | 当前工程所在目录 | | 6 | 系统目录 | Windows 系统目录或 Unix /usr | | 7/8 | 工作台面目录 | 用户工作台面目录 | Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L52-L80) ### 使用示例 ```python # 获取脚本路径 script_path = SSProcess.getSysPathName(3) # 获取当前工程文件所在目录 project_dir = SSProcess.getSysPathName(5) # 获取配置路径 config_path = SSProcess.getSysPathName(0) ``` ## 符号表管理 地图使用符号表来定义地物的显示样式和要素编码。符号表包括要素代码表、符号脚本表和注记模板表。 | 方法 | 功能描述 | |-----|---------| | `getFeatureCodeTB()` | 获取当前要素代码表名称 | | `getSymbolScriptTB()` | 获取当前符号表名称 | | `getNoteTemplateTB()` | 获取当前注记模板表名称 | | `setFeatureCodeTB(codeTB, symbolTB)` | 设置要素代码表和符号表 | | `setNoteTemplateTB(templateTB)` | 设置注记模板表 | Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L200-L267) ## 地图图幅管理 地图图幅是地图的一个逻辑划分单位,用于组织和管理地图的分幅显示。`ProjectMixin` 提供了图幅相关操作: | 方法 | 功能描述 | |-----|---------| | `createMapFrame()` | 创建当前地图的图幅列表 | | `getMapFrameCount()` | 获取图幅数量 | | `getMapFrameCenterPoint(index)` | 获取指定图幅的中心点坐标 | | `setCurMapFrame(x, y)` | 设置当前图幅 | | `getCurMapFrame()` | 获取当前图幅的编号 | | `getMapFrameNumber(x, y)` | 获取指定坐标所在的图幅号 | | `freeMapFrame()` | 释放图幅资源 | Sources: [ssprocess_mixins/project_mixin.py](ssprocess_mixins/project_mixin.py#L122-L178) ## 最佳实践 在使用工作空间和地图时,遵循以下最佳实践可以编写更健壮和高效的代码: ### 1. 始终检查空引用 访问地图或工作空间对象前,检查是否为 None: ```python current_map = SSProcess.getCurrentMap() if current_map is None: print("当前没有打开的地图") return ``` ### 2. 使用便捷方法优先 `ProjectMixin` 提供的便捷方法已经处理了常见的边界情况,优先使用这些方法而不是直接访问底层对象。 ### 3. 批量操作使用撤销标记 执行批量修改操作前,先创建撤销标记: ```python SSProcess.pushUndoMark("批量属性修改") # 执行批量操作... ``` ### 4. 及时释放资源 对于创建的临时资源(如图幅列表),使用完毕后及时释放: ```python try: SSProcess.createMapFrame() # 处理图幅... finally: SSProcess.freeMapFrame() ``` ### 5. 尊重图层锁定状态 修改地物前检查图层是否锁定: ```python layer_name = "DLG" if not SSProcess.map.isLayerLock(layer_name): # 执行修改操作 pass else: print(f"图层 {layer_name} 已锁定,无法编辑") ``` ## 与其他文档的关联 理解工作空间与地图概念后,可以继续深入学习以下主题: - **选择集与查询**:[清除与初始化选择集](11-qing-chu-yu-chu-shi-hua-xuan-ze-ji) 了解如何在地图中查询和选择地物 - **地理对象编辑**:[创建默认地物对象](19-chuang-jian-mo-ren-di-wu-dui-xiang) 学习如何在工作空间和地图中创建地物 - **项目与工作流**:[获取工作空间信息](34-huo-qu-gong-zuo-kong-jian-xin-xi) 探索更多工作空间信息获取方法 - **Mixin 设计模式**:[Mixin 设计模式](9-mixin-she-ji-mo-shi) 理解 ProjectMixin 等模块的设计理念 通过掌握工作空间与地图的核心概念,您将能够更高效地使用 sunvpy 库进行二次开发,构建功能强大的地理信息处理脚本。