Files
sunvpy-docs/docs/content/42-di-li-dui-xiang-lei-xing-ding-yi.md

622 lines
22 KiB
Markdown
Raw Normal View History

2026-04-10 13:47:53 +08:00
地理对象类型定义是 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) 中的几何转换功能