Files
sunvpy-docs/docs/content/42-di-li-dui-xiang-lei-xing-ding-yi.md
2026-04-10 13:47:53 +08:00

22 KiB
Raw Permalink Blame History

地理对象类型定义是 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 转换为 MarkNoteList
  • castToGeoBaseList(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(对象 IDSSObj_Name(对象名称)
  • 分组:SSObj_GroupID(分组 IDSSObj_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 系统地理数据模型的基础,掌握这些概念对于开发高效的地理数据处理脚本至关重要。以下是本页面介绍的核心要点和实际开发中的最佳实践建议。

核心概念回顾

  1. 四种基础类型0、线1、面2、注记3每种类型对应特定的几何类和应用场景
  2. 继承架构:所有地理对象继承自 GeoBase 基类,共享通用属性和方法,同时提供类型特定的功能
  3. 容器分离GeoObject 作为容器管理数据和事务,几何对象负责几何计算和属性存储
  4. 类型识别:通过 getObjectType() 方法进行运行时类型判断,使用类型转换函数进行安全类型转换
  5. 属性系统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)  # 注记对象

后续学习建议

完成本页面学习后,建议继续深入以下相关主题: