本文档详细说明如何在 SunvStation Python 脚本中读取地物对象的属性值，涵盖基本属性、几何特性和扩展属性三种类型的属性访问方式。通过掌握这些方法，您可以高效地获取和分析地理对象的各类信息，为后续的数据处理、质量检查和统计分析奠定基础。

## 属性类型与命名规则

SunvStation 系统中，地物属性根据来源和用途分为三类，每类属性使用特定的前缀标识符进行区分。理解这些分类和命名规则是正确读取属性的前提。

```mermaid
flowchart TD
    A[地物属性] --> B[基本属性 SSObj_]
    A --> C[几何特性 #60; #62;]
    A --> D[扩展属性 #91; #93;]
    
    B --> B1[对象标识<br/>SSObj_ID, SSObj_Code]
    B --> B2[外观属性<br/>SSObj_Color, SSObj_LineType, SSObj_LineWidth]
    B --> B3[名称属性<br/>SSObj_Name, SSObj_Byname, SSObj_LayerName]
    B --> B4[几何参量<br/>SSObj_Area, SSObj_Length, SSObj_PointCount]
    B --> B5[时间属性<br/>SSObj_CreateTime, SSObj_ModifyTime]
    B --> B6[坐标信息<br/>SSObj_X, SSObj_Y, SSObj_Z, SSObj_PointName]
    B --> B7[注记属性<br/>SSObj_FontString, SSObj_FontHeight, SSObj_FontWidth]
    
    C --> C1[拓扑判断<br/>#60;Overlap#62;, #60;Close#62;]
    C --> C2[几何判断<br/>#60;Convex#62;, #60;SelfIntersect#62;]
    
    D --> D1[业务属性<br/>#91;JG#93;, #91;CS#93;, #91;建筑结构#93;]
    D --> D2[自定义属性<br/>#91;自定义字段1#93;, #91;自定义字段2#93;]
```

### 基本属性

以 `SSObj_` 开头，表示系统内置的地物基本属性，包括对象标识、外观、几何参量、时间戳等。这些属性直接存储在地理对象内部，访问效率最高。

| 属性名称 | 属性说明 | 数据类型 | 适用对象类型 |
|---------|---------|---------|------------|
| `SSObj_ID` | 对象唯一标识 | 整数 | 所有类型 |
| `SSObj_Code` | 地物编码 | 整数 | 所有类型 |
| `SSObj_LayerName` | 所在图层名 | 字符串 | 所有类型 |
| `SSObj_Type` | 对象类型 | 字符串（POINT/LINE/AREA/NOTE） | 所有类型 |
| `SSObj_Color` | 颜色值 | 整数 | 所有类型 |
| `SSObj_LineType` | 线型 | 整数 | LINE/AREA |
| `SSObj_LineWidth` | 线宽 | 整数 | LINE/AREA |
| `SSObj_Name` | 对象名称 | 字符串 | 所有类型 |
| `SSObj_Byname` | 对象别名 | 字符串 | 所有类型 |
| `SSObj_Angle` | 旋转角度 | 浮点数 | 所有类型 |
| `SSObj_ScaleX` | X 方向缩放 | 浮点数 | 所有类型 |
| `SSObj_ScaleY` | Y 方向缩放 | 浮点数 | 所有类型 |
| `SSObj_Area` | 面积 | 浮点数 | AREA |
| `SSObj_Length` | 周长/长度 | 浮点数 | LINE/AREA |
| `SSObj_3DLength` | 三维长度 | 浮点数 | LINE/AREA |
| `SSObj_PointCount` | 坐标点数量 | 整数 | POINT/LINE/AREA |
| `SSObj_X` | X 坐标 | 浮点数 | POINT/线对象指定点 |
| `SSObj_Y` | Y 坐标 | 浮点数 | POINT/线对象指定点 |
| `SSObj_Z` | Z 坐标 | 浮点数 | POINT/线对象指定点 |
| `SSObj_PointName` | 点名称 | 字符串 | POINT/线对象指定点 |
| `SSObj_PointType` | 点类型 | 整数 | POINT/线对象指定点 |
| `SSObj_CreateTime` | 创建时间 | 字符串（格式：YYYY-MM-DD HH:MM:SS） | 所有类型 |
| `SSObj_ModifyTime` | 修改时间 | 字符串（格式：YYYY-MM-DD HH:MM:SS） | 所有类型 |
| `SSObj_DataMark` | 数据标识 | 字符串 | 所有类型 |

**注记对象专用属性**：

| 属性名称 | 属性说明 | 数据类型 |
|---------|---------|---------|
| `SSObj_FontString` | 注记内容 | 字符串 |
| `SSObj_FontStringCount` | 注记字符数量 | 整数 |
| `SSObj_FontWidth` | 字宽 | 浮点数 |
| `SSObj_FontHeight` | 字高 | 浮点数 |
| `SSObj_FontName` | 字体名称 | 字符串 |
| `SSObj_FontClass` | 注记分类号 | 整数 |
| `SSObj_FontAlignment` | 对齐方式 | 整数 |
| `SSObj_FontPosType` | 位置类型 | 整数 |
| `SSObj_FontDirection` | 字方向 | 整数 |
| `SSObj_FontWordAngle` | 字角度 | 浮点数 |
| `SSObj_FontStringAngle` | 串角度 | 浮点数 |
| `SSObj_FontWeight` | 字重 | 整数 |
| `SSObj_FontItalicAngle` | 倾斜角度 | 浮点数 |
| `SSObj_FontDownAngle` | 下沉角度 | 浮点数 |
| `SSObj_FontUnderLine` | 下划线 | 整数（0/1） |
| `SSObj_FontInterval` | 字间隔 | 浮点数 |
| `SSObj_FontRealHeight` | 实际高度 | 浮点数 |
| `SSObj_FontRealLength` | 实际长度 | 浮点数 |

### 几何特性

用尖括号 `<>` 括住的属性，表示对象的几何拓扑特性，如是否重叠、是否封闭、是否凸多边形等。这些属性不是存储值，而是通过几何计算实时得到的判断结果。

| 属性名称 | 属性说明 | 返回值类型 |
|---------|---------|-----------|
| `<Overlap>` | 对象是否重叠 | 布尔值（True/False） |
| `<Close>` | 对象是否封闭 | 布尔值（True/False） |
| `<Convex>` | 对象是否为凸多边形 | 布尔值（True/False） |
| `<SelfIntersect>` | 对象是否自相交 | 布尔值（True/False） |

### 扩展属性

用方括号 `[]` 括住的属性，表示用户自定义的扩展属性，存储在对象的扩展属性表中。这些属性通常用于存储业务相关的自定义字段，如建筑结构、层数等。

| 属性名称 | 属性说明 | 数据类型 |
|---------|---------|---------|
| `[JG]` | 建筑结构 | 字符串 |
| `[CS]` | 建筑层数 | 字符串/整数 |
| `[自定义字段]` | 用户自定义字段 | 根据定义 |

