# 坐标系动态适配设计方案(简化版) ## 问题背景 客户模型坐标系与插件默认坐标系不同: - **插件默认**: 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; /// /// 当前坐标系 /// public ICoordinateSystem Current => _current; /// /// 初始化/重新检测坐标系 /// 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}"); } /// /// 自动检测坐标系(基于 Document.UpVector) /// 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(); } } /// /// 手动切换坐标系(用于系统管理界面) /// 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 ``` **ViewModel 实现**: ```csharp public ObservableCollection CoordinateSystemOptions { get; } = new() { "AutoDetect", "ZUp", "YUp" }; public string SelectedCoordinateSystem { get => _selectedCoordinateSystem; set { if (SetProperty(ref _selectedCoordinateSystem, value)) { // 解析并应用新坐标系 if (Enum.TryParse(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* *版本: 简化版*