# 坐标系动态适配设计方案（简化版）

## 问题背景

客户模型坐标系与插件默认坐标系不同：
- **插件默认**: Z-up (Z轴向上)
- **客户模型**: Y-up (Y轴向上，常见于Revit导出)

这导致网格生成、高度检测、路径规划等功能出现问题。

---

## 简化检测方案

### 核心原则

**单一检测源**: 使用 `Document.UpVector` 作为唯一检测依据

```csharp
var upVector = Application.ActiveDocument.UpVector;

if (!upVector.IsZero)
{
    // 使用 Document.UpVector 判断坐标系
    if (Math.Abs(upVector.Y) > 0.9)
        return CoordinateSystemType.YUp;
    else if (Math.Abs(upVector.Z) > 0.9)
        return CoordinateSystemType.ZUp;
}
else
{
    // 未定义，使用默认配置
    return ConfigManager.Instance.Current.CoordinateSystem.Type;
}
```

---

## 实现架构

### 1. 坐标系类型枚举

```csharp
// src/Utils/CoordinateSystem/CoordinateSystemType.cs
public enum CoordinateSystemType
{
    AutoDetect,  // 自动检测（使用 Document.UpVector）
    ZUp,         // 强制 Z-Up
    YUp          // 强制 Y-Up
}
```

### 2. 简化坐标系管理器

```csharp
// src/Utils/CoordinateSystem/CoordinateSystemManager.cs
public class CoordinateSystemManager
{
    public static CoordinateSystemManager Instance { get; } = new();
    
    private ICoordinateSystem _current;
    private CoordinateSystemType _configuredType;
    
    /// <summary>
    /// 当前坐标系
    /// </summary>
    public ICoordinateSystem Current => _current;
    
    /// <summary>
    /// 初始化/重新检测坐标系
    /// </summary>
    public void Initialize()
    {
        _configuredType = ConfigManager.Instance.Current.CoordinateSystem.Type;
        
        switch (_configuredType)
        {
            case CoordinateSystemType.AutoDetect:
                _current = AutoDetect();
                break;
            case CoordinateSystemType.ZUp:
                _current = new ZUpCoordinateSystem();
                break;
            case CoordinateSystemType.YUp:
                _current = new YUpCoordinateSystem();
                break;
        }
        
        LogManager.Info($"[坐标系] 初始化完成: {_current.Type}");
    }
    
    /// <summary>
    /// 自动检测坐标系（基于 Document.UpVector）
    /// </summary>
    private ICoordinateSystem AutoDetect()
    {
        try
        {
            var doc = Application.ActiveDocument;
            if (doc == null) return new ZUpCoordinateSystem();
            
            var upVector = doc.UpVector;
            
            if (!upVector.IsZero)
            {
                if (Math.Abs(upVector.Y) > 0.9)
                {
                    LogManager.Info("[坐标系检测] Document.UpVector 表明 Y-Up 坐标系");
                    return new YUpCoordinateSystem();
                }
                else if (Math.Abs(upVector.Z) > 0.9)
                {
                    LogManager.Info("[坐标系检测] Document.UpVector 表明 Z-Up 坐标系");
                    return new ZUpCoordinateSystem();
                }
            }
            
            LogManager.Warning("[坐标系检测] Document.UpVector 未定义，使用默认 Z-Up");
            return new ZUpCoordinateSystem();
        }
        catch (Exception ex)
        {
            LogManager.Error($"[坐标系检测] 检测失败: {ex.Message}");
            return new ZUpCoordinateSystem();
        }
    }
    
    /// <summary>
    /// 手动切换坐标系（用于系统管理界面）
    /// </summary>
    public void SetCoordinateSystem(CoordinateSystemType type)
    {
        switch (type)
        {
            case CoordinateSystemType.ZUp:
                _current = new ZUpCoordinateSystem();
                break;
            case CoordinateSystemType.YUp:
                _current = new YUpCoordinateSystem();
                break;
            default:
                _current = AutoDetect();
                break;
        }
        
        LogManager.Info($"[坐标系] 手动切换为: {_current.Type}");
    }
}
```

---

## 配置文件

```toml
# default_config.toml
[coordinate_system]
# 坐标系类型: "AutoDetect"（推荐）, "ZUp", "YUp"
# AutoDetect 将使用 Document.UpVector 自动检测
type = "AutoDetect"
```

---

## 系统管理界面

在系统管理页签添加坐标系设置：

```xml
<!-- 添加到 SystemManagementView.xaml -->
<ComboBox ItemsSource="{Binding CoordinateSystemOptions}"
          SelectedItem="{Binding SelectedCoordinateSystem}"
          ToolTip="选择坐标系，AutoDetect 将自动检测"/>
```

**ViewModel 实现**:

```csharp
public ObservableCollection<string> CoordinateSystemOptions { get; } = 
    new() { "AutoDetect", "ZUp", "YUp" };

public string SelectedCoordinateSystem
{
    get => _selectedCoordinateSystem;
    set
    {
        if (SetProperty(ref _selectedCoordinateSystem, value))
        {
            // 解析并应用新坐标系
            if (Enum.TryParse<CoordinateSystemType>(value, out var type))
            {
                CoordinateSystemManager.Instance.SetCoordinateSystem(type);
                LogManager.Info($"坐标系已切换为: {value}");
            }
        }
    }
}
```

---

## 使用流程

### 场景1: 自动检测成功

1. 打开模型
2. 插件自动检测 `Document.UpVector`
3. 检测到 `(0,1,0)` → 自动使用 Y-Up 坐标系
4. 用户无感知，功能正常工作

### 场景2: 自动检测失败（UpVector 为 Zero）

1. 打开模型
2. 插件检测到 `Document.UpVector.IsZero`
3. 回退到默认 Z-Up，记录警告日志
4. 用户发现功能异常
5. 打开系统管理 → 手动切换坐标系为 Y-Up
6. 功能恢复正常

### 场景3: 用户强制指定

1. 用户提前知道模型坐标系
2. 在系统管理中设置坐标系为 Y-Up
3. 打开模型，直接使用指定坐标系

---

## 需要修改的模块

| 模块 | 修改内容 | 优先级 |
|------|----------|--------|
| **CoordinateSystemManager** | 新建，实现简化检测逻辑 | P0 |
| **ICoordinateSystem** | 接口及 ZUp/YUp 实现 | P0 |
| **SystemManagementView** | 添加坐标系选择下拉框 | P0 |
| **GridMap** | 使用坐标系抽象 | P1 |
| **GridMapGenerator** | 垂直扫描方向适配 | P1 |
| **其他模块** | 逐步替换直接坐标访问 | P2 |

---

## 实施步骤

### 阶段1: 核心实现（1周）

1. 创建坐标系统抽象层
2. 实现简化检测逻辑
3. 添加系统管理界面配置

### 阶段2: 核心模块适配（1周）

1. 修改 GridMap 使用坐标系抽象
2. 修改 GridMapGenerator
3. 测试验证

### 阶段3: 全面适配（1周）

1. 逐步替换其他模块
2. 完善测试
3. 文档更新

---

## 关键代码示例

### 坐标系抽象接口

```csharp
public interface ICoordinateSystem
{
    CoordinateSystemType Type { get; }
    
    // 获取高度值（统一抽象）
    double GetElevation(Point3D point);
    
    // 设置高度值
    Point3D SetElevation(Point3D point, double elevation);
    
    // 获取水平面坐标
    (double h1, double h2) GetHorizontalCoords(Point3D point);
    
    // 创建3D点
    Point3D CreatePoint(double h1, double h2, double elevation);
    
    // 向上向量
    Vector3D UpVector { get; }
    
    // 垂直扫描方向（用于障碍物检测）
    Vector3D VerticalScanDirection { get; }
}
```

### Z-Up 实现

```csharp
public class ZUpCoordinateSystem : ICoordinateSystem
{
    public CoordinateSystemType Type => CoordinateSystemType.ZUp;
    public Vector3D UpVector => new Vector3D(0, 0, 1);
    public Vector3D VerticalScanDirection => new Vector3D(0, 0, -1);
    
    public double GetElevation(Point3D point) => point.Z;
    public Point3D SetElevation(Point3D point, double elevation) => 
        new Point3D(point.X, point.Y, elevation);
    public (double h1, double h2) GetHorizontalCoords(Point3D point) => 
        (point.X, point.Y);
    public Point3D CreatePoint(double h1, double h2, double elevation) => 
        new Point3D(h1, h2, elevation);
}
```

### Y-Up 实现

```csharp
public class YUpCoordinateSystem : ICoordinateSystem
{
    public CoordinateSystemType Type => CoordinateSystemType.YUp;
    public Vector3D UpVector => new Vector3D(0, 1, 0);
    public Vector3D VerticalScanDirection => new Vector3D(0, -1, 0);
    
    public double GetElevation(Point3D point) => point.Y;
    public Point3D SetElevation(Point3D point, double elevation) => 
        new Point3D(point.X, elevation, point.Z);
    public (double h1, double h2) GetHorizontalCoords(Point3D point) => 
        (point.X, point.Z);
    public Point3D CreatePoint(double h1, double h2, double elevation) => 
        new Point3D(h1, elevation, h2);
}
```

---

## 优势

1. **简单可靠**: 基于 API 提供的 UpVector，无需猜测
2. **用户可控**: 自动检测失败时可手动干预
3. **向后兼容**: 默认行为不变，不影响现有用户
4. **易于维护**: 代码简洁，逻辑清晰

---

*文档更新时间: 2026-01-30*
*版本: 简化版*