Sources: [ObjBaseAttr.py](ObjBaseAttr.py#L7-L85)

## 核心 API 方法

获取地物属性值的核心方法是 `getSelGeoValue()` 和 `getSelNoteValue()`，这两个方法分别用于获取几何对象和注记对象的属性值。

### getSelGeoValue 方法

```python
def getSelGeoValue(self, index: int, fieldName: str) -> str
```

**参数说明**：

| 参数 | 类型 | 说明 |
|-----|------|------|
| index | int | 地物对象在选择集中的索引（从 0 开始） |
| fieldName | str | 属性名称，支持基本属性、几何特性和扩展属性 |

**返回值**：
- 类型：str
- 说明：指定地物对象的属性值，如果属性不存在或索引越界则返回空字符串

**使用示例**：

```python
from sunvpy import SSProcess

# 获取第 0 个对象的编码
code = SSProcess.getSelGeoValue(0, "SSObj_Code")
print(f"地物编码: {code}")

# 获取第 0 个对象的面积
area = SSProcess.getSelGeoValue(0, "SSObj_Area")
print(f"地物面积: {area}")

# 获取第 0 个对象的扩展属性 [JG]
structure = SSProcess.getSelGeoValue(0, "[JG]")
print(f"建筑结构: {structure}")
```

**内部实现逻辑**：

```mermaid
flowchart TD
    A[getSelGeoValue 调用] --> B{索引越界?}
    B -->|是| C[返回空字符串]
    B -->|否| D{字段名以 &#91 开头?}
    D -->|是| E[扩展属性路径]
    D -->|否| F[基本属性路径]
    
    E --> E1[map.getExtentAttr<br/>获取扩展属性列表]
    E1 --> E2{包含逗号?}
    E2 -->|是| E3[分割多个字段名]
    E2 -->|否| E4[查找单个字段]
    E3 --> E5[查找并拼接多个值]
    E4 --> E5
    E5 --> E6[返回属性值]
    
    F --> F1[objBaseAttr.getGeoValue<br/>处理基本属性]
    F1 --> F2{对象类型判断}
    F2 -->|注记对象| F3[读取注记专用属性]
    F2 -->|其他对象| F4[读取通用属性]
    F3 --> F5[返回属性值]
    F4 --> F5
```

Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L164-L202)

### getSelNoteValue 方法

```python
def getSelNoteValue(self, index: int, fieldName: str) -> str
```

**参数说明**：

| 参数 | 类型 | 说明 |
|-----|------|------|
| index | int | 注记对象在选择集中的索引（从 0 开始） |
| fieldName | str | 属性名称，支持基本属性、几何特性和扩展属性 |

**返回值**：
- 类型：str
- 说明：指定注记对象的属性值

**使用示例**：

```python
from sunvpy import SSProcess

# 获取第 0 个注记对象的字体内容
font_string = SSProcess.getSelNoteValue(0, "SSObj_FontString")
print(f"注记内容: {font_string}")

# 获取第 0 个注记对象的字体高度
font_height = SSProcess.getSelNoteValue(0, "SSObj_FontHeight")
print(f"字体高度: {font_height}")

# 获取第 0 个注记对象的字体分类号
font_class = SSProcess.getSelNoteValue(0, "SSObj_FontClass")
print(f"注记分类号: {font_class}")
```

Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L204-L241)

## 属性获取流程

获取地物属性值的完整流程包括构建选择集、遍历对象、读取属性和输出结果四个阶段。下图展示了这个过程的完整数据流：

```mermaid
flowchart LR
    A[初始化 SSProcess] --> B[清理选择集<br/>clearSelection]
    B --> C[清理选择条件<br/>clearSelectCondition]
    C --> D[设置选择条件<br/>setSelectCondition]
    D --> E[执行过滤查询<br/>selectFilter]
    E --> F[获取对象数量<br/>getSelGeoCount]
    F --> G[遍历选择集]
    G --> H[读取属性值<br/>getSelGeoValue]
    H --> I{是否还有对象?}
    I -->|是| G
    I -->|否| J[处理完成]
```

## 基本属性读取示例

### 示例 1：读取单个对象的多个属性

```python
from sunvpy import SSProcess

# 假设选择集中已有对象
# 清理并设置选择条件
SSProcess.clearSelection()
SSProcess.clearSelectCondition()
SSProcess.setSelectCondition("SSObj_Code", "==", "3103013")
SSProcess.selectFilter()

# 定义要读取的属性列表
fields = [
    "SSObj_ID", "SSObj_Code", "SSObj_LayerName", "SSObj_Type",
    "SSObj_Color", "SSObj_LineType", "SSObj_LineWidth",
    "SSObj_Name", "SSObj_Byname"
]

# 读取第 0 个对象的属性
print("=" * 50)
print("对象详细信息")
print("=" * 50)
for field in fields:
    value = SSProcess.getSelGeoValue(0, field)
    print(f"{field:20s}: {value}")
```

**输出示例**：

