22 KiB
地理对象类型定义是 SunvStation 系统中地理数据模型的核心组成部分。系统采用面向对象的设计模式,通过类继承体系和类型标识来管理不同形态的地理要素。理解这些类型定义及其相互关系,是进行地理数据处理、空间分析和可视化的基础。
本页面将系统性地介绍地理对象的类型体系、类结构、属性机制以及相关的类型识别和转换方法。建议在学习本页面之前,先了解 SunvStation 系统架构 和 C++ 扩展模块与 Python 接口。完成本页面学习后,可以继续学习 创建默认地物对象 和 地物基本属性详解。
Sources: PySSCore.py
地理对象类型体系
SunvStation 系统定义了四种基础地理对象类型,每种类型对应不同的几何形态和应用场景。这些类型通过整数标识符进行区分,并与特定的几何类相对应。类型体系的设计遵循简单、明确、可扩展的原则,为地理数据的存储、查询和展示提供了统一的抽象层次。
四种基础类型
| 类型标识 | 类型名称 | 几何类 | 典型应用场景 | 几何特征 |
|---|---|---|---|---|
| 0 | 点对象 | PointObject | 控制点、界碑、建筑物中心点、测量点 | 零维几何,由单个坐标点定义 |
| 1 | 线对象 | LineObject | 道路、管线、河流中心线、边界线 | 一维几何,由有序坐标点序列定义 |
| 2 | 面对象 | AreaObject | 建筑物轮廓、湖泊、行政区划、地块 | 二维几何,由闭合坐标环定义 |
| 3 | 注记对象 | MarkNote | 文字标注、地名说明、图例说明 | 特殊对象,结合文本与定位点 |
类型标识的作用
类型标识是系统内部识别对象类型的核心机制,其作用体现在以下几个方面:
- 对象创建:
createDefaultGeoBase(obj_type, dataset)方法通过类型标识决定创建具体的几何对象实例 - 类型判断:
getObjectType()方法返回当前对象的类型标识,用于运行时类型识别 - 数据查询:查询条件中可以通过类型标识过滤特定类型的地理对象
- 符号化渲染:系统根据对象类型应用不同的符号化规则和渲染策略
Sources: ssprocess_mixins/geo_edit_mixin.py
类继承架构
地理对象类型体系基于面向对象的继承架构设计,通过基类和派生类的层次结构实现代码复用和多态性。理解这个架构有助于掌握各类地理对象的共性和特性,以及如何正确使用它们提供的方法和属性。
继承层次结构
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
派生类特性
各派生类在继承基类功能的基础上,针对特定的几何类型提供了专门的属性和方法:
PointObject(点对象)
- 支持三维缩放变换(
setScaleX/Y/Z()) - 提供旋转功能(
rotate()) - 主要用于表示离散的地理位置或标记点
LineObject(线对象)
- 继承面积计算方法(可用于计算线性要素的缓冲区面积)
- 提供线厚度设置(
setLineThickness()) - 由一系列有序坐标点构成,表示连续的地理要素
AreaObject(面对象)
- 提供面积和周长的精确计算
- 支持多环结构(通过
getLoops()获取) - 由闭合坐标环构成,表示有界区域
MarkNote(注记对象)
- 继承自 GeoBase 但具有独特的属性体系
- 提供文本内容管理(
setNote()/getNote()) - 支持字体属性设置(高度、宽度、对齐方式等)
- 提供注记类关联(
setNoteClass())
Sources: PySSCore.py
GeoObject 容器对象
GeoObject 是地理对象的容器类,与具体的几何对象(PointObject、LineObject、AreaObject、MarkNote)协同工作,形成完整的地物对象体系。理解容器对象与几何对象的关系,对于正确创建、管理和操作地物对象至关重要。
容器与几何对象的分离设计
SunvStation 系统采用容器对象与几何对象分离的设计模式,每个地理地物由两个核心组件构成:
- GeoObject 容器:负责数据集关联、对象 ID 管理、属性存储和事务控制
- 几何对象(GeoBase 派生类):负责几何数据存储、空间计算和图形属性
这种分离设计的优势在于:
- 关注点分离:数据管理与几何计算职责清晰
- 灵活组合:同一容器可以承载不同类型的几何对象
- 事务支持:容器提供统一的事务管理接口
GeoObject 核心功能
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
类型识别与转换机制
系统提供了完整的类型识别和转换机制,支持运行时类型判断和安全地类型转换。这些机制在处理异构对象集合、实现多态操作和类型安全访问时发挥关键作用。
getObjectType() 类型识别方法
所有地理对象都实现了 getObjectType() 方法,该方法返回对象的类型标识符。这是运行时类型判断的主要方式:
# 示例:判断对象类型
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 |
转换示例:
# 安全的类型转换
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++ 层面实现,采用动态类型检查机制:
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
地理对象列表类型
为了高效管理大量同类型地理对象,系统为每种地理对象类型提供了专用的列表容器。这些列表容器继承自标准模板库的 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转换为MarkNoteListcastToGeoBaseList(geos):将MarkNoteList转换为GeoBaseList
这些转换函数在处理混合类型对象集合时非常有用,例如在选择集操作中。
示例:
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
属性系统与地物基本属性
地理对象的属性系统通过 ObjBaseAttr 类进行统一管理,该类定义了所有地物对象支持的基本属性名称和索引。属性系统为地物对象的元数据管理提供了标准化的接口,确保了属性访问的一致性和可扩展性。
ObjBaseAttr 类结构
ObjBaseAttr 类采用注册表模式,维护属性名称到索引的映射关系:
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)) - 属性名列表自动按升序排列,确保索引稳定性
使用示例:
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
对象类型与属性的关系
不同类型的地理对象在属性支持上存在差异,理解这些差异有助于正确地设置和访问对象属性。某些属性是所有类型通用的,而某些属性仅对特定类型有效。
通用属性 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:注记文本内容
属性有效性判断
系统提供了多种方式来判断属性的有效性:
基于对象类型的判断:
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
基于返回值的判断:
# 几何属性仅在特定对象类型返回有效值
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
总结与最佳实践
地理对象类型定义是 SunvStation 系统地理数据模型的基础,掌握这些概念对于开发高效的地理数据处理脚本至关重要。以下是本页面介绍的核心要点和实际开发中的最佳实践建议。
核心概念回顾
- 四种基础类型:点(0)、线(1)、面(2)、注记(3),每种类型对应特定的几何类和应用场景
- 继承架构:所有地理对象继承自
GeoBase基类,共享通用属性和方法,同时提供类型特定的功能 - 容器分离:
GeoObject作为容器管理数据和事务,几何对象负责几何计算和属性存储 - 类型识别:通过
getObjectType()方法进行运行时类型判断,使用类型转换函数进行安全类型转换 - 属性系统:
ObjBaseAttr统一管理所有地物属性,支持标准化的属性访问机制
类型识别与处理最佳实践
使用 getObjectType() 进行类型判断:
# 推荐:显式类型检查
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}")
使用类型转换函数安全访问类型特定方法:
# 推荐:安全转换后访问
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 统一管理属性索引:
# 推荐:使用属性管理器
attr_mgr = ObjBaseAttr()
code_idx = attr_mgr.get_value_index("Code")
# 访问属性
code_value = geo.getAttribute(code_idx)
根据对象类型选择有效属性:
# 推荐:判断属性有效性后再访问
def safeGetArea(geo):
if geo.getObjectType() in [1, 2]: # 线对象和面对象
area = geo.getArea()
return area if area > 0 else 0.0
else:
return 0.0 # 点对象和注记对象无面积
创建对象时的类型选择
根据应用场景选择合适的对象类型:
# 推荐:明确类型选择
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) # 注记对象
后续学习建议
完成本页面学习后,建议继续深入以下相关主题: