From 5fb18b5869a7097f03acf141d99a83d2d87ebeec Mon Sep 17 00:00:00 2001
From: tian <11429339@qq.com>
Date: Fri, 30 Jan 2026 23:39:21 +0800
Subject: [PATCH] =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E5=8A=A8=E6=80=81=E5=9D=90?=
=?UTF-8?q?=E6=A0=87=E7=B3=BB=E6=9E=B6=E6=9E=84=E8=AE=BE=E8=AE=A1=EF=BC=8C?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=8A=A8=E6=A3=80=E6=B5=8B=E6=A8=A1?=
=?UTF-8?q?=E5=9E=8B=E5=9D=90=E6=A0=87=E7=B3=BB=E6=8E=A2=E7=B4=A2=E6=8C=89?=
=?UTF-8?q?=E9=92=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
NavisworksTransportPlugin.csproj | 7 +
doc/requirement/todo_features.md | 2 +
...ate-system-adaptation-design-simplified.md | 342 +++++++++++
.../coordinate-system-adaptation-design.md | 530 ++++++++++++++++++
.../coordinate-system-detection-results.md | 136 +++++
...works-coordinate-system-api-exploration.md | 313 +++++++++++
.../CoordinateSystemExplorerCommand.cs | 201 +++++++
.../ViewModels/SystemManagementViewModel.cs | 293 ++++++++++
.../Views/CoordinateSystemResultDialog.xaml | 52 ++
.../CoordinateSystemResultDialog.xaml.cs | 78 +++
src/UI/WPF/Views/SystemManagementView.xaml | 6 +
11 files changed, 1960 insertions(+)
create mode 100644 doc/working/coordinate-system-adaptation-design-simplified.md
create mode 100644 doc/working/coordinate-system-adaptation-design.md
create mode 100644 doc/working/coordinate-system-detection-results.md
create mode 100644 doc/working/navisworks-coordinate-system-api-exploration.md
create mode 100644 src/Commands/CoordinateSystemExplorerCommand.cs
create mode 100644 src/UI/WPF/Views/CoordinateSystemResultDialog.xaml
create mode 100644 src/UI/WPF/Views/CoordinateSystemResultDialog.xaml.cs
diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj
index ea0e432..75584ab 100644
--- a/NavisworksTransportPlugin.csproj
+++ b/NavisworksTransportPlugin.csproj
@@ -245,6 +245,9 @@
EditRotationWindow.xaml
+
+ CoordinateSystemResultDialog.xaml
+
@@ -312,6 +315,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/doc/requirement/todo_features.md b/doc/requirement/todo_features.md
index 8e533a9..71777e0 100644
--- a/doc/requirement/todo_features.md
+++ b/doc/requirement/todo_features.md
@@ -5,6 +5,8 @@
### [2026/1/28]
1. [ ] (优化)将ViewPonit的RenderStyle改成Shaded,以免影响高亮(考虑在显示碰撞时,改成Wireframe)
+2、[ ] (优化)修改架构适应模型坐标系的变化(Yup-Xright-Zfront)
+3、[ ] (优化)修改吊装路径适应桁车空中路线(纵向+平移,有吊绳)
### [2026/1/26]
diff --git a/doc/working/coordinate-system-adaptation-design-simplified.md b/doc/working/coordinate-system-adaptation-design-simplified.md
new file mode 100644
index 0000000..f5fc9e3
--- /dev/null
+++ b/doc/working/coordinate-system-adaptation-design-simplified.md
@@ -0,0 +1,342 @@
+# 坐标系动态适配设计方案(简化版)
+
+## 问题背景
+
+客户模型坐标系与插件默认坐标系不同:
+- **插件默认**: 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*
+*版本: 简化版*
diff --git a/doc/working/coordinate-system-adaptation-design.md b/doc/working/coordinate-system-adaptation-design.md
new file mode 100644
index 0000000..7365df2
--- /dev/null
+++ b/doc/working/coordinate-system-adaptation-design.md
@@ -0,0 +1,530 @@
+# 坐标系动态适配设计方案
+
+## 问题背景
+
+客户模型坐标系与插件默认坐标系不同:
+- **插件默认**: Z-up (Z轴向上, X向右, Y向后)
+- **客户模型**: Y-up (Y轴向上, X向右, Z向前)
+
+这导致网格生成、高度检测、碰撞检测、路径渲染等功能出现问题。
+
+---
+
+## 架构设计
+
+### 整体架构
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│ 业务逻辑层 │
+│ (PathPlanning, Collision Detection, Animation, etc.) │
+├─────────────────────────────────────────────────────────────┤
+│ 坐标系抽象层 │
+│ ┌─────────────────┐ ┌─────────────────┐ │
+│ │ ICoordinateSystem │ │ CoordinateSystemManager │ │
+│ └─────────────────┘ └─────────────────┘ │
+├─────────────────────────────────────────────────────────────┤
+│ 具体实现层 │
+│ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐ │
+│ │ ZUpCoordinateSystem │ │ YUpCoordinateSystem │ │...│
+│ └───────────────┘ └───────────────┘ └─────────────────┘ │
+└─────────────────────────────────────────────────────────────┘
+ │
+ ┌───────┴───────┐
+ ▼ ▼
+ [Navisworks API] [自定义逻辑]
+```
+
+---
+
+## 核心组件实现
+
+### 1. 坐标系类型枚举
+
+**文件**: `src/Utils/CoordinateSystem/CoordinateSystemType.cs`
+
+```csharp
+namespace NavisworksTransport.Utils.CoordinateSystem
+{
+ ///
+ /// 支持的坐标系类型
+ ///
+ public enum CoordinateSystemType
+ {
+ ///
+ /// Z轴向上 (标准Navisworks坐标系: Z-up, X-right, Y-back)
+ ///
+ ZUp,
+
+ ///
+ /// Y轴向上 (常见于Revit等: Y-up, X-right, Z-front)
+ ///
+ YUp,
+
+ ///
+ /// 自动检测
+ ///
+ AutoDetect
+ }
+
+ ///
+ /// 轴定义
+ ///
+ public enum Axis
+ {
+ Horizontal1, // X轴对应(通常是Right)
+ Horizontal2, // Z/Y轴对应(通常是Front/Back)
+ Vertical // Y/Z轴对应(通常是Up)
+ }
+}
+```
+
+---
+
+### 2. 坐标系接口
+
+**文件**: `src/Utils/CoordinateSystem/ICoordinateSystem.cs`
+
+```csharp
+using Autodesk.Navisworks.Api;
+
+namespace NavisworksTransport.Utils.CoordinateSystem
+{
+ ///
+ /// 坐标系接口 - 抽象不同坐标系的差异
+ ///
+ public interface ICoordinateSystem
+ {
+ ///
+ /// 坐标系类型
+ ///
+ CoordinateSystemType Type { get; }
+
+ ///
+ /// 获取向上轴的索引 (0=X, 1=Y, 2=Z)
+ ///
+ int UpAxisIndex { get; }
+
+ ///
+ /// 获取水平面主轴索引 (通常是X)
+ ///
+ int PrimaryHorizontalAxisIndex { get; }
+
+ ///
+ /// 获取水平面次轴索引
+ ///
+ int SecondaryHorizontalAxisIndex { get; }
+
+ ///
+ /// 获取点的高度值(统一抽象)
+ ///
+ double GetElevation(Point3D point);
+
+ ///
+ /// 设置点的高度值,返回新点
+ ///
+ Point3D SetElevation(Point3D point, double elevation);
+
+ ///
+ /// 获取水平面坐标(返回Vector2D或Tuple)
+ ///
+ (double h1, double h2) GetHorizontalCoords(Point3D point);
+
+ ///
+ /// 从水平面坐标和高度构建3D点
+ ///
+ Point3D CreatePoint(double h1, double h2, double elevation);
+
+ ///
+ /// 获取垂直方向向量
+ ///
+ Vector3D UpVector { get; }
+
+ ///
+ /// 获取网格平面(用于2D网格的轴对应)
+ /// 返回两个轴的索引 (axis1, axis2)
+ ///
+ (int axis1, int axis2) GridPlaneAxes { get; }
+
+ ///
+ /// 将外部点转换为内部标准表示(如果必要)
+ ///
+ Point3D ToInternal(Point3D externalPoint);
+
+ ///
+ /// 将内部点转换为外部表示
+ ///
+ Point3D ToExternal(Point3D internalPoint);
+
+ ///
+ /// 获取用于垂直扫描的方向向量(通常是-UpVector)
+ ///
+ Vector3D VerticalScanDirection { get; }
+
+ ///
+ /// 获取包围盒的高度范围
+ ///
+ (double min, double max) GetHeightRange(BoundingBox3D bounds);
+
+ ///
+ /// 获取包围盒的水平范围
+ ///
+ (double min1, double max1, double min2, double max2) GetHorizontalRange(BoundingBox3D bounds);
+ }
+}
+```
+
+---
+
+### 3. Z-Up 坐标系实现
+
+**文件**: `src/Utils/CoordinateSystem/ZUpCoordinateSystem.cs`
+
+```csharp
+using Autodesk.Navisworks.Api;
+
+namespace NavisworksTransport.Utils.CoordinateSystem
+{
+ ///
+ /// Z轴向上坐标系 (Navisworks默认)
+ /// X = Right, Y = Back, Z = Up
+ ///
+ public class ZUpCoordinateSystem : ICoordinateSystem
+ {
+ public CoordinateSystemType Type => CoordinateSystemType.ZUp;
+ public int UpAxisIndex => 2; // Z
+ public int PrimaryHorizontalAxisIndex => 0; // X
+ public int SecondaryHorizontalAxisIndex => 1; // Y
+ public Vector3D UpVector => new Vector3D(0, 0, 1);
+ public Vector3D VerticalScanDirection => new Vector3D(0, 0, -1);
+ public (int axis1, int axis2) GridPlaneAxes => (0, 1); // X, Y
+
+ 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);
+
+ public Point3D ToInternal(Point3D externalPoint) => externalPoint;
+ public Point3D ToExternal(Point3D internalPoint) => internalPoint;
+
+ public (double min, double max) GetHeightRange(BoundingBox3D bounds) =>
+ (bounds.Min.Z, bounds.Max.Z);
+
+ public (double min1, double max1, double min2, double max2) GetHorizontalRange(BoundingBox3D bounds) =>
+ (bounds.Min.X, bounds.Max.X, bounds.Min.Y, bounds.Max.Y);
+ }
+}
+```
+
+---
+
+### 4. Y-Up 坐标系实现
+
+**文件**: `src/Utils/CoordinateSystem/YUpCoordinateSystem.cs`
+
+```csharp
+using Autodesk.Navisworks.Api;
+
+namespace NavisworksTransport.Utils.CoordinateSystem
+{
+ ///
+ /// Y轴向上坐标系 (Revit默认等)
+ /// X = Right, Y = Up, Z = Front
+ ///
+ public class YUpCoordinateSystem : ICoordinateSystem
+ {
+ public CoordinateSystemType Type => CoordinateSystemType.YUp;
+ public int UpAxisIndex => 1; // Y
+ public int PrimaryHorizontalAxisIndex => 0; // X
+ public int SecondaryHorizontalAxisIndex => 2; // Z
+ public Vector3D UpVector => new Vector3D(0, 1, 0);
+ public Vector3D VerticalScanDirection => new Vector3D(0, -1, 0);
+ public (int axis1, int axis2) GridPlaneAxes => (0, 2); // X, Z
+
+ 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);
+
+ public Point3D ToInternal(Point3D externalPoint) => new Point3D(
+ externalPoint.X,
+ externalPoint.Z,
+ externalPoint.Y); // 转换为内部Z-up表示
+
+ public Point3D ToExternal(Point3D internalPoint) => new Point3D(
+ internalPoint.X,
+ internalPoint.Z,
+ internalPoint.Y); // 从内部Z-up转换回来
+
+ public (double min, double max) GetHeightRange(BoundingBox3D bounds) =>
+ (bounds.Min.Y, bounds.Max.Y);
+
+ public (double min1, double max1, double min2, double max2) GetHorizontalRange(BoundingBox3D bounds) =>
+ (bounds.Min.X, bounds.Max.X, bounds.Min.Z, bounds.Max.Z);
+ }
+}
+```
+
+---
+
+### 5. 坐标系管理器
+
+**文件**: `src/Utils/CoordinateSystem/CoordinateSystemManager.cs`
+
+```csharp
+using Autodesk.Navisworks.Api;
+
+namespace NavisworksTransport.Utils.CoordinateSystem
+{
+ ///
+ /// 坐标系管理器 - 全局访问点和自动检测
+ ///
+ public class CoordinateSystemManager
+ {
+ private static readonly Lazy _instance =
+ new Lazy(() => new CoordinateSystemManager());
+ public static CoordinateSystemManager Instance => _instance.Value;
+
+ private ICoordinateSystem _current;
+ private CoordinateSystemType _configuredType = CoordinateSystemType.AutoDetect;
+
+ private CoordinateSystemManager()
+ {
+ // 默认使用Z-up
+ _current = new ZUpCoordinateSystem();
+ }
+
+ ///
+ /// 当前活动的坐标系
+ ///
+ public ICoordinateSystem Current => _current;
+
+ ///
+ /// 配置坐标系类型
+ ///
+ public void Configure(CoordinateSystemType type)
+ {
+ _configuredType = type;
+
+ switch (type)
+ {
+ case CoordinateSystemType.ZUp:
+ _current = new ZUpCoordinateSystem();
+ LogManager.Info("[坐标系管理器] 配置为 Z-Up 坐标系");
+ break;
+ case CoordinateSystemType.YUp:
+ _current = new YUpCoordinateSystem();
+ LogManager.Info("[坐标系管理器] 配置为 Y-Up 坐标系");
+ break;
+ case CoordinateSystemType.AutoDetect:
+ _current = AutoDetectCoordinateSystem();
+ break;
+ }
+ }
+
+ ///
+ /// 自动检测坐标系
+ /// 基于模型数据的统计分析
+ ///
+ private ICoordinateSystem AutoDetectCoordinateSystem()
+ {
+ try
+ {
+ var doc = Application.ActiveDocument;
+ if (doc == null || doc.Models.Count == 0)
+ {
+ LogManager.Warning("[坐标系管理器] 无法自动检测,使用默认Z-Up");
+ return new ZUpCoordinateSystem();
+ }
+
+ // 获取模型整体包围盒
+ var sceneBounds = doc.Models[0].RootItem.BoundingBox();
+
+ // 策略1: 分析模型边界在Y和Z方向的分布
+ // 如果Z方向的跨度明显小于X和Y,可能是Y-up(建筑通常更高而非更深)
+ double xSpan = sceneBounds.Max.X - sceneBounds.Min.X;
+ double ySpan = sceneBounds.Max.Y - sceneBounds.Min.Y;
+ double zSpan = sceneBounds.Max.Z - sceneBounds.Min.Z;
+
+ LogManager.Info($"[坐标系检测] 模型跨度: X={xSpan:F2}, Y={ySpan:F2}, Z={zSpan:F2}");
+
+ // 启发式规则:如果Y跨度远大于Z跨度,可能是Y-up
+ if (ySpan > zSpan * 3 && ySpan > xSpan * 0.5)
+ {
+ LogManager.Info("[坐标系检测] 检测到 Y-Up 坐标系 (Y跨度显著)");
+ return new YUpCoordinateSystem();
+ }
+
+ // 策略2: 分析典型建筑元素(楼板、墙)的方向
+ var coordinateSystem = AnalyzeBuildingElements();
+ if (coordinateSystem != null) return coordinateSystem;
+
+ LogManager.Info("[坐标系检测] 使用默认 Z-Up 坐标系");
+ return new ZUpCoordinateSystem();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"[坐标系检测] 自动检测失败: {ex.Message}");
+ return new ZUpCoordinateSystem();
+ }
+ }
+
+ ///
+ /// 通过分析建筑元素检测坐标系
+ ///
+ private ICoordinateSystem AnalyzeBuildingElements()
+ {
+ // 实现:检查楼板等水平元素的法向量
+ // 如果主要水平面的法向量在Y方向,则是Y-up
+ // 简化实现:可以根据项目需求扩展
+ return null;
+ }
+ }
+}
+```
+
+---
+
+## 影响范围分析
+
+### 需要修改的模块
+
+| 模块 | 修改策略 | 工作量 | 优先级 |
+|------|----------|--------|--------|
+| **GridMap** | 使用 `ICoordinateSystem` 替代直接的 `.X/.Y/.Z` 访问 | 中等 | P0 |
+| **GridMapGenerator** | 垂直扫描方向使用 `VerticalScanDirection` | 中等 | P0 |
+| **AutoPathFinder** | 高度计算抽象化 | 中等 | P0 |
+| **PathPointRenderPlugin** | 渲染时坐标转换 | 较小 | P1 |
+| **GeometryHelper** | 几何提取时考虑坐标系 | 中等 | P1 |
+| **ChannelHeightDetector** | 垂直射线方向适配 | 较小 | P0 |
+| **Animation/TimeLiner** | 车辆移动方向适配 | 中等 | P2 |
+| **SlopeAnalyzer** | 坡度计算适配 | 较小 | P1 |
+
+---
+
+## 配置文件支持
+
+在 `default_config.toml` 中添加坐标系配置:
+
+```toml
+[coordinate_system]
+# 坐标系类型: "ZUp", "YUp", "AutoDetect"
+type = "AutoDetect"
+
+# 手动指定时的轴映射(可选,用于特殊坐标系)
+# up_axis = "Y" # 或 "Z"
+# right_axis = "X"
+# front_axis = "Z"
+```
+
+---
+
+## 代码修改示例
+
+### GridMap.cs 修改示例
+
+**修改前**:
+```csharp
+public Point3D GridToWorld3D(GridPoint2D gridPosition)
+{
+ var world2D = GridToWorld2D(gridPosition);
+ var cell = Cells[gridPosition.X, gridPosition.Y];
+ double z = 0;
+ if (cell.HeightLayers != null && cell.HeightLayers.Count > 0)
+ {
+ z = cell.HeightLayers[0].Z; // ❌ 直接访问Z
+ }
+ return new Point3D(world2D.X, world2D.Y, z);
+}
+```
+
+**修改后**:
+```csharp
+public Point3D GridToWorld3D(GridPoint2D gridPosition)
+{
+ var cs = CoordinateSystemManager.Instance.Current;
+ var world2D = GridToWorld2D(gridPosition);
+ var cell = Cells[gridPosition.X, gridPosition.Y];
+
+ double elevation = 0;
+ if (cell.HeightLayers != null && cell.HeightLayers.Count > 0)
+ {
+ elevation = cell.HeightLayers[0].Elevation; // ✅ 使用抽象的高度
+ }
+
+ // 使用坐标系创建点
+ var (h1, h2) = cs.GetHorizontalCoords(world2D);
+ return cs.CreatePoint(h1, h2, elevation);
+}
+```
+
+---
+
+## 实施路线图
+
+### 阶段1:核心适配(P0)- 1-2周
+
+1. 创建坐标系抽象层(ICoordinateSystem + 实现类)
+2. 修改 GridMap 和 GridMapGenerator
+3. 修改 ChannelHeightDetector 的垂直扫描
+4. 添加配置支持
+5. 基础测试验证
+
+### 阶段2:完整适配(P1)- 1周
+
+1. 修改 AutoPathFinder
+2. 修改 GeometryHelper
+3. 修改 PathPointRenderPlugin
+4. 修改 SlopeAnalyzer
+
+### 阶段3:优化完善(P2)- 1周
+
+1. 动画系统适配
+2. 性能优化(缓存转换结果)
+3. 完整测试覆盖
+4. 文档更新
+
+---
+
+## 测试策略
+
+1. **准备测试模型**
+ - Z-up 坐标系的模型(现有)
+ - Y-up 坐标系的模型(客户提供或创建)
+
+2. **验证功能**
+ - 网格生成正确性
+ - 路径规划结果一致性
+ - 高度检测准确性
+ - 渲染显示正确性
+
+3. **回归测试**
+ - 确保Z-up模型仍然正常工作
+ - Y-up模型功能完整
+
+---
+
+## 注意事项
+
+1. **向后兼容**: 默认保持 Z-up 行为,确保现有用户不受影响
+2. **性能**: 坐标转换可能带来轻微性能开销,可通过缓存优化
+3. **文档**: 更新 AGENTS.md 和 README.md,说明坐标系配置方法
+4. **日志**: 在关键位置添加坐标系检测和使用的日志,便于调试
+
+---
+
+*文档创建时间: 2026-01-30*
+*作者: AI Assistant*
+*状态: 设计方案*
diff --git a/doc/working/coordinate-system-detection-results.md b/doc/working/coordinate-system-detection-results.md
new file mode 100644
index 0000000..d5e33b1
--- /dev/null
+++ b/doc/working/coordinate-system-detection-results.md
@@ -0,0 +1,136 @@
+# 坐标系检测结果分析
+
+## 测试模型对比
+
+### 模型1:标准 Z-Up 模型 (Floor2_mobile.nwd)
+
+| 指标 | 值 |
+|------|-----|
+| WorldUpVector | (0, 0, 1) |
+| Transform.Rotation | 0° (无旋转) |
+| 包围盒 Min | Z=-33.51 |
+| 包围盒 Max | Z=88.00 |
+| **判定** | ✅ **Z-Up 坐标系** |
+
+### 模型2:Y-Up 模型 (Floor2_mobile_yup.nwf)
+
+| 指标 | 值 |
+|------|-----|
+| WorldUpVector | **(0, 1, 0)** |
+| Transform.Rotation | **270° 绕 X 轴** |
+| 包围盒 Min | Y=-33.51 |
+| 包围盒 Max | Y=100.56 |
+| **判定** | ✅ **Y-Up 坐标系** |
+
+---
+
+## 关键发现
+
+### 1. WorldUpVector 是最可靠的判断依据
+
+```
+Z-Up 模型: WorldUpVector = (0.0000, 0.0000, 1.0000)
+Y-Up 模型: WorldUpVector = (0.0000, 1.0000, 0.0000)
+```
+
+**结论**:`Viewpoint.WorldUpVector` 直接反映了模型的原始坐标系,无需分析包围盒。
+
+### 2. Navisworks 的自动转换机制
+
+当导入 Y-Up 模型时,Navisworks 会:
+1. **自动旋转模型**:绕 X 轴旋转 270°,将 Y-Up 转为 Z-Up 显示
+2. **保留原始信息**:通过 `WorldUpVector` 记录原始坐标系
+
+这使得:
+- 视觉上所有模型都是 Z-Up
+- 但 `WorldUpVector` 保持原始坐标系
+- 插件需要据此适配内部计算
+
+### 3. 包围盒分析的局限性
+
+Y-Up 模型经过旋转后:
+- 原始 Y 轴(高度)变成了 Z 轴
+- 所以包围盒跨度分析会显示 Z 跨度大
+- 容易产生误判
+
+---
+
+## 正确的检测方法(已实施)
+
+```csharp
+// 方法1:使用 WorldUpVector(推荐)
+var worldUp = doc.CurrentViewpoint.Value.WorldUpVector;
+
+if (Math.Abs(worldUp.Z) > 0.9)
+ return CoordinateSystemType.ZUp; // (0, 0, 1)
+else if (Math.Abs(worldUp.Y) > 0.9)
+ return CoordinateSystemType.YUp; // (0, 1, 0)
+else if (Math.Abs(worldUp.X) > 0.9)
+ return CoordinateSystemType.XUp; // (1, 0, 0) 罕见
+
+// 方法2:辅助检查 Transform 旋转
+var rotation = model.RootItem.Transform.Factor().Rotation.ToAxisAndAngle();
+if (Math.Abs(rotation.Axis.X) > 0.9 &&
+ (Math.Abs(rotation.Angle - Math.PI/2) < 0.1 || Math.Abs(rotation.Angle - 3*Math.PI/2) < 0.1))
+{
+ // 90° 或 270° 绕 X 轴旋转 → Y-Up 模型
+}
+```
+
+---
+
+## 实施建议
+
+### 1. 更新 CoordinateSystemManager
+
+使用 `WorldUpVector` 作为主要检测依据:
+
+```csharp
+private ICoordinateSystem AutoDetectCoordinateSystem()
+{
+ var doc = Application.ActiveDocument;
+ var worldUp = doc.CurrentViewpoint.Value.WorldUpVector;
+
+ if (Math.Abs(worldUp.Y) > 0.9)
+ {
+ LogManager.Info("[坐标系检测] WorldUpVector 表明 Y-Up 坐标系");
+ return new YUpCoordinateSystem();
+ }
+
+ // 默认为 Z-Up
+ return new ZUpCoordinateSystem();
+}
+```
+
+### 2. 用户确认机制
+
+检测后提示用户确认:
+```
+检测到模型使用 Y-Up 坐标系(来自 Revit 等软件)
+是否启用坐标系适配?
+[是] [否] [保持默认]
+```
+
+### 3. 配置文件预设置
+
+在 `default_config.toml` 中:
+```toml
+[coordinate_system]
+# 可选值: "AutoDetect"(推荐), "ZUp", "YUp"
+type = "AutoDetect"
+```
+
+---
+
+## 下一步行动
+
+1. ✅ **已完成**:坐标系探索按钮
+2. ✅ **已完成**:可靠的检测方法(WorldUpVector)
+3. ⏳ **待实施**:更新 `CoordinateSystemManager` 使用新方法
+4. ⏳ **待实施**:实现坐标系抽象层适配
+5. ⏳ **待实施**:修改 GridMap 等核心模块
+
+---
+
+*文档更新时间: 2026-01-30*
+*状态: 检测方法已验证,等待实施适配*
diff --git a/doc/working/navisworks-coordinate-system-api-exploration.md b/doc/working/navisworks-coordinate-system-api-exploration.md
new file mode 100644
index 0000000..9777a44
--- /dev/null
+++ b/doc/working/navisworks-coordinate-system-api-exploration.md
@@ -0,0 +1,313 @@
+# Navisworks API 坐标系探索文档
+
+## 概述
+
+本文档记录 Navisworks API 中关于坐标系获取的探索结果,包括已验证的方法和待验证的潜在方法。
+
+---
+
+## 已验证的 API
+
+### 1. Viewpoint.WorldUpVector
+
+**文件**: `src/Utils/ViewpointHelper.cs` (第119行)
+
+```csharp
+// 获取/设置视角的向上向量
+newViewpoint.WorldUpVector = new UnitVector3D(0, 1, 0);
+```
+
+**说明**:
+- 这是视图级别的向上向量,不是模型级别的坐标系定义
+- 用于控制相机的朝向
+- **局限性**: 可能不同于模型的实际坐标系
+
+---
+
+### 2. Model.Transform
+
+**文件**: `src/Commands/ReadTransformTestCommand.cs` (第30行)
+
+```csharp
+// 获取模型项的变换矩阵
+var transform = item.Transform;
+var components = transform.Factor();
+```
+
+**说明**:
+- 获取单个模型项的局部变换
+- 包含 Translation, Rotation, Scale
+- **局限性**: 这是模型项级别的变换,不是全局坐标系定义
+
+---
+
+### 3. COM API - GetLocalToWorldMatrix
+
+**文件**: `src/Utils/GeometryHelper.cs` (第270行)
+
+```csharp
+// 从 COM API 获取局部到世界的变换矩阵
+var transform = (ComApi.InwLTransform3f3)(object)fragment.GetLocalToWorldMatrix();
+```
+
+**说明**:
+- 用于几何片段的世界坐标变换
+- **局限性**: 几何级别的变换,不是坐标系定义
+
+---
+
+## 待验证的潜在方法
+
+### 方法1: Document 级别的 Orientation 设置
+
+Navisworks 界面中可以通过以下路径设置坐标系:
+```
+File Options → Orientation → Up Vector / North Vector
+```
+
+**可能的 API 路径**:
+
+#### A. COM API 方式 (最有可能)
+```csharp
+// 伪代码 - 待验证
+var comDocument = ComApiBridge.ToInwOpState(Application.ActiveDocument);
+// 或
+var fileOptions = comDocument.FileOptions;
+var orientation = fileOptions.Orientation;
+var upVector = orientation.UpVector; // 可能是 Vector3D 或类似类型
+var northVector = orientation.NorthVector;
+```
+
+#### B. .NET API 方式 (可能不存在)
+```csharp
+// 伪代码 - 待验证
+var doc = Application.ActiveDocument;
+// 可能的属性路径:
+// doc.Options.Orientation.UpVector
+// doc.FileOptions.Orientation.UpVector
+// doc.Settings.Orientation.UpVector
+```
+
+**验证建议**:
+1. 使用 Object Browser 查看 `Autodesk.Navisworks.Api` 中的相关类
+2. 检查 `Document`, `DocumentOptions`, `FileOptions` 等类
+3. 查看 COM API 的 `InwOpState` 或相关接口
+
+---
+
+### 方法2: Model 级别的 Transform
+
+**可能的 API**:
+```csharp
+// 伪代码 - 待验证
+foreach (Model model in Application.ActiveDocument.Models)
+{
+ // 模型可能有一个根级变换
+ var modelTransform = model.Transform;
+ var orientation = modelTransform.Factor().Rotation;
+ // 从旋转矩阵推导坐标系
+}
+```
+
+**验证建议**:
+1. 检查 `Model` 类的属性
+2. 对比不同坐标系模型的 `RootItem.Transform`
+
+---
+
+### 方法3: 通过场景包围盒分析
+
+**思路**: 通过分析模型的包围盒特征推断坐标系
+
+```csharp
+// 启发式检测算法
+public CoordinateSystemType DetectByBoundingBox()
+{
+ var sceneBounds = doc.Models[0].RootItem.BoundingBox();
+
+ double xSpan = sceneBounds.Max.X - sceneBounds.Min.X;
+ double ySpan = sceneBounds.Max.Y - sceneBounds.Min.Y;
+ double zSpan = sceneBounds.Max.Z - sceneBounds.Min.Z;
+
+ // 建筑通常更高而非更深
+ if (ySpan > zSpan * 3 && ySpan > xSpan * 0.5)
+ {
+ return CoordinateSystemType.YUp; // Y轴向上
+ }
+
+ return CoordinateSystemType.ZUp; // 默认 Z轴向上
+}
+```
+
+**局限性**:
+- 不精确,只是启发式猜测
+- 某些建筑可能不符合常规(如横向发展的建筑)
+
+---
+
+### 方法4: 通过典型元素分析
+
+**思路**: 分析楼板、墙等建筑元素的法向量
+
+```csharp
+// 伪代码
+var floorItems = FindItemsByCategory("楼板");
+foreach (var floor in floorItems)
+{
+ // 获取几何并计算法向量
+ var triangles = ExtractTriangles(floor);
+ var normal = CalculateAverageNormal(triangles);
+
+ // 如果法向量主要在 Y 方向,则是 Y-up
+ if (Math.Abs(normal.Y) > 0.9)
+ {
+ return CoordinateSystemType.YUp;
+ }
+}
+```
+
+**局限性**:
+- 需要解析几何,计算量大
+- 需要正确识别楼板元素
+
+---
+
+## 推荐探索代码
+
+创建一个测试命令来探索 API:
+
+```csharp
+using System;
+using System.Windows;
+using Autodesk.Navisworks.Api;
+using Autodesk.Navisworks.Api.Plugins;
+using ComApi = Autodesk.Navisworks.Api.Interop.ComApi;
+using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;
+
+namespace NavisworksTransport.Commands
+{
+ [Plugin("CoordinateSystemExplorer", "NavisworksTransport", DisplayName = "坐标系探索")]
+ [AddInPlugin(AddInLocation.AddIn)]
+ public class CoordinateSystemExplorerCommand : AddInPlugin
+ {
+ public override int Execute(params string[] parameters)
+ {
+ var doc = Application.ActiveDocument;
+ var sb = new System.Text.StringBuilder();
+
+ sb.AppendLine("=== 坐标系探索 ===\n");
+
+ // 1. 检查 Document 级别的选项
+ sb.AppendLine("1. Document 级别信息:");
+ sb.AppendLine($" 文档名称: {doc.FileName}");
+ sb.AppendLine($" 模型数量: {doc.Models.Count}");
+ sb.AppendLine();
+
+ // 2. 检查每个模型的信息
+ sb.AppendLine("2. Model 级别信息:");
+ foreach (Model model in doc.Models)
+ {
+ sb.AppendLine($" 模型: {model.Title}");
+ sb.AppendLine($" - RootItem.Name: {model.RootItem.DisplayName}");
+ sb.AppendLine($" - RootItem.Transform: {model.RootItem.Transform}");
+
+ var bbox = model.RootItem.BoundingBox();
+ sb.AppendLine($" - 包围盒: [{bbox.Min.X:F2}, {bbox.Min.Y:F2}, {bbox.Min.Z:F2}] - [{bbox.Max.X:F2}, {bbox.Max.Y:F2}, {bbox.Max.Z:F2}]");
+ sb.AppendLine();
+ }
+
+ // 3. 检查 COM API
+ sb.AppendLine("3. COM API 探索:");
+ try
+ {
+ var comState = ComApiBridge.ToInwOpState(doc);
+ // 尝试访问 FileOptions 或 Orientation
+ // 注意:这部分需要根据实际 COM API 结构调整
+ sb.AppendLine($" COM State 类型: {comState.GetType().Name}");
+ }
+ catch (Exception ex)
+ {
+ sb.AppendLine($" COM API 访问失败: {ex.Message}");
+ }
+ sb.AppendLine();
+
+ // 4. 检查 Viewpoint
+ sb.AppendLine("4. Viewpoint 信息:");
+ var vp = doc.CurrentViewpoint.Value;
+ sb.AppendLine($" WorldUpVector: ({vp.WorldUpVector.X}, {vp.WorldUpVector.Y}, {vp.WorldUpVector.Z})");
+ sb.AppendLine($" Position: ({vp.Position.X:F2}, {vp.Position.Y:F2}, {vp.Position.Z:F2})");
+ sb.AppendLine();
+
+ // 5. 包围盒分析
+ sb.AppendLine("5. 包围盒分析:");
+ var sceneBounds = doc.Models[0].RootItem.BoundingBox();
+ double xSpan = sceneBounds.Max.X - sceneBounds.Min.X;
+ double ySpan = sceneBounds.Max.Y - sceneBounds.Min.Y;
+ double zSpan = sceneBounds.Max.Z - sceneBounds.Min.Z;
+ sb.AppendLine($" X 跨度: {xSpan:F2}");
+ sb.AppendLine($" Y 跨度: {ySpan:F2}");
+ sb.AppendLine($" Z 跨度: {zSpan:F2}");
+ sb.AppendLine($" 检测建议: {(ySpan > zSpan * 3 ? "可能是 Y-Up" : "可能是 Z-Up")}");
+
+ // 显示结果
+ MessageBox.Show(sb.ToString(), "坐标系探索结果");
+ LogManager.Info(sb.ToString());
+
+ return 0;
+ }
+ }
+}
+```
+
+---
+
+## 下一步行动建议
+
+### 立即行动
+
+1. **创建探索命令**
+ - 实现上面的 `CoordinateSystemExplorerCommand`
+ - 在客户模型上运行,记录结果
+ - 在标准 Z-up 模型上运行,对比结果
+
+2. **Object Browser 检查**
+ - 打开 Visual Studio 的 Object Browser
+ - 查看 `Autodesk.Navisworks.Api` 程序集
+ - 搜索关键词: `Orientation`, `FileOptions`, `UpVector`, `North`
+
+3. **COM API 文档检查**
+ - 打开 `doc\navisworks_api\COM\documentation\NavisWorksCOM.chm`
+ - 搜索 `FileOptions`, `Orientation`
+
+### 短期行动
+
+1. **如果找到 API**
+ - 更新 `CoordinateSystemManager` 使用官方 API
+ - 简化自动检测逻辑
+
+2. **如果没有找到 API**
+ - 完善启发式检测算法
+ - 增加用户手动配置选项
+ - 考虑通过 UI 提示用户确认检测到的坐标系
+
+---
+
+## 相关资源
+
+### 内部文档
+- `doc\navisworks_api\NET\documentation\NET API.chm`
+- `doc\navisworks_api\COM\documentation\NavisWorksCOM.chm`
+
+### 外部链接
+- [Autodesk Forum: Setting File Options Up- and North-orientation](https://forums.autodesk.com/t5/navisworks-api-forum/setting-file-options-up-and-north-orientation-using-navisworks/td-p/11795216)
+- [How to change model orientation in Navisworks](https://www.autodesk.com/support/technical/article/caas/sfdcarticles/sfdcarticles/How-to-change-model-orientation-in-Navisworks.html)
+
+### 参考文件
+- `src/Utils/ViewpointHelper.cs` - Viewpoint.WorldUpVector 使用示例
+- `src/Commands/ReadTransformTestCommand.cs` - Transform 读取示例
+- `src/Utils/GeometryHelper.cs` - COM API Transform 使用示例
+
+---
+
+*文档创建时间: 2026-01-30*
+*状态: 探索中*
diff --git a/src/Commands/CoordinateSystemExplorerCommand.cs b/src/Commands/CoordinateSystemExplorerCommand.cs
new file mode 100644
index 0000000..ad14490
--- /dev/null
+++ b/src/Commands/CoordinateSystemExplorerCommand.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using Autodesk.Navisworks.Api;
+using Autodesk.Navisworks.Api.Plugins;
+using ComApi = Autodesk.Navisworks.Api.Interop.ComApi;
+using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;
+using NavisworksTransport.Utils;
+
+namespace NavisworksTransport.Commands
+{
+ ///
+ /// 坐标系探索命令 - 用于探索 Navisworks API 中的坐标系相关信息
+ ///
+ [Plugin("CoordinateSystemExplorer", "NavisworksTransport", DisplayName = "坐标系探索")]
+ [AddInPlugin(AddInLocation.AddIn)]
+ public class CoordinateSystemExplorerCommand : AddInPlugin
+ {
+ public override int Execute(params string[] parameters)
+ {
+ try
+ {
+ var doc = Application.ActiveDocument;
+ if (doc == null || doc.IsClear)
+ {
+ MessageBox.Show("没有活动的文档!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ return 1;
+ }
+
+ var sb = new StringBuilder();
+ sb.AppendLine("=== Navisworks 坐标系探索 ===\n");
+
+ // 1. Document 级别信息
+ sb.AppendLine("【1. Document 级别信息】");
+ sb.AppendLine($"文档名称: {doc.FileName}");
+ sb.AppendLine($"文档标题: {doc.Title}");
+ sb.AppendLine($"模型数量: {doc.Models.Count}");
+ sb.AppendLine();
+
+ // 2. Model 级别信息
+ sb.AppendLine("【2. Model 级别信息】");
+ int modelIndex = 0;
+ foreach (Model model in doc.Models)
+ {
+ sb.AppendLine($"模型 [{modelIndex}]: {model.Title}");
+ sb.AppendLine($" - 源文件名: {model.SourceFileName}");
+ sb.AppendLine($" - 源格式: {model.SourceFileFormat}");
+
+ var rootItem = model.RootItem;
+ if (rootItem != null)
+ {
+ sb.AppendLine($" - RootItem.DisplayName: {rootItem.DisplayName}");
+ sb.AppendLine($" - RootItem.Transform: {rootItem.Transform}");
+
+ var components = rootItem.Transform.Factor();
+ sb.AppendLine($" - Transform.Translation: ({components.Translation.X:F4}, {components.Translation.Y:F4}, {components.Translation.Z:F4})");
+ sb.AppendLine($" - Transform.Rotation.Axis: ({components.Rotation.Axis.X:F4}, {components.Rotation.Axis.Y:F4}, {components.Rotation.Axis.Z:F4})");
+ sb.AppendLine($" - Transform.Rotation.Angle: {components.Rotation.Angle:F6} rad ({components.Rotation.Angle * 180 / Math.PI:F2}°)");
+ sb.AppendLine($" - Transform.Scale: ({components.Scale.X:F4}, {components.Scale.Y:F4}, {components.Scale.Z:F4})");
+
+ var bbox = rootItem.BoundingBox();
+ sb.AppendLine($" - 包围盒 Min: ({bbox.Min.X:F4}, {bbox.Min.Y:F4}, {bbox.Min.Z:F4})");
+ sb.AppendLine($" - 包围盒 Max: ({bbox.Max.X:F4}, {bbox.Max.Y:F4}, {bbox.Max.Z:F4})");
+
+ double xSpan = bbox.Max.X - bbox.Min.X;
+ double ySpan = bbox.Max.Y - bbox.Min.Y;
+ double zSpan = bbox.Max.Z - bbox.Min.Z;
+ sb.AppendLine($" - 跨度: X={xSpan:F2}, Y={ySpan:F2}, Z={zSpan:F2}");
+ sb.AppendLine($" - 坐标系推测: {(ySpan > zSpan * 2 ? "可能是 Y-Up" : "可能是 Z-Up")}");
+ }
+ sb.AppendLine();
+ modelIndex++;
+ }
+
+ // 3. 当前选择项的 Transform 详情
+ sb.AppendLine("【3. 当前选择项信息】");
+ var selection = doc.CurrentSelection.SelectedItems;
+ if (selection.Count > 0)
+ {
+ var item = selection.First();
+ sb.AppendLine($"选中项: {item.DisplayName}");
+ sb.AppendLine($" - ClassName: {item.ClassName}");
+ sb.AppendLine($" - ClassDisplayName: {item.ClassDisplayName}");
+ sb.AppendLine($" - HasGeometry: {item.HasGeometry}");
+
+ var transform = item.Transform;
+ var comp = transform.Factor();
+ sb.AppendLine($" - Transform.Translation: ({comp.Translation.X:F4}, {comp.Translation.Y:F4}, {comp.Translation.Z:F4})");
+ sb.AppendLine($" - Transform.Rotation.Axis: ({comp.Rotation.Axis.X:F4}, {comp.Rotation.Axis.Y:F4}, {comp.Rotation.Axis.Z:F4})");
+ sb.AppendLine($" - Transform.Rotation.Angle: {comp.Rotation.Angle:F6} rad");
+
+ var itemBbox = item.BoundingBox();
+ sb.AppendLine($" - 包围盒 Center: ({itemBbox.Center.X:F4}, {itemBbox.Center.Y:F4}, {itemBbox.Center.Z:F4})");
+ }
+ else
+ {
+ sb.AppendLine("当前没有选择项");
+ }
+ sb.AppendLine();
+
+ // 4. Viewpoint 信息
+ sb.AppendLine("【4. Viewpoint 信息】");
+ var vp = doc.CurrentViewpoint.Value;
+ sb.AppendLine($"WorldUpVector: ({vp.WorldUpVector.X:F4}, {vp.WorldUpVector.Y:F4}, {vp.WorldUpVector.Z:F4})");
+ sb.AppendLine($"Position: ({vp.Position.X:F4}, {vp.Position.Y:F4}, {vp.Position.Z:F4})");
+ sb.AppendLine($"Rotation.Axis: ({vp.Rotation.Axis.X:F4}, {vp.Rotation.Axis.Y:F4}, {vp.Rotation.Axis.Z:F4})");
+ sb.AppendLine($"Rotation.Angle: {vp.Rotation.Angle:F6} rad");
+ sb.AppendLine();
+
+ // 5. COM API 探索
+ sb.AppendLine("【5. COM API 探索】");
+ try
+ {
+ var comState = ComApiBridge.ToInwOpState(doc);
+ sb.AppendLine($"COM State 类型: {comState.GetType().FullName}");
+
+ // 尝试获取模型的 COM 表示
+ if (doc.Models.Count > 0)
+ {
+ var firstModel = doc.Models[0];
+ // 注意:这里可能需要不同的方法来获取 COM 模型对象
+ sb.AppendLine($"尝试访问 COM 模型对象...");
+
+ // 通过选择获取 COM 对象
+ var modelCollection = new ModelItemCollection { firstModel.RootItem };
+ var comSelection = ComApiBridge.ToInwOpSelection(modelCollection);
+ sb.AppendLine($"COM Selection 路径数: {comSelection.Paths().Count}");
+
+ // 释放 COM 对象
+ System.Runtime.InteropServices.Marshal.ReleaseComObject(comSelection);
+ }
+
+ sb.AppendLine("COM API 访问成功");
+ }
+ catch (Exception ex)
+ {
+ sb.AppendLine($"COM API 访问失败: {ex.Message}");
+ sb.AppendLine($"堆栈: {ex.StackTrace}");
+ }
+ sb.AppendLine();
+
+ // 6. 坐标系推测总结
+ sb.AppendLine("【6. 坐标系推测总结】");
+ if (doc.Models.Count > 0)
+ {
+ var rootBounds = doc.Models[0].RootItem.BoundingBox();
+ double xSpan = rootBounds.Max.X - rootBounds.Min.X;
+ double ySpan = rootBounds.Max.Y - rootBounds.Min.Y;
+ double zSpan = rootBounds.Max.Z - rootBounds.Min.Z;
+
+ sb.AppendLine($"模型跨度分析:");
+ sb.AppendLine($" - X (左右): {xSpan:F2} 单位");
+ sb.AppendLine($" - Y (前后/上下): {ySpan:F2} 单位");
+ sb.AppendLine($" - Z (上下/前后): {zSpan:F2} 单位");
+ sb.AppendLine();
+
+ sb.AppendLine($"启发式判断:");
+ if (ySpan > zSpan * 3)
+ {
+ sb.AppendLine($" - Y 跨度显著大于 Z 跨度 ({ySpan/zSpan:F1}x)");
+ sb.AppendLine($" - 推测: Y-Up 坐标系 (Y轴向上)");
+ }
+ else if (zSpan > ySpan * 3)
+ {
+ sb.AppendLine($" - Z 跨度显著大于 Y 跨度 ({zSpan/ySpan:F1}x)");
+ sb.AppendLine($" - 推测: Z-Up 坐标系 (Z轴向上)");
+ }
+ else
+ {
+ sb.AppendLine($" - Y 和 Z 跨度相近");
+ sb.AppendLine($" - 无法确定坐标系,可能是特殊模型或 Z-Up");
+ }
+ }
+
+ // 显示结果
+ string result = sb.ToString();
+
+ // 保存到日志
+ LogManager.Info(result);
+
+ // 显示对话框(如果内容太长,可能需要截断)
+ const int maxLength = 4000;
+ string displayText = result.Length > maxLength
+ ? result.Substring(0, maxLength) + "\n\n... (内容已截断,请查看完整日志)"
+ : result;
+
+ MessageBox.Show(displayText, "坐标系探索结果", MessageBoxButton.OK, MessageBoxImage.Information);
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ string errorMsg = $"坐标系探索失败: {ex.Message}\n{ex.StackTrace}";
+ LogManager.Error(errorMsg);
+ MessageBox.Show(errorMsg, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ return 1;
+ }
+ }
+ }
+}
diff --git a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs
index 5fb20c1..97e9976 100644
--- a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs
+++ b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.ObjectModel;
+using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using NavisworksTransport.UI.WPF.Collections;
@@ -116,6 +117,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public ICommand TestVoxelGridSDFCommand { get; private set; }
public ICommand TestVoxelPathFindingCommand { get; private set; }
public ICommand ReadTransformTestCommand { get; private set; }
+ public ICommand CoordinateSystemExplorerCommand { get; private set; }
#endregion
@@ -220,6 +222,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
TestVoxelGridSDFCommand = new RelayCommand(() => ExecuteTestVoxelGridSDF());
TestVoxelPathFindingCommand = new RelayCommand(() => ExecuteTestVoxelPathFinding());
ReadTransformTestCommand = new RelayCommand(() => ExecuteReadTransformTest());
+ CoordinateSystemExplorerCommand = new RelayCommand(() => ExecuteCoordinateSystemExplorer());
LogManager.Info("系统管理命令初始化完成");
}
@@ -845,6 +848,296 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
+ ///
+ /// 执行坐标系探索命令
+ ///
+ private void ExecuteCoordinateSystemExplorer()
+ {
+ SafeExecute(() =>
+ {
+ try
+ {
+ UpdateMainStatus("正在执行坐标系探索...");
+ LogManager.Info("开始坐标系探索");
+
+ var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
+ if (doc == null || doc.IsClear)
+ {
+ System.Windows.MessageBox.Show(
+ "没有活动的文档!请先打开一个模型。",
+ "错误",
+ System.Windows.MessageBoxButton.OK,
+ System.Windows.MessageBoxImage.Error);
+ UpdateMainStatus("坐标系探索失败:无活动文档");
+ return;
+ }
+
+ var sb = new StringBuilder();
+ sb.AppendLine("=== Navisworks 坐标系探索 ===\n");
+
+ // 1. Document 级别信息
+ sb.AppendLine("【1. Document 级别信息】");
+ sb.AppendLine($"文档名称: {doc.FileName}");
+ sb.AppendLine($"文档标题: {doc.Title}");
+ sb.AppendLine($"模型数量: {doc.Models.Count}");
+ sb.AppendLine();
+
+ // 2. Model 级别信息
+ sb.AppendLine("【2. Model 级别信息】");
+ int modelIndex = 0;
+ foreach (var model in doc.Models)
+ {
+ sb.AppendLine($"模型 [{modelIndex}]:");
+
+ var rootItem = model.RootItem;
+ if (rootItem != null)
+ {
+ sb.AppendLine($" - RootItem.DisplayName: {rootItem.DisplayName}");
+
+ var components = rootItem.Transform.Factor();
+ sb.AppendLine($" - Transform.Translation: ({components.Translation.X:F4}, {components.Translation.Y:F4}, {components.Translation.Z:F4})");
+ var rotation = components.Rotation;
+ // Rotation3D 使用 ToAxisAndAngle() 方法获取轴和角度
+ var axisAngle = rotation.ToAxisAndAngle();
+ sb.AppendLine($" - Transform.Rotation.Axis: ({axisAngle.Axis.X:F4}, {axisAngle.Axis.Y:F4}, {axisAngle.Axis.Z:F4})");
+ sb.AppendLine($" - Transform.Rotation.Angle: {axisAngle.Angle:F6} rad ({axisAngle.Angle * 180 / Math.PI:F2}°)");
+ sb.AppendLine($" - Transform.Scale: ({components.Scale.X:F4}, {components.Scale.Y:F4}, {components.Scale.Z:F4})");
+
+ var bbox = rootItem.BoundingBox();
+ sb.AppendLine($" - 包围盒 Min: ({bbox.Min.X:F4}, {bbox.Min.Y:F4}, {bbox.Min.Z:F4})");
+ sb.AppendLine($" - 包围盒 Max: ({bbox.Max.X:F4}, {bbox.Max.Y:F4}, {bbox.Max.Z:F4})");
+
+ double xSpan = bbox.Max.X - bbox.Min.X;
+ double ySpan = bbox.Max.Y - bbox.Min.Y;
+ double zSpan = bbox.Max.Z - bbox.Min.Z;
+ sb.AppendLine($" - 跨度: X={xSpan:F2}, Y={ySpan:F2}, Z={zSpan:F2}");
+ sb.AppendLine($" - 坐标系推测: {(ySpan > zSpan * 2 ? "可能是 Y-Up" : "可能是 Z-Up")}");
+ }
+ sb.AppendLine();
+ modelIndex++;
+ }
+
+ // 3. Document 坐标系向量 (直接来自模型)
+ sb.AppendLine("【3. Document 坐标系向量 (模型原始)】");
+ var docUp = doc.UpVector;
+ var docRight = doc.RightVector;
+ var docFront = doc.FrontVector;
+
+ if (docUp.IsZero)
+ {
+ sb.AppendLine("UpVector: (0, 0, 0) - 未定义");
+ }
+ else
+ {
+ sb.AppendLine($"UpVector: ({docUp.X:F4}, {docUp.Y:F4}, {docUp.Z:F4})");
+ }
+
+ if (docRight.IsZero)
+ {
+ sb.AppendLine("RightVector: (0, 0, 0) - 未定义");
+ }
+ else
+ {
+ sb.AppendLine($"RightVector: ({docRight.X:F4}, {docRight.Y:F4}, {docRight.Z:F4})");
+ }
+
+ if (docFront.IsZero)
+ {
+ sb.AppendLine("FrontVector: (0, 0, 0) - 未定义");
+ }
+ else
+ {
+ sb.AppendLine($"FrontVector: ({docFront.X:F4}, {docFront.Y:F4}, {docFront.Z:F4})");
+ }
+ sb.AppendLine();
+
+ // 4. Viewpoint 信息 (Navisworks 处理后的)
+ sb.AppendLine("【4. Viewpoint 信息 (Navisworks 处理后)】");
+ var vp = doc.CurrentViewpoint.Value;
+ sb.AppendLine($"WorldUpVector: ({vp.WorldUpVector.X:F4}, {vp.WorldUpVector.Y:F4}, {vp.WorldUpVector.Z:F4})");
+ sb.AppendLine($"Position: ({vp.Position.X:F4}, {vp.Position.Y:F4}, {vp.Position.Z:F4})");
+ var vpRotation = vp.Rotation.ToAxisAndAngle();
+ sb.AppendLine($"Rotation.Axis: ({vpRotation.Axis.X:F4}, {vpRotation.Axis.Y:F4}, {vpRotation.Axis.Z:F4})");
+ sb.AppendLine($"Rotation.Angle: {vpRotation.Angle:F6} rad");
+ sb.AppendLine();
+
+ // 5. 坐标系推测总结
+ sb.AppendLine("【5. 坐标系推测总结】");
+
+ // 方法1: 优先使用 Document.UpVector 判断(模型原始定义)
+ sb.AppendLine($"方法1 - Document.UpVector (原始):");
+ if (!docUp.IsZero)
+ {
+ sb.AppendLine($" 值: ({docUp.X:F4}, {docUp.Y:F4}, {docUp.Z:F4})");
+
+ if (Math.Abs(docUp.Z) > 0.9)
+ {
+ sb.AppendLine($" ✅ 判定: Z-Up 坐标系 (原始)");
+ }
+ else if (Math.Abs(docUp.Y) > 0.9)
+ {
+ sb.AppendLine($" ✅ 判定: Y-Up 坐标系 (原始)");
+ }
+ else if (Math.Abs(docUp.X) > 0.9)
+ {
+ sb.AppendLine($" ⚠️ 判定: X-Up 坐标系 (罕见)");
+ }
+ }
+ else
+ {
+ sb.AppendLine($" 未定义 (Zero),需使用 Viewpoint.WorldUpVector");
+ }
+ sb.AppendLine();
+
+ // 方法2: 使用 WorldUpVector 判断(Navisworks 处理后的,最可靠)
+ var worldUp = doc.CurrentViewpoint.Value.WorldUpVector;
+ sb.AppendLine($"方法2 - Viewpoint.WorldUpVector (推荐):");
+ sb.AppendLine($" 值: ({worldUp.X:F4}, {worldUp.Y:F4}, {worldUp.Z:F4})");
+
+ string detectedCoordinateSystem = "Unknown";
+ if (Math.Abs(worldUp.Z) > 0.9)
+ {
+ sb.AppendLine($" ✅ 判定: Z-Up 坐标系 (Z轴向上)");
+ sb.AppendLine($" 说明: 这是 Navisworks 默认坐标系,插件无需特殊配置");
+ detectedCoordinateSystem = "ZUp";
+ }
+ else if (Math.Abs(worldUp.Y) > 0.9)
+ {
+ sb.AppendLine($" ✅ 判定: Y-Up 坐标系 (Y轴向上)");
+ sb.AppendLine($" 说明: 通常是 Revit 等软件导出的模型");
+ sb.AppendLine($" 建议: 在 default_config.toml 中设置坐标系为 YUp");
+ detectedCoordinateSystem = "YUp";
+ }
+ else if (Math.Abs(worldUp.X) > 0.9)
+ {
+ sb.AppendLine($" ⚠️ 判定: X-Up 坐标系 (罕见)");
+ sb.AppendLine($" 说明: 非标准坐标系,需要手动适配");
+ detectedCoordinateSystem = "XUp";
+ }
+ else
+ {
+ sb.AppendLine($" ❓ 判定: 无法确定(非标准向上向量)");
+ }
+ sb.AppendLine();
+
+ // 方法3: 通过模型 Transform 旋转判断(辅助验证)
+ sb.AppendLine($"方法3 - 模型 Transform 旋转:");
+ if (doc.Models.Count > 0)
+ {
+ var rootItem = doc.Models[0].RootItem;
+ if (rootItem != null)
+ {
+ var components = rootItem.Transform.Factor();
+ var rotation = components.Rotation.ToAxisAndAngle();
+ double angleDegrees = rotation.Angle * 180 / Math.PI;
+
+ sb.AppendLine($" 旋转轴: ({rotation.Axis.X:F4}, {rotation.Axis.Y:F4}, {rotation.Axis.Z:F4})");
+ sb.AppendLine($" 旋转角: {angleDegrees:F2}°");
+
+ // 检查是否有 90° 或 270° 绕 X 轴旋转(Y-Up 模型的典型特征)
+ if (Math.Abs(rotation.Axis.X) > 0.9 &&
+ (Math.Abs(angleDegrees - 90) < 5 || Math.Abs(angleDegrees - 270) < 5))
+ {
+ sb.AppendLine($" ✅ 发现 X 轴旋转 ~{angleDegrees:F0}°,这是 Y-Up 导入的典型特征");
+ }
+ else if (Math.Abs(angleDegrees) < 1)
+ {
+ sb.AppendLine($" 无显著旋转,符合 Z-Up 模型特征");
+ }
+ }
+ }
+ sb.AppendLine();
+
+ // 方法4: 包围盒跨度分析(启发式)
+ sb.AppendLine($"方法4 - 包围盒跨度分析(启发式):");
+ if (doc.Models.Count > 0)
+ {
+ var rootBounds = doc.Models[0].RootItem.BoundingBox();
+ double xSpan = rootBounds.Max.X - rootBounds.Min.X;
+ double ySpan = rootBounds.Max.Y - rootBounds.Min.Y;
+ double zSpan = rootBounds.Max.Z - rootBounds.Min.Z;
+
+ sb.AppendLine($" X 跨度: {xSpan:F2} 单位");
+ sb.AppendLine($" Y 跨度: {ySpan:F2} 单位");
+ sb.AppendLine($" Z 跨度: {zSpan:F2} 单位");
+
+ // 注意:经过旋转后,Y-Up 模型在 Navisworks 中显示为 Z-Up
+ // 所以这里看到的是转换后的坐标
+ if (zSpan > ySpan * 1.5)
+ {
+ sb.AppendLine($" Z 跨度大于 Y 跨度,显示为 Z-Up 方向");
+ }
+ else if (ySpan > zSpan * 1.5)
+ {
+ sb.AppendLine($" Y 跨度大于 Z 跨度,可能未完全转换");
+ }
+ }
+ sb.AppendLine();
+
+ // 最终建议
+ sb.AppendLine($"【最终建议】");
+ if (detectedCoordinateSystem == "YUp")
+ {
+ sb.AppendLine($"⚠️ 检测到 Y-Up 坐标系!");
+ sb.AppendLine($"当前插件使用 Z-Up 假设,在此模型上可能出现问题。");
+ sb.AppendLine($"建议:实施坐标系动态适配功能。");
+ }
+ else if (detectedCoordinateSystem == "ZUp")
+ {
+ sb.AppendLine($"✅ 标准 Z-Up 坐标系,插件应正常工作。");
+ }
+
+ // 显示和记录结果
+ string result = sb.ToString();
+ LogManager.Info(result);
+
+ // 使用可复制的对话框显示结果
+ var resultDialog = new NavisworksTransport.UI.WPF.Views.CoordinateSystemResultDialog
+ {
+ Title = "坐标系探索结果",
+ ResultText = result
+ };
+
+ // 尝试设置对话框所有者
+ try
+ {
+ var mainWindow = System.Windows.Application.Current?.MainWindow;
+ if (mainWindow != null && mainWindow.IsLoaded)
+ {
+ resultDialog.Owner = mainWindow;
+ }
+ else
+ {
+ foreach (System.Windows.Window window in System.Windows.Application.Current.Windows)
+ {
+ if (window.IsActive && window.IsLoaded)
+ {
+ resultDialog.Owner = window;
+ break;
+ }
+ }
+ }
+ }
+ catch { }
+
+ resultDialog.ShowDialog();
+
+ UpdateMainStatus("坐标系探索完成");
+ LogManager.Info("坐标系探索成功完成");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"坐标系探索异常: {ex.Message}", ex);
+ System.Windows.MessageBox.Show(
+ $"坐标系探索出现异常:\n{ex.Message}",
+ "错误",
+ System.Windows.MessageBoxButton.OK,
+ System.Windows.MessageBoxImage.Error);
+ UpdateMainStatus($"坐标系探索异常: {ex.Message}");
+ }
+ }, "坐标系探索");
+ }
+
#endregion
#region 辅助方法
diff --git a/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml b/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml
new file mode 100644
index 0000000..c39fe65
--- /dev/null
+++ b/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml.cs b/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml.cs
new file mode 100644
index 0000000..690af4b
--- /dev/null
+++ b/src/UI/WPF/Views/CoordinateSystemResultDialog.xaml.cs
@@ -0,0 +1,78 @@
+using System.Windows;
+using System.Windows.Controls;
+
+namespace NavisworksTransport.UI.WPF.Views
+{
+ ///
+ /// 坐标系探索结果对话框 - 支持文本选择和复制
+ ///
+ public partial class CoordinateSystemResultDialog : Window
+ {
+ public CoordinateSystemResultDialog()
+ {
+ InitializeComponent();
+ }
+
+ ///
+ /// 设置要显示的结果文本
+ ///
+ public string ResultText
+ {
+ get => ResultTextBox.Text;
+ set => ResultTextBox.Text = value;
+ }
+
+ ///
+ /// 复制按钮点击事件
+ ///
+ private void CopyButton_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ Clipboard.SetText(ResultTextBox.Text);
+ MessageBox.Show("内容已复制到剪贴板!", "复制成功", MessageBoxButton.OK, MessageBoxImage.Information);
+ }
+ catch (System.Exception ex)
+ {
+ MessageBox.Show($"复制失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+
+ ///
+ /// 确定按钮点击事件
+ ///
+ private void OkButton_Click(object sender, RoutedEventArgs e)
+ {
+ DialogResult = true;
+ Close();
+ }
+
+ ///
+ /// 静态方法,方便调用显示结果
+ ///
+ public static void ShowResult(string title, string content, Window owner = null)
+ {
+ var dialog = new CoordinateSystemResultDialog
+ {
+ Title = title,
+ ResultText = content
+ };
+
+ if (owner != null)
+ {
+ dialog.Owner = owner;
+ }
+ else
+ {
+ // 尝试设置当前活动窗口为所有者
+ try
+ {
+ dialog.Owner = System.Windows.Application.Current?.MainWindow;
+ }
+ catch { }
+ }
+
+ dialog.ShowDialog();
+ }
+ }
+}
diff --git a/src/UI/WPF/Views/SystemManagementView.xaml b/src/UI/WPF/Views/SystemManagementView.xaml
index 20309d2..99f699e 100644
--- a/src/UI/WPF/Views/SystemManagementView.xaml
+++ b/src/UI/WPF/Views/SystemManagementView.xaml
@@ -174,6 +174,12 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
Command="{Binding ReadTransformTestCommand}"
Style="{StaticResource ActionButtonStyle}"
ToolTip="读取选中对象的Transform信息(包括旋转角度)"/>
+
+
+