```
==================================================
对象详细信息
==================================================
SSObj_ID            : 1001
SSObj_Code          : 3103013
SSObj_LayerName     : Default_A
SSObj_Type          : LINE
SSObj_Color         : 16777215
SSObj_LineType      : 1
SSObj_LineWidth     : 2
SSObj_Name          : 道路1
SSObj_Byname        : 主路
```

Sources: [PySSProcess.py](PySSProcess.py#L110-L138)

### 示例 2：批量读取所有对象的核心属性

```python
from sunvpy import SSProcess

# 清理并设置选择条件
SSProcess.clearSelection()
SSProcess.clearSelectCondition()
SSProcess.setSelectCondition("SSObj_Type", "==", "AREA")
SSProcess.selectFilter()

# 获取对象数量
count = SSProcess.getSelGeoCount()
print(f"选择集中有 {count} 个面对象\n")

# 定义要读取的核心属性
core_fields = ["SSObj_ID", "SSObj_Code", "SSObj_Area", "SSObj_Length"]

# 遍历所有对象并读取属性
for i in range(count):
    print(f"对象 {i}:")
    for field in core_fields:
        value = SSProcess.getSelGeoValue(i, field)
        print(f"  {field}: {value}")
    print("-" * 30)
```

Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L152-L162)

## 坐标点属性读取

对于点、线、面对象，可以使用带参数的属性名来读取特定坐标点的信息。参数放在属性名后的括号中，如 `SSObj_X(0)` 表示第一个点的 X 坐标。

```python
from sunvpy import SSProcess

# 清理并设置选择条件
SSProcess.clearSelection()
SSProcess.clearSelectCondition()
SSProcess.setSelectCondition("SSObj_Type", "==", "LINE")
SSProcess.selectFilter()

# 获取第 0 个线对象
count = SSProcess.getSelGeoCount()
if count > 0:
    # 获取点数
    point_count = SSProcess.getSelGeoValue(0, "SSObj_PointCount")
    print(f"该线对象包含 {point_count} 个坐标点\n")
    
    # 遍历所有坐标点
    for j in range(int(point_count)):
        x = SSProcess.getSelGeoValue(0, f"SSObj_X({j})")
        y = SSProcess.getSelGeoValue(0, f"SSObj_Y({j})")
        z = SSProcess.getSelGeoValue(0, f"SSObj_Z({j})")
        point_name = SSProcess.getSelGeoValue(0, f"SSObj_PointName({j})")
        point_type = SSProcess.getSelGeoValue(0, f"SSObj_PointType({j})")
        
        print(f"点 {j}: X={x}, Y={y}, Z={z}, 名称={point_name}, 类型={point_type}")
```

**输出示例**：

```
该线对象包含 5 个坐标点

点 0: X=12345.67, Y=54321.09, Z=0.00, 名称=起点, 类型=1
点 1: X=12400.00, Y=54380.00, Z=0.00, 名称=, 类型=0
点 2: X=12450.50, Y=54420.30, Z=0.00, 名称=, 类型=0
点 3: X=12500.00, Y=54480.00, Z=0.00, 名称=, 类型=0
点 4: X=12550.75, Y=54530.60, Z=0.00, 名称=终点, 类型=2
```

Sources: [ObjBaseAttr.py](ObjBaseAttr.py#L329-L363)

## 几何特性读取示例

几何特性属性用于判断对象的拓扑状态，通常用于数据质量检查。

```python
from sunvpy import SSProcess

# 清理并设置选择条件
SSProcess.clearSelection()
SSProcess.clearSelectCondition()
SSProcess.setSelectCondition("SSObj_Type", "==", "AREA")
SSProcess.selectFilter()

# 获取对象数量
count = SSProcess.getSelGeoCount()
print(f"面对象几何特性检查\n")

# 遍历所有面对象
for i in range(count):
    obj_id = SSProcess.getSelGeoValue(i, "SSObj_ID")
    obj_code = SSProcess.getSelGeoValue(i, "SSObj_Code")
    
    # 读取几何特性
    is_closed = SSProcess.getSelGeoValue(i, "<Close>")
    is_overlap = SSProcess.getSelGeoValue(i, "<Overlap>")
    is_convex = SSProcess.getSelGeoValue(i, "<Convex>")
    is_self_intersect = SSProcess.getSelGeoValue(i, "<SelfIntersect>")
    
    print(f"对象 ID={obj_id}, Code={obj_code}:")
    print(f"  是否封闭: {is_closed}")
    print(f"  是否重叠: {is_overlap}")
    print(f"  是否凸多边形: {is_convex}")
    print(f"  是否自相交: {is_self_intersect}")
    
    # 检查是否有问题
    issues = []
    if is_closed == "False":
        issues.append("未封闭")
    if is_overlap == "True":
        issues.append("存在重叠")
    if is_self_intersect == "True":
        issues.append("存在自相交")
    
    if issues:
        print(f"  ⚠️ 发现问题: {', '.join(issues)}")
    print("-" * 40)
```

Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L52-L110)

## 扩展属性读取示例

扩展属性使用方括号 `[]` 括住属性名，支持读取单个属性或多个属性。

### 读取单个扩展属性

```python
from sunvpy import SSProcess

# 清理并设置选择条件
SSProcess.clearSelection()
SSProcess.clearSelectCondition()
SSProcess.setSelectCondition("SSObj_Type", "==", "AREA")
SSProcess.selectFilter()

# 读取第一个对象的扩展属性
building_structure = SSProcess.getSelGeoValue(0, "[JG]")
building_floors = SSProcess.getSelGeoValue(0, "[CS]")
custom_field = SSProcess.getSelGeoValue(0, "[建筑用途]")

print(f"建筑结构: {building_structure}")
print(f"建筑层数: {building_floors}")
print(f"建筑用途: {custom_field}")
```

### 读取多个扩展属性

使用逗号分隔多个属性名，可以一次性读取多个扩展属性，返回值会用逗号拼接。

```python
from sunvpy import SSProcess

# 清理并设置选择条件
SSProcess.clearSelection()
SSProcess.clearSelectCondition()
SSProcess.setSelectCondition("SSObj_Type", "==", "AREA")
SSProcess.selectFilter()

# 一次性读取多个扩展属性
combined_value = SSProcess.getSelGeoValue(0, "[JG],[CS]")
values = combined_value.split(',')

print(f"建筑结构: {values[0] if len(values) > 0 else ''}")
print(f"建筑层数: {values[1] if len(values) > 1 else ''}")
```

### 获取对象的完整扩展属性列表

如果不确定对象有哪些扩展属性，可以先获取完整的扩展属性列表：

```python
from sunvpy import SSProcess

# 清理并设置选择条件
SSProcess.clearSelection()
SSProcess.clearSelectCondition()
SSProcess.selectFilter()

# 获取第一个对象的扩展属性字段和值
SSProcess.curSelGeoFields.clear()
SSProcess.curSelGeoValues.clear()

# 直接访问地物对象获取扩展属性
geo = SSProcess.selGeoList[0]
SSProcess.map.getExtentAttr(geo, SSProcess.curSelGeoFields, SSProcess.curSelGeoValues)

# 打印所有扩展属性
print("对象的扩展属性列表:")
for i in range(SSProcess.curSelGeoFields.size()):
    field = SSProcess.curSelGeoFields[i]
    value = SSProcess.curSelGeoValues[i]
    print(f"  [{field}]: {value}")
```

**输出示例**：

```
对象的扩展属性列表:
  [JG]: 砖混结构
  [CS]: 6
  [建筑用途]: 住宅
  [竣工年份]: 2020
  [建设单位]: XX公司
```

Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L164-L186)

## 注记对象属性读取

注记对象（NOTE 类型）除了通用属性外，还有许多专用的字体和排版属性。

