修改地物属性值是 SunvStation Python API 中最核心的数据操作功能之一。本页将系统性地介绍如何通过脚本修改地物的基本属性、扩展属性以及几何属性,并确保修改内容正确保存到数据库。 ## 属性修改架构概览 地物属性修改涉及三个核心层次:**新建对象属性设置**、**选择集对象属性修改**和**批量保存机制**。理解这个架构对于正确使用 API 至关重要。 ```mermaid flowchart TB A[开始属性修改] --> B{修改场景} B --> C[新建对象] B --> D[选择集对象] B --> E[批量修改] C --> C1[createDefaultGeoBase
创建对象] C1 --> C2[setNewObjValue
设置属性] C2 --> C3[addNewObjToSaveObjList
添加到保存列表] D --> D1[遍历选择集对象] D1 --> D2{属性类型} D2 --> D3[SSObj_Code/LayerName
特殊处理] D2 --> D4[基本属性
setGeoValue] D2 --> D5[扩展属性
setMemoData] D3 --> D6[addSelGeoToSaveGeoList
添加到保存列表] D4 --> D6 D5 --> D6 E --> E1[setSelGeoValue -1
批量设置] E1 --> E2[addSelGeoToSaveGeoList -1
批量添加] C3 --> F[saveBufferObjToDatabase
保存到数据库] D6 --> F E2 --> F F --> G[updateRequest
刷新地图显示] G --> H[完成] ``` ## 属性类型与命名规范 SunvStation 支持三种不同类型的属性,每种类型使用特定的命名前缀和语法规则。 | 属性类型 | 命名格式 | 示例 | 说明 | |---------|---------|------|------| | **基本属性** | `SSObj_` 开头 | `SSObj_Code`, `SSObj_Name`, `SSObj_Color` | 系统预定义的固有属性 | | **扩展属性** | `[属性名]` 格式 | `[建筑类型]`, `[施工状态]` | 用户自定义的扩展字段 | | **几何属性** | `<属性名>` 格式 | ``, ``, `` | 对象的几何特性和坐标信息 | ### 基本属性分类 **通用属性**:涵盖对象的标识、图层和图形表现。这包括对象 ID、编码、图层名称、颜色、线型和线宽等关键属性。 **几何属性**:涉及对象的坐标、几何尺寸和拓扑特征。包括坐标点(X, Y, Z)、面积、长度、边界框等几何信息。 **注记属性**:专门针对文本标注的样式和格式。包括字体宽度、高度、名称、内容、对齐方式和角度等详细属性。 **时间与状态**:记录对象的创建和修改时间,以及对象的状态标记。 Sources: [ObjBaseAttr.py](ObjBaseAttr.py#L9-L79) ## 修改新建对象的属性 当通过 `createDefaultGeoBase()` 或 `createNewObjByCode()` 创建新地物对象后,可以使用 `setNewObjValue()` 方法设置其属性。这种方法适用于单次创建并立即设置属性的场景。 ### 基本属性设置 ```python # 创建编码为 100 的线对象 obj, geo = ssp.createNewObjByCode(100) # 设置基本属性 ssp.setNewObjValue("SSObj_Name", "主干道") ssp.setNewObjValue("SSObj_Color", "16711680") # RGB 红色 ssp.setNewObjValue("SSObj_LineWidth", "2") ssp.setNewObjValue("SSObj_Angle", "45.0") ``` ### 扩展属性设置 扩展属性使用方括号 `[]` 包裹属性名,可以同时设置多个属性: ```python # 设置单个扩展属性 ssp.setNewObjValue("[建筑类型]", "住宅楼") ssp.setNewObjValue("[建成年份]", "2020") # 同时设置多个扩展属性(用逗号分隔) ssp.setNewObjValue("[建筑类型],[建成年份],[楼层数]", "商业楼,2021,18") ``` ### 注记属性设置 对于注记对象,支持专门的字体属性: ```python # 创建注记对象 obj, note = ssp.createNewObjByClass("1") # 分类号为1的注记 # 设置注记属性 ssp.setNewObjValue("SSObj_FontString", "示例文字") ssp.setNewObjValue("SSObj_FontHeight", "300") ssp.setNewObjValue("SSObj_FontWidth", "200") ssp.setNewObjValue("SSObj_FontName", "SimSun") ssp.setNewObjValue("SSObj_FontAlignment", "1") # 对齐方式 ``` 完成属性设置后,需要将新对象添加到保存列表并持久化: ```python ssp.addNewObjToSaveObjList() ssp.saveBufferObjToDatabase() ssp.updateRequest() ``` Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L106-L266) ## 修改选择集中对象的属性 对于已经存在于地图上的对象,需要先通过选择集过滤获取目标对象,然后使用 `setSelGeoValue()` 或 `setSelNoteValue()` 修改属性。 ### 选择集对象属性修改流程 ```mermaid flowchart LR A[设置选择条件] --> B[执行过滤查询] B --> C[遍历选择集] C --> D[修改对象属性] D --> E[添加到保存列表] E --> F[保存到数据库] F --> G[刷新显示] ``` ### 修改单个对象的属性 通过指定索引值修改选择集中特定对象的属性: ```python # 清除并设置选择条件 ssp.clearSelection() ssp.clearSelectCondition() ssp.setSelectCondition("SSObj_Code", "==", "100") ssp.selectFilter() # 修改选择集中第0个对象的属性 ssp.setSelGeoValue(0, "SSObj_Name", "修改后的名称") ssp.setSelGeoValue(0, "SSObj_Color", "255") # 设置颜色号 ssp.setSelGeoValue(0, "[施工状态]", "已完成") # 将修改后的对象添加到保存列表 ssp.addSelGeoToSaveGeoList(0) # 批量保存到数据库 ssp.saveBufferObjToDatabase() ssp.updateRequest() ``` ### 批量修改选择集对象的属性 将索引值设为 `-1` 可以一次性修改选择集中的所有对象: ```python # 获取所有编码为 100 的对象 ssp.clearSelection() ssp.setSelectCondition("SSObj_Code", "==", "100") ssp.selectFilter() print(f"当前选择集对象数量: {ssp.getSelGeoCount()}") # 批量修改所有选择集对象的属性 ssp.setSelGeoValue(-1, "SSObj_Color", "255") # 统一颜色 ssp.setSelGeoValue(-1, "SSObj_LineWidth", "3") # 统一线宽 ssp.setSelGeoValue(-1, "[更新时间]", "2024-01-15") # 批量添加到保存列表 for i in range(ssp.getSelGeoCount()): ssp.addSelGeoToSaveGeoList(i) # 保存并刷新 ssp.saveBufferObjToDatabase() ssp.updateRequest() ``` ### 修改注记对象的属性 对于注记对象,使用 `setSelNoteValue()` 方法: ```python # 清除并设置注记选择条件 ssp.clearSelection() ssp.setSelectCondition("SSObj_Type", "==", "NOTE") ssp.setSelectCondition("[注记分类]", "==", "道路注记") ssp.selectFilter() # 批量修改注记属性 ssp.setSelNoteValue(-1, "SSObj_FontHeight", "250") ssp.setSelNoteValue(-1, "SSObj_FontWeight", "700") # 粗体 ssp.setSelNoteValue(-1, "SSObj_FontColor", "16777215") # 白色 # 添加到保存列表 for i in range(ssp.getSelNoteCount()): ssp.addSelNoteToSaveNoteList(i) # 保存 ssp.saveBufferObjToDatabase() ssp.updateRequest() ``` Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L310-L411) ## 特殊属性处理 某些属性的修改涉及对象重建或特殊逻辑,需要特别注意。 ### 编码属性(SSObj_Code)修改 修改对象编码会触发对象重新创建,需要通过数据源重新获取特性信息: ```python # 修改单个对象的编码 ssp.setSelGeoValue(0, "SSObj_Code", "200") # 注意:此操作会自动处理对象重建 # 无需手动管理新旧对象的替换 ``` ### 图层属性(SSObj_LayerName)修改 将对象移动到不同图层涉及完整的对象克隆和数据集切换: ```python # 将选择集中的对象移动到"建筑"图层 ssp.setSelGeoValue(0, "SSObj_LayerName", "建筑") # 系统会自动: # 1. 克隆原始对象 # 2. 保留扩展属性 # 3. 删除旧对象 # 4. 在新图层创建新对象 ``` ### 点坐标修改(SSObj_X, SSObj_Y, SSObj_Z) 修改坐标点需要指定点的索引: ```python # 修改第一个点的坐标 ssp.setSelGeoValue(0, "SSObj_X(0)", "123456.789") ssp.setSelGeoValue(0, "SSObj_Y(0)", "3456789.123") ssp.setSelGeoValue(0, "SSObj_Z(0)", "100.5") # 修改第二个点的坐标 ssp.setSelGeoValue(0, "SSObj_X(1)", "123500.000") ssp.setSelGeoValue(0, "SSObj_Y(1)", "3456800.000") ``` ### 点名称与类型修改(SSObj_PointName, SSObj_PointType) ```python # 修改点名称 ssp.setSelGeoValue(0, "SSObj_PointName(0)", "起点") ssp.setSelGeoValue(0, "SSObj_PointName(1)", "终点") # 修改点类型(需要指定点索引) ssp.setSelGeoValue(0, "SSObj_PointType(0)", "1") ``` Sources: [ObjBaseAttr.py](ObjBaseAttr.py#L495-L550) ## 颜色属性设置详解 SunvStation 支持三种颜色表示方式,系统会自动识别并转换: | 颜色表示方式 | 格式示例 | 说明 | |------------|---------|------| | **颜色号方式** | `COLORNO(1)` | 使用系统颜色索引,推荐方式 | | **RGB方式** | `RGB(255,0,0)` | 直接指定红绿蓝分量 | | **颜色值方式** | `16711680` | 24位RGB颜色值(0x00FF0000 = 红) | ```python # 三种等价的红色设置方式 ssp.setSelGeoValue(0, "SSObj_Color", "COLORNO(1)") # 颜色号方式 ssp.setSelGeoValue(0, "SSObj_Color", "RGB(255,0,0)") # RGB方式 ssp.setSelGeoValue(0, "SSObj_Color", "16711680") # 颜色值方式(红色) ``` Sources: [ObjBaseAttr.py](ObjBaseAttr.py#L413-L419) ## 完整示例:批量更新道路属性 下面的示例展示了完整的属性修改工作流程:选择所有道路对象,更新其颜色、线宽和扩展属性,然后保存到数据库。 ```python # 1. 清除并初始化选择集 ssp.clearSelection() ssp.clearSelectCondition() # 2. 设置选择条件:选择编码为 200 的道路对象 ssp.setSelectCondition("SSObj_Code", "==", "200") ssp.selectFilter() geo_count = ssp.getSelGeoCount() print(f"选中对象数量: {geo_count}") if geo_count > 0: # 3. 批量修改基本属性 ssp.setSelGeoValue(-1, "SSObj_Color", "COLORNO(5)") # 统一颜色 ssp.setSelGeoValue(-1, "SSObj_LineWidth", "4") # 统一线宽 ssp.setSelGeoValue(-1, "SSObj_DataMark", "已更新") # 数据标记 # 4. 批量修改扩展属性 ssp.setSelGeoValue(-1, "[路面宽度]", "12.5") ssp.setSelGeoValue(-1, "[铺装类型]", "沥青混凝土") ssp.setSelGeoValue(-1, "[维护日期]", "2024-01-10") # 5. 将所有修改后的对象添加到保存列表 for i in range(geo_count): ssp.addSelGeoToSaveGeoList(i) # 6. 保存到数据库并刷新显示 ssp.saveBufferObjToDatabase() ssp.updateRequest() print("属性更新完成!") else: print("未找到符合条件的对象") ``` Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L50-L95) ## 完整示例:创建并设置新对象 ```python # 1. 创建编码为 101 的建筑物对象 obj, geo = ssp.createNewObjByCode(101) # 2. 设置基本属性 ssp.setNewObjValue("SSObj_Name", "新建建筑A栋") ssp.setNewObjValue("SSObj_Color", "COLORNO(3)") ssp.setNewObjValue("SSObj_LayerName", "建筑物") # 3. 添加坐标点 ssp.addNewObjPoint(123456.789, 3456789.123, 50.0, 0, "") ssp.addNewObjPoint(123500.000, 3456800.000, 50.0, 0, "") ssp.addNewObjPoint(123500.000, 3456700.000, 50.0, 0, "") ssp.addNewObjPoint(123456.789, 3456789.123, 50.0, 0, "") # 4. 设置扩展属性 ssp.setNewObjValue("[建筑高度]", "45.5") ssp.setNewObjValue("[建筑面积]", "3200") ssp.setNewObjValue("[建筑功能]", "办公") # 5. 添加到保存列表并持久化 ssp.addNewObjToSaveObjList() ssp.saveBufferObjToDatabase() ssp.updateRequest() print("新对象创建完成并已保存!") ``` Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L106-L411) ## 注意事项与最佳实践 ### 属性修改注意事项 1. **数据类型匹配**:确保属性值的数据类型与属性定义一致,数值属性使用数字字符串,文本属性使用字符串 2. **编码和图层**:修改 `SSObj_Code` 和 `SSObj_LayerName` 会触发对象重建,确保目标编码和图层存在 3. **批量操作**:修改大量对象时,使用 `-1` 索引进行批量操作可以提高性能 4. **扩展属性**:使用逗号分隔可以一次设置多个扩展属性,但确保属性数量和值数量匹配 ### 保存机制 **重要**:属性修改后必须显式调用保存方法,否则修改仅在内存中生效,不会持久化到数据库: ```python # 单个对象保存 ssp.addSelGeoToSaveGeoList(index) # index 为具体索引或 -1(全部) ssp.saveBufferObjToDatabase() # 新对象保存 ssp.addNewObjToSaveObjList() ssp.saveBufferObjToDatabase() ``` ### 错误处理 属性修改操作通常会静默失败,建议在关键操作后检查结果: ```python # 修改属性前检查对象是否存在 if ssp.getSelGeoCount() > 0: # 执行修改 ssp.setSelGeoValue(0, "SSObj_Color", "255") ssp.addSelGeoToSaveGeoList(0) else: print("选择集为空,无法执行修改") ``` ## 进阶操作:通过对象ID直接修改属性 对于已知对象 ID 的情况,可以通过 `getObjectAttr()` 和 `setSelGeoValue()` 组合使用: ```python # 通过对象 ID 直接获取属性 obj_id = 12345 attr_value = ssp.getObjectAttr(obj_id, "SSObj_Name") print(f"当前名称: {attr_value}") # 先选择该对象,再修改属性 ssp.clearSelection() ssp.setSelectCondition("SSObj_ID", "==", str(obj_id)) ssp.selectFilter() if ssp.getSelGeoCount() > 0: ssp.setSelGeoValue(0, "SSObj_Name", "修改后的名称") ssp.addSelGeoToSaveGeoList(0) ssp.saveBufferObjToDatabase() ``` Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L570-L600) ## 下一步学习 掌握属性修改后,建议继续学习以下相关主题: - **[地物基本属性详解](17-di-wu-ji-ben-shu-xing-xiang-jie)** - 深入了解每种基本属性的含义和用途 - **[扩展属性与自定义属性](18-kuo-zhan-shu-xing-yu-zi-ding-yi-shu-xing)** - 学习如何创建和管理扩展属性系统 - **[批量保存到数据库](24-pi-liang-bao-cun-dao-shu-ju-ku)** - 了解批量保存的内部机制和性能优化 - **[撤销标记管理](25-che-xiao-biao-ji-guan-li)** - 学习如何实现属性修改的撤销功能