地理对象类型定义是 SunvStation 系统中地理数据模型的核心组成部分。系统采用面向对象的设计模式,通过类继承体系和类型标识来管理不同形态的地理要素。理解这些类型定义及其相互关系,是进行地理数据处理、空间分析和可视化的基础。 本页面将系统性地介绍地理对象的类型体系、类结构、属性机制以及相关的类型识别和转换方法。建议在学习本页面之前,先了解 [SunvStation 系统架构](6-sunvstation-xi-tong-jia-gou) 和 [C++ 扩展模块与 Python 接口](10-c-kuo-zhan-mo-kuai-yu-python-jie-kou)。完成本页面学习后,可以继续学习 [创建默认地物对象](19-chuang-jian-mo-ren-di-wu-dui-xiang) 和 [地物基本属性详解](17-di-wu-ji-ben-shu-xing-xiang-jie)。 Sources: [PySSCore.py](PySSCore.py#L2600-L3200) ## 地理对象类型体系 SunvStation 系统定义了四种基础地理对象类型,每种类型对应不同的几何形态和应用场景。这些类型通过整数标识符进行区分,并与特定的几何类相对应。类型体系的设计遵循简单、明确、可扩展的原则,为地理数据的存储、查询和展示提供了统一的抽象层次。 ### 四种基础类型 | 类型标识 | 类型名称 | 几何类 | 典型应用场景 | 几何特征 | |---------|---------|--------|------------|---------| | 0 | 点对象 | PointObject | 控制点、界碑、建筑物中心点、测量点 | 零维几何,由单个坐标点定义 | | 1 | 线对象 | LineObject | 道路、管线、河流中心线、边界线 | 一维几何,由有序坐标点序列定义 | | 2 | 面对象 | AreaObject | 建筑物轮廓、湖泊、行政区划、地块 | 二维几何,由闭合坐标环定义 | | 3 | 注记对象 | MarkNote | 文字标注、地名说明、图例说明 | 特殊对象,结合文本与定位点 | ### 类型标识的作用 类型标识是系统内部识别对象类型的核心机制,其作用体现在以下几个方面: - **对象创建**:`createDefaultGeoBase(obj_type, dataset)` 方法通过类型标识决定创建具体的几何对象实例 - **类型判断**:`getObjectType()` 方法返回当前对象的类型标识,用于运行时类型识别 - **数据查询**:查询条件中可以通过类型标识过滤特定类型的地理对象 - **符号化渲染**:系统根据对象类型应用不同的符号化规则和渲染策略 Sources: [ssprocess_mixins/geo_edit_mixin.py](ssprocess_mixins/geo_edit_mixin.py#L93-L120) ## 类继承架构 地理对象类型体系基于面向对象的继承架构设计,通过基类和派生类的层次结构实现代码复用和多态性。理解这个架构有助于掌握各类地理对象的共性和特性,以及如何正确使用它们提供的方法和属性。 ### 继承层次结构 ```mermaid classDiagram GeoBase <|-- PointObject GeoBase <|-- LineObject GeoBase <|-- AreaObject GeoBase <|-- MarkNote class GeoBase { <<抽象基类>> +getId() int +setId(id) +getCode() int +setCode(code) +getColor() int +setColor(color) +getObjectType() int +getArea(haveSign) float +getPerimeter() float +setStatus(flag, status) +getStatus(status) bool } class PointObject { +getObjectType() int +getScaleX/Y/Z() float +setScaleX/Y/Z(scale) +rotate(point, vct) } class LineObject { +getObjectType() int +getPerimeter() float +getArea(haveSign) float +setLineThickness(thickness) +getLineThickness() float } class AreaObject { +getObjectType() int +getArea(haveSign) float +getPerimeter() float +getLoops() PointArray } class MarkNote { +getObjectType() int +setNote(note) +getNote() string +setFontHeight(height) +setFontWidth(width) +setAlignment(alignment) +setNoteClass(number) } ``` ### GeoBase 基类 `GeoBase` 是所有地理对象的抽象基类,定义了所有地理对象共有的属性和方法。基类的设计遵循"提取共性、隔离差异"的原则,将通用的功能集中在基类中实现,而将特定类型的几何操作委托给派生类。 **核心属性**: - **ID**:对象的唯一标识符(`getId()`/`setId()`) - **Code**:地物编码,关联符号定义(`getCode()`/`setCode()`) - **Color**:颜色值(`getColor()`/`setColor()`) - **LineType/LineWidth**:线型和线宽(`getLineType()`/`setLineType()`, `getLineWidth()`/`setLineWidth()`) - **Status**:对象状态标志(`setStatus()`/`getStatus()`) **核心方法**: - `getObjectType()`:获取对象类型标识(返回 0、1、2 或 3) - `getArea()`:计算面积(仅 AreaObject 和 LineObject 返回有效值) - `getPerimeter()`:计算周长(仅 AreaObject 和 LineObject 返回有效值) Sources: [PySSCore.py](PySSCore.py#L2000-L2800) ### 派生类特性 各派生类在继承基类功能的基础上,针对特定的几何类型提供了专门的属性和方法: **PointObject(点对象)** - 支持三维缩放变换(`setScaleX/Y/Z()`) - 提供旋转功能(`rotate()`) - 主要用于表示离散的地理位置或标记点 **LineObject(线对象)** - 继承面积计算方法(可用于计算线性要素的缓冲区面积) - 提供线厚度设置(`setLineThickness()`) - 由一系列有序坐标点构成,表示连续的地理要素 **AreaObject(面对象)** - 提供面积和周长的精确计算 - 支持多环结构(通过 `getLoops()` 获取) - 由闭合坐标环构成,表示有界区域 **MarkNote(注记对象)** - 继承自 GeoBase 但具有独特的属性体系 - 提供文本内容管理(`setNote()`/`getNote()`) - 支持字体属性设置(高度、宽度、对齐方式等) - 提供注记类关联(`setNoteClass()`) Sources: [PySSCore.py](PySSCore.py#L2800-L3000) ## GeoObject 容器对象 `GeoObject` 是地理对象的容器类,与具体的几何对象(PointObject、LineObject、AreaObject、MarkNote)协同工作,形成完整的地物对象体系。理解容器对象与几何对象的关系,对于正确创建、管理和操作地物对象至关重要。 ### 容器与几何对象的分离设计 SunvStation 系统采用容器对象与几何对象分离的设计模式,每个地理地物由两个核心组件构成: - **GeoObject 容器**:负责数据集关联、对象 ID 管理、属性存储和事务控制 - **几何对象(GeoBase 派生类)**:负责几何数据存储、空间计算和图形属性 这种分离设计的优势在于: - **关注点分离**:数据管理与几何计算职责清晰 - **灵活组合**:同一容器可以承载不同类型的几何对象 - **事务支持**:容器提供统一的事务管理接口 ### GeoObject 核心功能 ```mermaid flowchart LR subgraph GeoObject容器 A[数据集引用] B[唯一ID管理] C[属性存储] D[事务控制] end subgraph 几何对象 E[PointObject] F[LineObject] G[AreaObject] H[MarkNote] end A --> E A --> F A --> G A --> H C --> E C --> F C --> G C --> H ``` **数据集关联**:GeoObject 维护到数据集的引用,确保对象与数据库表的正确映射 **唯一 ID 管理**:通过 `generateUniqueId()` 生成全局唯一的对象标识符 **属性管理**:提供属性和图形信息的统一访问接口(`getAttribute()`/`getGraphicInfo()`) **几何对象绑定**:通过 `setGeoBase()`/`getGeoBase()` 方法管理几何对象的关联 Sources: [PySSCore.py](PySSCore.py#L900-L1000) ## 类型识别与转换机制 系统提供了完整的类型识别和转换机制,支持运行时类型判断和安全地类型转换。这些机制在处理异构对象集合、实现多态操作和类型安全访问时发挥关键作用。 ### getObjectType() 类型识别方法 所有地理对象都实现了 `getObjectType()` 方法,该方法返回对象的类型标识符。这是运行时类型判断的主要方式: ```python # 示例:判断对象类型 geo = getGeoObject() # 获取一个地理对象 obj_type = geo.getObjectType() if obj_type == 0: print("这是一个点对象") elif obj_type == 1: print("这是一个线对象") elif obj_type == 2: print("这是一个面对象") elif obj_type == 3: print("这是一个注记对象") ``` ### 类型转换函数 系统提供了一组类型转换函数,用于在 `GeoBase` 基类指针和具体类型指针之间进行安全转换: | 转换函数 | 目标类型 | 转换条件 | 失败返回 | |---------|---------|---------|---------| | `castToPointObject(geo)` | PointObject | 对象类型为 0 | None | | `castToLineObject(geo)` | LineObject | 对象类型为 1 | None | | `castToAreaObject(geo)` | AreaObject | 对象类型为 2 | None | | `castToMarkNote(geo)` | MarkNote | 对象类型为 3 | None | **转换示例**: ```python # 安全的类型转换 from sunvpy.PySSCore import castToLineObject, castToMarkNote def processObject(geo): obj_type = geo.getObjectType() if obj_type == 1: # 转换为线对象并访问线特有方法 line = castToLineObject(geo) if line is not None: thickness = line.getLineThickness() print(f"线对象厚度: {thickness}") elif obj_type == 3: # 转换为注记对象并访问注记特有方法 note = castToMarkNote(geo) if note is not None: text = note.getNote() print(f"注记内容: {text}") ``` ### 类型转换的工作原理 类型转换函数在 C++ 层面实现,采用动态类型检查机制: ```mermaid sequenceDiagram participant Py as Python代码 participant SWIG as SWIG接口 participant Cpp as C++实现 Py->>SWIG: castToLineObject(geo) SWIG->>Cpp: 调用转换函数 Cpp->>Cpp: 检查对象类型 alt 类型匹配 (getObjectType() == 1) Cpp->>Cpp: 执行类型转换 Cpp->>SWIG: 返回 LineObject 指针 SWIG->>Py: 返回 Python 对象 else 类型不匹配 Cpp->>SWIG: 返回 NULL SWIG->>Py: 返回 None end ``` Sources: [PySSCore.py](PySSCore.py#L3000-L3100) ## 地理对象列表类型 为了高效管理大量同类型地理对象,系统为每种地理对象类型提供了专用的列表容器。这些列表容器继承自标准模板库的 vector 容器,提供了丰富的集合操作接口。 ### 列表类型体系 | 列表类型 | 元素类型 | 典型用途 | 特殊方法 | |---------|---------|---------|---------| | `PointObjectList` | PointObject | 控制点集合、测量点集 | 通用列表方法 | | `LineObjectList` | LineObject | 道路网络、管线系统 | 通用列表方法 | | `AreaObjectList` | AreaObject | 建筑物群、地块集合 | 通用列表方法 | | `MarkNoteList` | MarkNote | 标注集合、图例列表 | 通用列表方法 | | `GeoBaseList` | GeoBase | 混合类型对象集合 | 通用列表方法 | ### 列表通用方法 所有列表容器都提供以下核心方法: **基本操作**: - `size()`:获取元素数量 - `empty()`:判断是否为空 - `clear()`:清空列表 - `append(x)`:在尾部添加元素 - `pop()`:移除并返回尾部元素 **访问操作**: - `front()`:访问首元素 - `back()`:访问尾元素 - `__getitem__(index)`:索引访问(支持负索引) - `iterator()`:获取迭代器(支持 Python 迭代协议) **修改操作**: - `insert(index, x)`:在指定位置插入元素 - `erase(index)`:删除指定位置元素 - `resize(n)`:调整列表大小 **列表操作**: - `swap(other)`:交换两个列表内容 - `assign(n, x)`:用 n 个 x 填充列表 ### 类型转换列表 系统还提供了列表类型的转换函数,用于在不同列表类型之间进行转换: - `castToMarkNoteList(geos)`:将 `GeoBaseList` 转换为 `MarkNoteList` - `castToGeoBaseList(geos)`:将 `MarkNoteList` 转换为 `GeoBaseList` 这些转换函数在处理混合类型对象集合时非常有用,例如在选择集操作中。 **示例**: ```python from sunvpy.PySSCore import GeoBaseList, MarkNoteList, castToMarkNoteList # 创建通用列表 geo_list = GeoBaseList() # 添加不同类型的对象 geo_list.append(point_obj) # 添加点对象 geo_list.append(line_obj) # 添加线对象 geo_list.append(note_obj) # 添加注记对象 # 转换为注记列表(仅提取注记对象) note_list = castToMarkNoteList(geo_list) print(f"注记对象数量: {note_list.size()}") # 遍历注记列表 for i in range(note_list.size()): note = note_list[i] print(f"注记内容: {note.getNote()}") ``` Sources: [PySSCore.py](PySSCore.py#L3100-L3400) ## 属性系统与地物基本属性 地理对象的属性系统通过 `ObjBaseAttr` 类进行统一管理,该类定义了所有地物对象支持的基本属性名称和索引。属性系统为地物对象的元数据管理提供了标准化的接口,确保了属性访问的一致性和可扩展性。 ### ObjBaseAttr 类结构 `ObjBaseAttr` 类采用注册表模式,维护属性名称到索引的映射关系: ```python class ObjBaseAttr: def __init__(self): self.valueNames = [] # 属性名称列表(自动排序) # 注册所有属性名(去前缀 SSObj_,按升序排列) attr_names = [ # 点属性 "SSObj_PointName", "SSObj_PointCount", "SSObj_PointType", "SSObj_X", "SSObj_Y", "SSObj_Z", # 通用属性 "SSObj_Code", "SSObj_Byname", "SSObj_LayerName", "SSObj_Color", "SSObj_LineType", "SSObj_LineWidth", "SSObj_ID", "SSObj_GroupID", "SSObj_Name", "SSObj_Type", "SSObj_Status", "SSObj_DataMark", "SSObj_RelationID", "SSObj_CreateTime", "SSObj_ModifyTime", # ... 更多属性 ] ``` ### 属性分类体系 属性按照功能和用途分为多个类别,每类属性对应不同的应用场景和操作需求: **几何属性**: - 点坐标:`SSObj_X`, `SSObj_Y`, `SSObj_Z` - 点信息:`SSObj_PointName`, `SSObj_PointCount`, `SSObj_PointType` - 几何参量:`SSObj_Area`, `SSObj_Length`, `SSObj_3DLength` - 边界框:`SSObj_minX`, `SSObj_minY`, `SSObj_maxX`, `SSObj_maxY` **显示属性**: - 颜色:`SSObj_Color`(前景色)、`SSObj_Area`(填充色) - 线型:`SSObj_LineType`(线型样式)、`SSObj_LineWidth`(线宽) - 变换:`SSObj_Angle`(旋转角度)、`SSObj_ScaleX/Y/XY`(缩放) **数据属性**: - 标识:`SSObj_Code`(地物编码)、`SSObj_ID`(对象 ID)、`SSObj_Name`(对象名称) - 分组:`SSObj_GroupID`(分组 ID)、`SSObj_LayerName`(图层名称) - 时间:`SSObj_CreateTime`(创建时间)、`SSObj_ModifyTime`(修改时间) **注记属性**(仅 MarkNote 对象): - 字体:`SSObj_FontName`, `SSObj_FontHeight`, `SSObj_FontWidth` - 对齐:`SSObj_FontAlignment`, `SSObj_FontPosType` - 方向:`SSObj_FontDirection`, `SSObj_FontWordAngle`, `SSObj_FontStringAngle` - 样式:`SSObj_FontWeight`, `SSObj_FontItalicAngle`, `SSObj_FontUnderLine` ### 属性索引机制 `ObjBaseAttr` 提供了属性名称到索引的映射功能,支持高效的属性访问: **核心方法**: - `get_value_index(field: str) -> int`:根据属性名获取索引(去除 SSObj_ 前缀) - `get_value_index_param(field: str) -> tuple`:解析带参数的属性名,返回索引和参数 - `getGeoValue(map, geo, field) -> str`:获取地理对象的属性值 **索引规则**: - 属性名自动去除 `SSObj_` 前缀并转换为小写 - 支持带参数的属性名(如 `SSObj_Code(param)`) - 属性名列表自动按升序排列,确保索引稳定性 **使用示例**: ```python from sunvpy.ObjBaseAttr import ObjBaseAttr attr_mgr = ObjBaseAttr() # 获取属性索引 code_idx = attr_mgr.get_value_index("SSObj_Code") name_idx = attr_mgr.get_value_index("SSObj_Name") color_idx = attr_mgr.get_value_index("color") # 不需要前缀 print(f"Code 索引: {code_idx}") print(f"Name 索引: {name_idx}") print(f"Color 索引: {color_idx}") # 获取对象属性值 value = attr_mgr.getGeoValue(map, geo, "SSObj_Area") print(f"面积: {value}") ``` Sources: [ObjBaseAttr.py](ObjBaseAttr.py#L1-L200) ## 对象类型与属性的关系 不同类型的地理对象在属性支持上存在差异,理解这些差异有助于正确地设置和访问对象属性。某些属性是所有类型通用的,而某些属性仅对特定类型有效。 ### 通用属性 vs 特定类型属性 **所有地理对象共有的属性**: - `SSObj_Code`:地物编码 - `SSObj_ID`:对象唯一标识 - `SSObj_Name`:对象名称 - `SSObj_Color`:颜色 - `SSObj_LineType`:线型 - `SSObj_LineWidth`:线宽 - `SSObj_Status`:对象状态 - `SSObj_CreateTime` / `SSObj_ModifyTime`:时间戳 **仅 PointObject 支持的属性**: - 点坐标属性:`SSObj_X`, `SSObj_Y`, `SSObj_Z` - 点信息:`SSObj_PointName`, `SSObj_PointCount`, `SSObj_PointType` **仅 LineObject 和 AreaObject 支持的属性**: - 几何参量:`SSObj_Length`, `SSObj_3DLength`, `SSObj_Area` - 边界框:`SSObj_minX`, `SSObj_minY`, `SSObj_maxX`, `SSObj_maxY` **仅 AreaObject 支持的属性**: - 椭球面积:`SSObj_EllipsoidArea1`, `SSObj_EllipsoidArea2` - 面积标注:`SSObj_DrawAreaLabelStatus`, `SSObj_AreaLabelX`, `SSObj_AreaLabelY` **仅 MarkNote 支持的属性**: - 所有以 `SSObj_Font` 开头的字体相关属性 - `SSObj_FontClass`:注记类 - `SSObj_FontString`:注记文本内容 ### 属性有效性判断 系统提供了多种方式来判断属性的有效性: **基于对象类型的判断**: ```python def isValidAttribute(geo, attr_name): """判断属性是否对当前对象类型有效""" obj_type = geo.getObjectType() attr_name_lower = attr_name.lower().replace('ssobj_', '') # 点对象专用属性 if attr_name_lower in ['x', 'y', 'z', 'pointname', 'pointcount', 'pointtype']: return obj_type == 0 # 线对象和面对象的几何属性 if attr_name_lower in ['length', '3dlength']: return obj_type in [1, 2] # 面对象专用属性 if attr_name_lower in ['ellipsoidarea1', 'ellipsoidarea2', 'arealabelx', 'arealabely']: return obj_type == 2 # 注记对象专用属性 if attr_name_lower.startswith('font'): return obj_type == 3 # 通用属性 return True ``` **基于返回值的判断**: ```python # 几何属性仅在特定对象类型返回有效值 area = geo.getArea() if area > 0.0: print(f"对象面积为: {area}") # 仅 AreaObject 和 LineObject 有有效面积 perimeter = geo.getPerimeter() if perimeter > 0.0: print(f"对象周长为: {perimeter}") # 仅 AreaObject 和 LineObject 有有效周长 ``` Sources: [PySSCore.py](PySSCore.py#L2600-L2800) ## 总结与最佳实践 地理对象类型定义是 SunvStation 系统地理数据模型的基础,掌握这些概念对于开发高效的地理数据处理脚本至关重要。以下是本页面介绍的核心要点和实际开发中的最佳实践建议。 ### 核心概念回顾 1. **四种基础类型**:点(0)、线(1)、面(2)、注记(3),每种类型对应特定的几何类和应用场景 2. **继承架构**:所有地理对象继承自 `GeoBase` 基类,共享通用属性和方法,同时提供类型特定的功能 3. **容器分离**:`GeoObject` 作为容器管理数据和事务,几何对象负责几何计算和属性存储 4. **类型识别**:通过 `getObjectType()` 方法进行运行时类型判断,使用类型转换函数进行安全类型转换 5. **属性系统**:`ObjBaseAttr` 统一管理所有地物属性,支持标准化的属性访问机制 ### 类型识别与处理最佳实践 **使用 `getObjectType()` 进行类型判断**: ```python # 推荐:显式类型检查 def processGeoObject(geo): obj_type = geo.getObjectType() if obj_type == 0: processPoint(geo) elif obj_type == 1: processLine(geo) elif obj_type == 2: processArea(geo) elif obj_type == 3: processNote(geo) else: print(f"未知对象类型: {obj_type}") ``` **使用类型转换函数安全访问类型特定方法**: ```python # 推荐:安全转换后访问 def printObjectDetails(geo): if geo.getObjectType() == 1: line = castToLineObject(geo) if line is not None: print(f"线厚度: {line.getLineThickness()}") if geo.getObjectType() == 3: note = castToMarkNote(geo) if note is not None: print(f"注记: {note.getNote()}") ``` ### 属性访问最佳实践 **使用 `ObjBaseAttr` 统一管理属性索引**: ```python # 推荐:使用属性管理器 attr_mgr = ObjBaseAttr() code_idx = attr_mgr.get_value_index("Code") # 访问属性 code_value = geo.getAttribute(code_idx) ``` **根据对象类型选择有效属性**: ```python # 推荐:判断属性有效性后再访问 def safeGetArea(geo): if geo.getObjectType() in [1, 2]: # 线对象和面对象 area = geo.getArea() return area if area > 0 else 0.0 else: return 0.0 # 点对象和注记对象无面积 ``` ### 创建对象时的类型选择 **根据应用场景选择合适的对象类型**: ```python # 推荐:明确类型选择 def createFeature(feature_type, coordinates): if feature_type == 'control_point': obj, geo = createDefaultGeoBase(0, dataset) # 点对象 elif feature_type == 'road': obj, geo = createDefaultGeoBase(1, dataset) # 线对象 elif feature_type == 'building': obj, geo = createDefaultGeoBase(2, dataset) # 面对象 elif feature_type == 'label': obj, geo = createDefaultGeoBase(3, dataset) # 注记对象 ``` ### 后续学习建议 完成本页面学习后,建议继续深入以下相关主题: - **对象创建**:学习 [创建默认地物对象](19-chuang-jian-mo-ren-di-wu-dui-xiang) 和 [通过编码创建对象](20-tong-guo-bian-ma-chuang-jian-dui-xiang) - **属性管理**:学习 [地物基本属性详解](17-di-wu-ji-ben-shu-xing-xiang-jie) 和 [获取地物属性值](15-huo-qu-di-wu-shu-xing-zhi) - **类型转换**:学习 [SSProcessManager 完整 API](40-ssprocessmanager-wan-zheng-api) 中的类型相关方法 - **高级操作**:学习 [坐标转换工具](44-zuo-biao-zhuan-huan-gong-ju) 中的几何转换功能