```python
from sunvpy import SSProcess

# 清理并设置选择条件
SSProcess.clearSelection()
SSProcess.clearSelectCondition()
SSProcess.setSelectCondition("SSObj_Type", "==", "NOTE")
SSProcess.selectFilter()

# 获取注记对象数量
count = SSProcess.getSelNoteCount()
print(f"选择集中有 {count} 个注记对象\n")

# 定义注记专用属性列表
note_fields = [
    "SSObj_FontString", "SSObj_FontStringCount",
    "SSObj_FontWidth", "SSObj_FontHeight", "SSObj_FontName",
    "SSObj_FontClass", "SSObj_FontAlignment", "SSObj_FontPosType",
    "SSObj_FontWordAngle", "SSObj_FontStringAngle",
    "SSObj_FontWeight", "SSObj_FontUnderLine", "SSObj_FontInterval"
]

# 遍历所有注记对象
for i in range(min(count, 5)):  # 最多显示前 5 个
    print(f"注记对象 {i}:")
    for field in note_fields:
        value = SSProcess.getSelNoteValue(i, field)
        print(f"  {field:20s}: {value}")
    print("-" * 50)
```

**输出示例**：

```
选择集中有 3 个注记对象

注记对象 0:
  SSObj_FontString      : 测区边界
  SSObj_FontStringCount : 4
  SSObj_FontWidth       : 15.00
  SSObj_FontHeight      : 20.00
  SSObj_FontName        : 宋体
  SSObj_FontClass       : 1
  SSObj_FontAlignment  : 0
  SSObj_FontPosType     : 0
  SSObj_FontWordAngle   : 0.00
  SSObj_FontStringAngle : 0.00
  SSObj_FontWeight      : 400
  SSObj_FontUnderLine   : 0
  SSObj_FontInterval    : 1.00
--------------------------------------------------
```

Sources: [ObjBaseAttr.py](ObjBaseAttr.py#L147-L207)

## 综合应用示例

下面的示例展示了如何结合基本属性、几何特性和扩展属性，实现一个完整的属性查询和分析功能。

```python
from sunvpy import SSProcess

def analyze_geospatial_objects():
    """分析地物对象的综合属性"""
    
    # 步骤 1: 清理并设置选择条件
    SSProcess.clearSelection()
    SSProcess.clearSelectCondition()
    SSProcess.setSelectCondition("SSObj_Type", "==", "AREA")
    SSProcess.selectFilter()
    
    # 步骤 2: 获取对象数量
    count = SSProcess.getSelGeoCount()
    print(f"分析 {count} 个面对象的综合属性\n")
    
    # 步骤 3: 统计信息
    total_area = 0.0
    total_length = 0.0
    problem_count = 0
    
    # 步骤 4: 遍历所有对象
    for i in range(count):
        # 读取基本属性
        obj_id = SSProcess.getSelGeoValue(i, "SSObj_ID")
        obj_code = SSProcess.getSelGeoValue(i, "SSObj_Code")
        obj_layer = SSProcess.getSelGeoValue(i, "SSObj_LayerName")
        obj_area = float(SSProcess.getSelGeoValue(i, "SSObj_Area"))
        obj_length = float(SSProcess.getSelGeoValue(i, "SSObj_Length"))
        obj_create_time = SSProcess.getSelGeoValue(i, "SSObj_CreateTime")
        obj_modify_time = SSProcess.getSelGeoValue(i, "SSObj_ModifyTime")
        
        # 累计面积和长度
        total_area += obj_area
        total_length += obj_length
        
        # 读取几何特性
        is_closed = SSProcess.getSelGeoValue(i, "<Close>")
        is_overlap = SSProcess.getSelGeoValue(i, "<Overlap>")
        
        # 读取扩展属性
        building_structure = SSProcess.getSelGeoValue(i, "[JG]")
        building_floors = SSProcess.getSelGeoValue(i, "[CS]")
        
        # 检查几何问题
        has_problem = False
        problems = []
        
        if is_closed == "False":
            problems.append("未封闭")
            has_problem = True
        
        if is_overlap == "True":
            problems.append("存在重叠")
            has_problem = True
        
        if has_problem:
            problem_count += 1
            print(f"⚠️ 对象 {obj_id} (Code={obj_code}) 发现问题: {', '.join(problems)}")
        
        # 输出对象详细信息
        print(f"对象 ID={obj_id}:")
        print(f"  图层: {obj_layer}")
        print(f"  面积: {obj_area:.2f} 平方米")
        print(f"  周长: {obj_length:.2f} 米")
        print(f"  建筑结构: {building_structure if building_structure else '未知'}")
        print(f"  建筑层数: {building_floors if building_floors else '未知'}")
        print(f"  创建时间: {obj_create_time}")
        print(f"  修改时间: {obj_modify_time}")
        print(f"  几何状态: {'封闭' if is_closed == 'True' else '未封闭'}, {'重叠' if is_overlap == 'True' else '无重叠'}")
        print("-" * 60)
    
    # 步骤 5: 输出统计摘要
    print("\n" + "=" * 60)
    print("统计摘要")
    print("=" * 60)
    print(f"对象总数: {count}")
    print(f"总面积: {total_area:.2f} 平方米")
    print(f"平均面积: {total_area/count if count > 0 else 0:.2f} 平方米")
    print(f"总周长: {total_length:.2f} 米")
    print(f"平均周长: {total_length/count if count > 0 else 0:.2f} 米")
    print(f"问题对象数: {problem_count} ({problem_count/count*100 if count > 0 else 0:.1f}%)")
    print("=" * 60)

# 执行分析
analyze_geospatial_objects()
```

Sources: [PySSProcess.py](PySSProcess.py#L110-L138)

## 常见问题与解决方案

### 问题 1：属性值返回空字符串

**现象**：调用 `getSelGeoValue()` 后返回空字符串

**可能原因**：
1. 索引越界：指定的索引超出了选择集范围
2. 属性名不存在：属性名拼写错误或该对象不支持此属性
3. 属性不适用：尝试读取不适用的属性（如点对象的面积）

**解决方案**：

```python
from sunvpy import SSProcess

# 检查索引是否有效
count = SSProcess.getSelGeoCount()
index = 0

if index >= 0 and index < count:
    value = SSProcess.getSelGeoValue(index, "SSObj_Code")
    if value:
        print(f"属性值: {value}")
    else:
        print("属性值为空，可能属性不存在")
else:
    print(f"索引 {index} 越界，选择集中只有 {count} 个对象")
```

### 问题 2：扩展属性无法读取

**现象**：使用 `[扩展属性名]` 格式读取时返回空值

**可能原因**：
1. 扩展属性名称拼写错误
2. 当前对象没有该扩展属性
3. 扩展属性未在数据源中定义

**解决方案**：

```python
from sunvpy import SSProcess

# 方法 1: 先查询对象有哪些扩展属性
SSProcess.curSelGeoFields.clear()
SSProcess.curSelGeoValues.clear()
geo = SSProcess.selGeoList[0] if SSProcess.getSelGeoCount() > 0 else None

if geo:
    SSProcess.map.getExtentAttr(geo, SSProcess.curSelGeoFields, SSProcess.curSelGeoValues)
    print("可用的扩展属性:")
    for i in range(SSProcess.curSelGeoFields.size()):
        print(f"  {SSProcess.curSelGeoFields[i]}")

# 方法 2: 使用正确的属性名读取
structure = SSProcess.getSelGeoValue(0, "[JG]")  # 确保方括号和名称正确
```

### 问题 3：坐标点属性读取失败

**现象**：使用 `SSObj_X(0)` 等格式读取坐标点时返回空值

**可能原因**：
1. 对象点数不足：指定的点索引超出了对象的实际点数
2. 对象类型不支持：注记对象不支持坐标点属性

**解决方案**：

```python
from sunvpy import SSProcess

# 先获取对象的点数
point_count = SSProcess.getSelGeoValue(0, "SSObj_PointCount")
obj_type = SSProcess.getSelGeoValue(0, "SSObj_Type")

if obj_type in ["POINT", "LINE", "AREA"]:
    if point_count:
        for j in range(int(point_count)):
            x = SSProcess.getSelGeoValue(0, f"SSObj_X({j})")
            y = SSProcess.getSelGeoValue(0, f"SSObj_Y({j})")
            print(f"点 {j}: ({x}, {y})")
    else:
        print("对象没有坐标点")
else:
    print("注记对象不支持坐标点属性")
```

### 问题 4：几何特性返回值不是预期的布尔值

**现象**：读取 `<Close>` 等几何特性时，返回值不是 "True" 或 "False"

**可能原因**：几何特性的返回值格式可能与预期不同

**解决方案**：

```python
from sunvpy import SSProcess

# 读取几何特性并处理不同格式
is_closed = SSProcess.getSelGeoValue(0, "<Close>")

# 处理不同的返回值格式
if is_closed in ["True", "true", "1", "是"]:
    print("对象是封闭的")
elif is_closed in ["False", "false", "0", "否", ""]:
    print("对象未封闭")
else:
    print(f"未知的状态值: {is_closed}")
```

Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L164-L241)

## 属性读取性能优化建议

在处理大量地物对象时，合理的代码组织可以显著提高属性读取效率。

### 建议 1：批量读取多个属性

```python
# 不推荐：多次调用 getSelGeoValue
code = SSProcess.getSelGeoValue(i, "SSObj_Code")
name = SSProcess.getSelGeoValue(i, "SSObj_Name")
layer = SSProcess.getSelGeoValue(i, "SSObj_LayerName")

# 推荐：使用列表批量定义属性，然后循环读取
fields = ["SSObj_Code", "SSObj_Name", "SSObj_LayerName"]
for field in fields:
    value = SSProcess.getSelGeoValue(i, field)
    print(f"{field}: {value}")
```

### 建议 2：避免重复读取

```python
# 不推荐：在循环中重复读取相同的属性
for i in range(count):
    obj_type = SSProcess.getSelGeoValue(i, "SSObj_Type")
    if obj_type == "AREA":
        area = SSProcess.getSelGeoValue(i, "SSObj_Area")  # 第一次读取
        length = SSProcess.getSelGeoValue(i, "SSObj_Length")
        # ... 其他处理
        print(f"面积: {SSProcess.getSelGeoValue(i, 'SSObj_Area')}")  # 重复读取

# 推荐：缓存已读取的属性值
for i in range(count):
    obj_type = SSProcess.getSelGeoValue(i, "SSObj_Type")
    if obj_type == "AREA":
        area = SSProcess.getSelGeoValue(i, "SSObj_Area")
        length = SSProcess.getSelGeoValue(i, "SSObj_Length")
        # ... 其他处理
        print(f"面积: {area}")  # 使用缓存的值
```

### 建议 3：使用字典存储对象属性

```python
# 推荐：使用字典存储每个对象的属性
for i in range(count):
    obj_attrs = {}
    fields = ["SSObj_ID", "SSObj_Code", "SSObj_Name", "SSObj_Area"]
    
    for field in fields:
        obj_attrs[field] = SSProcess.getSelGeoValue(i, field)
    
    # 使用字典中的值进行处理
    print(f"对象 {obj_attrs['SSObj_ID']}: {obj_attrs['SSObj_Name']}, 面积={obj_attrs['SSObj_Area']}")
```

## 下一步学习

掌握了属性读取方法后，您可能对以下主题感兴趣：

- **修改地物属性值**：学习如何使用 `setSelGeoValue()` 和 `setSelNoteValue()` 方法修改地物属性，参见 [修改地物属性值](16-xiu-gai-di-wu-shu-xing-zhi)
- **地物基本属性详解**：深入了解各个基本属性的含义和取值范围，参见 [地物基本属性详解](17-di-wu-ji-ben-shu-xing-xiang-jie)
- **扩展属性与自定义属性**：学习如何定义和使用扩展属性，参见 [扩展属性与自定义属性](18-kuo-zhan-shu-xing-yu-zi-ding-yi-shu-xing)
- **遍历选择集对象**：了解更多关于选择集遍历的高级技巧和最佳实践，参见 [遍历选择集对象](14-bian-li-xuan-ze-ji-dui-xiang)

通过这些文档的结合学习，您将能够全面掌握 SunvStation 地物属性的管理技巧，构建更强大和高效的地理数据处理脚本。