using System;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using NavisworksTransport.UI.WPF.Collections;
using NavisworksTransport.Core;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Utils;
using NavisworksTransport.Utils.CoordinateSystem;
using NavisworksTransport.Commands;
namespace NavisworksTransport.UI.WPF.ViewModels
{
///
/// 系统管理ViewModel - 处理插件系统管理功能
///
public class SystemManagementViewModel : ViewModelBase, IDisposable
{
#region 私有字段
private readonly UIStateManager _uiStateManager;
// 日志管理字段
private ObservableCollection _logLevels;
private string _selectedLogLevel = "Info";
private string _pluginVersion = "v1.0";
private string _navisworksVersion = "2026";
private string _memoryUsage = "0 MB";
private string _runningTime = "00:00:00";
// 数据管理字段
private string _databaseVersion = "--";
private string _pathCount = "--";
private string _collisionRecordCount = "--";
private bool _autoBackupEnabled = true;
private int _selectedBackupKeepCount = 10;
private string _lastBackupInfo = "暂无备份记录";
// 🔧 修复:添加释放状态标志
private bool _disposed = false;
#endregion
#region 公共属性
///
/// 日志级别集合
///
public ObservableCollection LogLevels
{
get => _logLevels;
set => SetProperty(ref _logLevels, value);
}
///
/// 选中的日志级别
///
public string SelectedLogLevel
{
get => _selectedLogLevel;
set
{
if (SetProperty(ref _selectedLogLevel, value))
{
// 将字符串转换为LogLevel枚举并设置
if (Enum.TryParse(value, out var level))
{
LogManager.SetLogLevel(level);
LogManager.Info($"日志级别已更改为: {value}");
UpdateMainStatus($"日志级别已设置为: {value}");
}
}
}
}
///
/// 插件版本
///
public string PluginVersion
{
get => _pluginVersion;
set => SetProperty(ref _pluginVersion, value);
}
///
/// Navisworks版本
///
public string NavisworksVersion
{
get => _navisworksVersion;
set => SetProperty(ref _navisworksVersion, value);
}
///
/// 内存使用情况
///
public string MemoryUsage
{
get => _memoryUsage;
set => SetProperty(ref _memoryUsage, value);
}
///
/// 运行时间
///
public string RunningTime
{
get => _runningTime;
set => SetProperty(ref _runningTime, value);
}
// 数据管理属性
public string DatabaseVersion
{
get => _databaseVersion;
set => SetProperty(ref _databaseVersion, value);
}
public string PathCount
{
get => _pathCount;
set => SetProperty(ref _pathCount, value);
}
public string CollisionRecordCount
{
get => _collisionRecordCount;
set => SetProperty(ref _collisionRecordCount, value);
}
public bool AutoBackupEnabled
{
get => _autoBackupEnabled;
set => SetProperty(ref _autoBackupEnabled, value);
}
public ObservableCollection BackupKeepCountOptions { get; } = new ObservableCollection { 5, 10, 20, 50 };
public int SelectedBackupKeepCount
{
get => _selectedBackupKeepCount;
set => SetProperty(ref _selectedBackupKeepCount, value);
}
public string LastBackupInfo
{
get => _lastBackupInfo;
set => SetProperty(ref _lastBackupInfo, value);
}
#endregion
#region 命令
public ICommand ViewLogCommand { get; private set; }
public ICommand OpenSettingsCommand { get; private set; }
public ICommand CheckUpdateCommand { get; private set; }
public ICommand GeneratePerformanceReportCommand { get; private set; }
public ICommand DiagnosticCommand { get; private set; }
// 数据管理命令
public ICommand BackupDataCommand { get; private set; }
public ICommand RestoreDataCommand { get; private set; }
public ICommand RepairDatabaseCommand { get; private set; }
public ICommand ClearAllDataCommand { get; private set; }
// 功能测试命令
public ICommand TestVoxelGridSDFCommand { get; private set; }
public ICommand TestVoxelPathFindingCommand { get; private set; }
public ICommand ReadTransformTestCommand { get; private set; }
public ICommand CoordinateSystemExplorerCommand { get; private set; }
// 坐标系设置
public ObservableCollection CoordinateSystemOptions { get; private set; }
private string _selectedCoordinateSystem = "AutoDetect";
public string SelectedCoordinateSystem
{
get => _selectedCoordinateSystem;
set
{
if (SetProperty(ref _selectedCoordinateSystem, value))
{
OnCoordinateSystemChanged(value);
}
}
}
private string _currentCoordinateSystemInfo = "当前坐标系: 未初始化";
public string CurrentCoordinateSystemInfo
{
get => _currentCoordinateSystemInfo;
set => SetProperty(ref _currentCoordinateSystemInfo, value);
}
#endregion
#region 构造函数
public SystemManagementViewModel() : base()
{
try
{
// 获取UI状态管理器实例
_uiStateManager = UIStateManager.Instance;
// 验证关键组件是否正常初始化
if (_uiStateManager == null)
{
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
// 初始化日志级别集合
LogLevels = new ThreadSafeObservableCollection();
// 初始化命令
InitializeCommands();
// 初始化系统管理设置
_ = InitializeSystemManagementSettingsAsync();
// 订阅文档切换事件,以便重新检测坐标系
SubscribeToDocumentEvents();
LogManager.Info("SystemManagementViewModel构造函数执行完成");
}
catch (Exception ex)
{
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
// 在构造函数中尽量保证对象处于可用状态
UpdateMainStatus("初始化失败,请检查日志");
throw;
}
}
///
/// 带主ViewModel参数的构造函数,支持统一状态栏
///
/// 主ViewModel,用于统一状态栏
public SystemManagementViewModel(LogisticsControlViewModel mainViewModel) : base()
{
try
{
// 设置主ViewModel引用到基类
SetMainViewModel(mainViewModel);
// 获取UI状态管理器实例
_uiStateManager = UIStateManager.Instance;
// 验证关键组件是否正常初始化
if (_uiStateManager == null)
{
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
// 初始化日志级别集合
LogLevels = new ThreadSafeObservableCollection();
// 初始化命令
InitializeCommands();
// 初始化系统管理设置
_ = InitializeSystemManagementSettingsAsync();
LogManager.Info("SystemManagementViewModel构造函数执行完成 - 支持统一状态栏");
}
catch (Exception ex)
{
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
// 在构造函数中尽量保证对象处于可用状态
UpdateMainStatus("初始化失败,请检查日志");
throw;
}
}
#endregion
#region 初始化
///
/// 初始化命令
///
private void InitializeCommands()
{
try
{
// 系统管理命令
ViewLogCommand = new RelayCommand(() => ExecuteViewLog());
OpenSettingsCommand = new RelayCommand(() => ExecuteOpenSettings());
CheckUpdateCommand = new RelayCommand(() => ExecuteCheckUpdate());
GeneratePerformanceReportCommand = new RelayCommand(() => ExecuteGeneratePerformanceReport());
DiagnosticCommand = new RelayCommand(() => ExecuteDiagnostic());
// 数据管理命令
BackupDataCommand = new RelayCommand(() => ExecuteBackupData());
RestoreDataCommand = new RelayCommand(() => ExecuteRestoreData());
RepairDatabaseCommand = new RelayCommand(() => ExecuteRepairDatabase());
ClearAllDataCommand = new RelayCommand(() => ExecuteClearAllData());
// 功能测试命令
TestVoxelGridSDFCommand = new RelayCommand(() => ExecuteTestVoxelGridSDF());
TestVoxelPathFindingCommand = new RelayCommand(() => ExecuteTestVoxelPathFinding());
ReadTransformTestCommand = new RelayCommand(() => ExecuteReadTransformTest());
CoordinateSystemExplorerCommand = new RelayCommand(() => ExecuteCoordinateSystemExplorer());
// 初始化坐标系选项
CoordinateSystemOptions = new ObservableCollection { "AutoDetect", "ZUp", "YUp" };
// 从配置加载当前坐标系设置
var configType = ConfigManager.Instance.Current.CoordinateSystem?.Type ?? "AutoDetect";
_selectedCoordinateSystem = configType;
// 订阅文档事件(用于自动检测坐标系)
SubscribeToDocumentEvents();
// 检查当前是否已有活动文档,如果有立即检测
if (Autodesk.Navisworks.Api.Application.ActiveDocument != null)
{
InitializeCoordinateSystem();
}
else
{
// 没有活动文档,显示等待状态
CurrentCoordinateSystemInfo = "当前坐标系: 等待文档加载...";
}
LogManager.Info("系统管理命令初始化完成");
}
catch (Exception ex)
{
LogManager.Error($"初始化命令失败: {ex.Message}", ex);
throw;
}
}
///
/// 获取路径规划管理器实例
///
/// 路径规划管理器或null
private PathPlanningManager GetPathPlanningManager()
{
try
{
// 使用PathPlanningManager的静态方法获取活动实例
var pathManager = PathPlanningManager.GetActivePathManager();
if (pathManager != null)
{
LogManager.Info("成功获取到活动的PathPlanningManager实例");
return pathManager;
}
else
{
LogManager.Warning("当前没有活动的PathPlanningManager实例");
return null;
}
}
catch (Exception ex)
{
LogManager.Error($"获取PathPlanningManager失败: {ex.Message}", ex);
return null;
}
}
///
/// 初始化坐标系
///
private void InitializeCoordinateSystem()
{
try
{
// 解析配置类型
if (!Enum.TryParse(_selectedCoordinateSystem, out var configType))
{
configType = CoordinateSystemType.AutoDetect;
}
// 初始化坐标系管理器
CoordinateSystemManager.Instance.Initialize(configType);
// 更新显示信息
UpdateCoordinateSystemInfo();
LogManager.Info($"坐标系初始化完成: {configType}");
}
catch (Exception ex)
{
LogManager.Error($"坐标系初始化失败: {ex.Message}");
}
}
///
/// 坐标系选择改变时调用
///
private void OnCoordinateSystemChanged(string newValue)
{
try
{
if (!Enum.TryParse(newValue, out var type))
{
type = CoordinateSystemType.AutoDetect;
}
// 设置新坐标系
CoordinateSystemManager.Instance.SetCoordinateSystem(type);
// 更新显示信息
UpdateCoordinateSystemInfo();
// 更新配置
ConfigManager.Instance.Current.CoordinateSystem.Type = newValue;
UpdateMainStatus($"坐标系已切换为: {newValue}");
LogManager.Info($"坐标系已手动切换为: {newValue}");
}
catch (Exception ex)
{
LogManager.Error($"切换坐标系失败: {ex.Message}");
UpdateMainStatus($"切换坐标系失败: {ex.Message}");
}
}
///
/// 更新坐标系显示信息
///
private void UpdateCoordinateSystemInfo()
{
var info = CoordinateSystemManager.Instance.GetCurrentInfo();
CurrentCoordinateSystemInfo = $"当前坐标系: {info}";
}
#region 文档事件处理
///
/// 订阅文档切换事件
///
private void SubscribeToDocumentEvents()
{
try
{
// 订阅文档切换后事件(文档已完全加载)
Autodesk.Navisworks.Api.Application.ActiveDocumentChanged += OnActiveDocumentChanged;
// 同时订阅模型集合变化事件(SDI架构下的真正文档变化)
if (Autodesk.Navisworks.Api.Application.ActiveDocument != null)
{
Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CollectionChanged += OnModelsCollectionChanged;
}
LogManager.Info("[系统管理] 已订阅文档相关事件");
}
catch (Exception ex)
{
LogManager.Error($"[系统管理] 订阅文档事件失败: {ex.Message}");
}
}
///
/// 取消订阅文档事件
///
private void UnsubscribeFromDocumentEvents()
{
try
{
// 取消订阅文档切换事件
Autodesk.Navisworks.Api.Application.ActiveDocumentChanged -= OnActiveDocumentChanged;
// 取消订阅模型集合变化事件
if (Autodesk.Navisworks.Api.Application.ActiveDocument != null)
{
Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CollectionChanged -= OnModelsCollectionChanged;
}
LogManager.Info("[系统管理] 已取消订阅文档相关事件");
}
catch (Exception ex)
{
LogManager.Warning($"[系统管理] 取消订阅文档事件时出现警告: {ex.Message}");
}
}
///
/// 文档切换事件处理
///
private void OnActiveDocumentChanged(object sender, EventArgs e)
{
try
{
LogManager.Info("[系统管理] 检测到文档切换");
// 订阅新文档的 Models.CollectionChanged
if (Autodesk.Navisworks.Api.Application.ActiveDocument != null)
{
try
{
Autodesk.Navisworks.Api.Application.ActiveDocument.Models.CollectionChanged += OnModelsCollectionChanged;
LogManager.Info("[系统管理] 已订阅新文档的模型集合变化事件");
}
catch (Exception ex)
{
LogManager.Warning($"[系统管理] 订阅模型集合变化事件失败: {ex.Message}");
}
}
// 执行坐标系检测
HandleDocumentChange();
}
catch (Exception ex)
{
LogManager.Error($"[系统管理] 文档切换处理失败: {ex.Message}");
}
}
///
/// 模型集合变化事件处理(SDI架构下的真正文档变化)
///
private void OnModelsCollectionChanged(object sender, EventArgs e)
{
try
{
LogManager.Info("[系统管理] 检测到模型集合变化");
HandleDocumentChange();
}
catch (Exception ex)
{
LogManager.Error($"[系统管理] 模型集合变化处理失败: {ex.Message}");
}
}
///
/// 处理文档变化,重新检测坐标系
///
private void HandleDocumentChange()
{
// 检查文档是否已完全加载
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (doc == null || string.IsNullOrEmpty(doc.FileName))
{
LogManager.Debug("[系统管理] 文档尚未完全加载,跳过坐标系检测");
return;
}
// 如果配置为自动检测,重新检测坐标系
if (_selectedCoordinateSystem == "AutoDetect")
{
// 在 UI 线程执行
_ = _uiStateManager.ExecuteUIUpdateAsync(() =>
{
try
{
InitializeCoordinateSystem();
UpdateMainStatus("坐标系已根据新文档重新检测");
}
catch (Exception ex)
{
LogManager.Error($"[系统管理] 坐标系检测失败: {ex.Message}");
}
});
}
}
#endregion
///
/// 初始化系统管理设置
///
private async Task InitializeSystemManagementSettingsAsync()
{
await SafeExecuteAsync(async () =>
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// 初始化日志级别
LogLevels.Clear();
LogLevels.Add("Debug");
LogLevels.Add("Info");
LogLevels.Add("Warning");
LogLevels.Add("Error");
// 获取当前日志级别
var currentLevel = LogManager.GetLogLevel();
SelectedLogLevel = currentLevel.ToString();
// 初始化系统信息
PluginVersion = "v1.0";
NavisworksVersion = "2026";
// 初始化数据库状态(如果数据库已连接)
RefreshDatabaseStatus();
UpdateMainStatus("系统管理初始化完成");
});
LogManager.Info("系统管理设置初始化完成");
}, "初始化系统管理设置");
}
#endregion
#region 命令实现
///
/// 查看日志
///
private void ExecuteViewLog()
{
SafeExecute(() =>
{
try
{
// 创建并显示日志查看器对话框
var logViewerDialog = new NavisworksTransport.UI.WPF.Views.LogViewerDialog();
// 尝试设置窗口所有者,使用更安全的方式
try
{
// 查找当前活动的主窗口
var mainWindow = System.Windows.Application.Current.MainWindow;
if (mainWindow != null && mainWindow.IsLoaded)
{
logViewerDialog.Owner = mainWindow;
}
else
{
// 如果主窗口不可用,查找当前活动的窗口
foreach (System.Windows.Window window in System.Windows.Application.Current.Windows)
{
if (window.IsActive && window.IsLoaded)
{
logViewerDialog.Owner = window;
break;
}
}
}
}
catch (Exception ownerEx)
{
// 如果设置Owner失败,记录警告但继续显示窗口
LogManager.Warning($"设置日志查看器Owner失败: {ownerEx.Message}");
}
// 显示对话框(使用Show而不是ShowDialog以避免阻塞)
logViewerDialog.Show();
UpdateMainStatus("日志查看器已打开");
LogManager.Info("通过系统管理打开日志查看器");
}
catch (Exception ex)
{
UpdateMainStatus("打开日志查看器失败");
LogManager.Error($"打开日志查看器失败: {ex.Message}", ex);
// 显示错误消息给用户
System.Windows.MessageBox.Show($"打开日志查看器失败: {ex.Message}", "错误",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
}
}, "查看日志");
}
///
/// 打开设置
///
private void ExecuteOpenSettings()
{
SafeExecute(() =>
{
try
{
// 创建并显示配置编辑器对话框
var configEditorDialog = new NavisworksTransport.UI.WPF.Views.ConfigEditorDialog();
// 尝试设置窗口所有者
try
{
var mainWindow = System.Windows.Application.Current.MainWindow;
if (mainWindow != null && mainWindow.IsLoaded)
{
configEditorDialog.Owner = mainWindow;
}
else
{
foreach (System.Windows.Window window in System.Windows.Application.Current.Windows)
{
if (window.IsActive && window.IsLoaded)
{
configEditorDialog.Owner = window;
break;
}
}
}
}
catch (Exception ownerEx)
{
LogManager.Warning($"设置配置编辑器Owner失败: {ownerEx.Message}");
}
// 显示对话框
bool? result = configEditorDialog.ShowDialog();
if (result == true)
{
UpdateMainStatus("配置已更新");
LogManager.Info("配置编辑器:用户保存了配置");
}
else
{
UpdateMainStatus("配置编辑已取消");
LogManager.Info("配置编辑器:用户取消了修改");
}
}
catch (Exception ex)
{
UpdateMainStatus("打开配置编辑器失败");
LogManager.Error($"打开配置编辑器失败: {ex.Message}", ex);
System.Windows.MessageBox.Show($"打开配置编辑器失败: {ex.Message}", "错误",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
}
}, "打开设置");
}
///
/// 检查更新 (已优化为Idle事件监听)
///
private void ExecuteCheckUpdate()
{
SafeExecute(() =>
{
UpdateMainStatus("正在检查更新...");
// 使用Idle事件监听替代Thread.Sleep(2000)
const string taskId = "SystemManagement_CheckUpdate";
var startTime = DateTime.Now;
IdleEventManager.Instance.RegisterOnceTask(
taskId,
() => (DateTime.Now - startTime).TotalMilliseconds >= 2000, // 2秒后条件满足
() =>
{
try
{
// 检查释放状态,避免在释放后更新UI
if (_disposed)
{
LogManager.Info("SystemManagementViewModel已释放,跳过更新检查UI更新");
return;
}
UpdateMainStatus("当前版本已是最新版本");
}
catch (Exception ex)
{
LogManager.Error($"更新检查UI更新失败: {ex.Message}");
}
},
8 // 高优先级
);
LogManager.Info("检查更新 (使用Idle事件监听)");
}, "检查更新");
}
///
/// 生成性能报告 (已优化为Idle事件监听)
///
private void ExecuteGeneratePerformanceReport()
{
SafeExecute(() =>
{
UpdateMainStatus("正在生成性能报告...");
// 使用Idle事件监听替代Thread.Sleep(1500)
const string taskId = "SystemManagement_GenerateReport";
var startTime = DateTime.Now;
IdleEventManager.Instance.RegisterOnceTask(
taskId,
() => (DateTime.Now - startTime).TotalMilliseconds >= 1500, // 1.5秒后条件满足
() =>
{
try
{
// 检查释放状态,避免在释放后更新UI
if (_disposed)
{
LogManager.Info("SystemManagementViewModel已释放,跳过性能报告UI更新");
return;
}
UpdateMainStatus("性能报告生成完成");
// 性能信息更新已合并到统一状态栏
}
catch (Exception ex)
{
LogManager.Error($"性能报告UI更新失败: {ex.Message}");
}
},
8 // 高优先级
);
LogManager.Info("生成性能报告 (使用Idle事件监听)");
}, "生成性能报告");
}
///
/// 执行环境诊断
///
private void ExecuteDiagnostic()
{
SafeExecute(() =>
{
try
{
LogManager.Info("开始环境诊断");
// 直接调用本地的环境诊断方法
string diagnosticReport = DiagnoseEnvironment();
// 显示诊断结果对话框
System.Windows.MessageBox.Show(
diagnosticReport,
"环境诊断结果",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Information);
LogManager.Info("环境诊断完成");
}
catch (Exception ex)
{
LogManager.Error($"环境诊断失败: {ex.Message}", ex);
System.Windows.MessageBox.Show(
$"环境诊断失败: {ex.Message}",
"错误",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
}
}, "环境诊断");
}
///
/// 环境诊断方法 - 快速检查API是否可用
///
/// 诊断报告
private string DiagnoseEnvironment()
{
var report = new System.Text.StringBuilder();
report.AppendLine("=== Navisworks API环境诊断报告 ===");
try
{
// 1. 线程状态
var apartmentState = System.Threading.Thread.CurrentThread.GetApartmentState();
report.AppendLine($"线程状态: {apartmentState} {(apartmentState == System.Threading.ApartmentState.STA ? "✓" : "✗")}");
// 2. API可用性
try
{
var app = Autodesk.Navisworks.Api.Application.ActiveDocument;
report.AppendLine("API可用性: 可用 ✓");
}
catch (Exception apiEx)
{
report.AppendLine($"API可用性: 异常 - {apiEx.Message} ✗");
}
// 3. 文档状态
try
{
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document != null)
{
report.AppendLine($"活动文档: {document.FileName ?? "未命名"} ✓");
report.AppendLine($"模型数量: {document.Models?.Count ?? 0}");
}
else
{
report.AppendLine("活动文档: 无 ✗");
}
}
catch (Exception docEx)
{
report.AppendLine($"活动文档: 异常 - {docEx.Message} ✗");
}
// 4. 内存状态
long memoryMB = GC.GetTotalMemory(false) / 1024 / 1024;
report.AppendLine($"当前内存: {memoryMB} MB");
// 5. 系统信息
report.AppendLine($"插件版本: {PluginVersion}");
report.AppendLine($"Navisworks版本: {NavisworksVersion}");
report.AppendLine("系统状态: 正常");
report.AppendLine("=== 诊断完成 ===");
string result = report.ToString();
LogManager.Info($"[SystemManagement] 环境诊断报告:\n{result}");
return result;
}
catch (Exception ex)
{
string error = $"诊断过程出错: {ex.Message}";
report.AppendLine(error);
LogManager.Error($"[SystemManagement] {error}");
return report.ToString();
}
}
#region 数据管理方法
///
/// 刷新数据库状态信息
///
private void RefreshDatabaseStatus()
{
try
{
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
if (pathDatabase != null)
{
// 获取数据库信息
var dbInfo = pathDatabase.Backup.GetDatabaseInfo();
DatabaseVersion = dbInfo.VersionFormatted;
PathCount = dbInfo.PathRoutesCount.ToString();
CollisionRecordCount = dbInfo.ClashResultsCount.ToString();
LogManager.Debug($"数据库状态: 版本{dbInfo.VersionFormatted}, 路径{dbInfo.PathRoutesCount}, 点{dbInfo.PathPointsCount}, 边{dbInfo.PathEdgesCount}, 碰撞{dbInfo.ClashResultsCount}");
}
else
{
DatabaseVersion = "未连接";
PathCount = "--";
CollisionRecordCount = "--";
}
}
catch (Exception ex)
{
LogManager.Error($"刷新数据库状态失败: {ex.Message}");
DatabaseVersion = "错误";
}
}
///
/// 执行数据备份
///
private void ExecuteBackupData()
{
SafeExecute(() =>
{
try
{
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
if (pathDatabase == null)
{
System.Windows.MessageBox.Show(
"未找到数据库连接,请确保已加载模型",
"备份数据",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Warning);
return;
}
UpdateMainStatus("正在备份数据库...");
LogManager.Info("开始数据库文件备份");
string backupPath = pathDatabase.Backup.BackupDatabase();
if (!string.IsNullOrEmpty(backupPath))
{
var info = pathDatabase.Backup.GetDatabaseInfo();
LastBackupInfo = $"上次备份: {DateTime.Now:yyyy-MM-dd HH:mm:ss}, 版本{info.VersionFormatted}, {info.FileSizeFormatted}";
System.Windows.MessageBox.Show(
$"数据库备份完成!\n\n" +
$"版本: {info.VersionFormatted}\n" +
$"文件: {backupPath}\n\n" +
$"包含数据:\n" +
$"- 路径: {info.PathRoutesCount} 条\n" +
$"- 路径点: {info.PathPointsCount} 个\n" +
$"- 碰撞记录: {info.ClashResultsCount} 条\n" +
$"- 截图: {info.ScreenshotsCount} 张",
"备份成功",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Information);
UpdateMainStatus("数据库备份完成");
LogManager.Info($"数据库备份完成: {backupPath}, 版本{info.VersionFormatted}");
}
}
catch (Exception ex)
{
LogManager.Error($"数据备份失败: {ex.Message}");
System.Windows.MessageBox.Show(
$"数据备份失败: {ex.Message}",
"备份失败",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
UpdateMainStatus("数据备份失败");
}
}, "数据备份");
}
///
/// 执行数据恢复
///
private void ExecuteRestoreData()
{
SafeExecute(() =>
{
try
{
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
if (pathDatabase == null)
{
System.Windows.MessageBox.Show(
"未找到数据库连接,请确保已加载模型",
"恢复数据",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Warning);
return;
}
// 选择备份文件
var openFileDialog = new Microsoft.Win32.OpenFileDialog
{
Title = "选择数据库备份文件",
Filter = "数据库备份文件 (*.db)|*.db",
InitialDirectory = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"NavisworksTransport", "Backups")
};
if (openFileDialog.ShowDialog() != true)
{
return;
}
// 确认恢复
var result = System.Windows.MessageBox.Show(
"恢复数据将覆盖现有数据,建议先备份当前数据。\n\n是否继续?",
"确认恢复",
System.Windows.MessageBoxButton.YesNo,
System.Windows.MessageBoxImage.Warning);
if (result != System.Windows.MessageBoxResult.Yes)
{
return;
}
UpdateMainStatus("正在恢复数据库...");
LogManager.Info($"开始数据库恢复: {openFileDialog.FileName}");
pathDatabase.Backup.RestoreDatabase(openFileDialog.FileName);
// 恢复成功
bool restoreSuccess = true;
if (restoreSuccess)
{
// 刷新数据库状态
RefreshDatabaseStatus();
var info = pathDatabase.Backup.GetDatabaseInfo();
System.Windows.MessageBox.Show(
$"数据库恢复完成!\n\n" +
$"当前数据:\n" +
$"- 路径: {info.PathRoutesCount} 条\n" +
$"- 路径点: {info.PathPointsCount} 个\n" +
$"- 碰撞记录: {info.ClashResultsCount} 条\n" +
$"- 截图: {info.ScreenshotsCount} 张\n\n" +
$"请重新启动 Navisworks 以加载恢复的数据。",
"恢复成功",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Information);
UpdateMainStatus("数据恢复完成");
LogManager.Info("数据恢复完成");
// 刷新显示
RefreshDatabaseStatus();
}
}
catch (Exception ex)
{
LogManager.Error($"数据恢复失败: {ex.Message}");
System.Windows.MessageBox.Show(
$"数据恢复失败: {ex.Message}",
"恢复失败",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
UpdateMainStatus("数据恢复失败");
}
}, "数据恢复");
}
///
/// 执行数据库修复
///
private void ExecuteRepairDatabase()
{
SafeExecute(() =>
{
try
{
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
if (pathDatabase == null)
{
System.Windows.MessageBox.Show(
"未找到数据库连接",
"修复数据库",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Warning);
return;
}
UpdateMainStatus("正在检查数据库...");
LogManager.Info("开始数据库修复检查");
// 获取数据库信息
var info = pathDatabase.Backup.GetDatabaseInfo();
System.Windows.MessageBox.Show(
$"数据库检查结果:\n\n" +
$"版本: {info.VersionFormatted}\n" +
$"文件大小: {info.FileSizeFormatted}\n" +
$"路径数量: {info.PathRoutesCount} 条\n" +
$"路径点: {info.PathPointsCount} 个\n" +
$"路径边: {info.PathEdgesCount} 条\n" +
$"碰撞记录: {info.ClashResultsCount} 条\n" +
$"截图: {info.ScreenshotsCount} 张",
"检查结果",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Information);
// 刷新状态
RefreshDatabaseStatus();
UpdateMainStatus("数据库检查完成");
}
catch (Exception ex)
{
LogManager.Error($"数据库修复失败: {ex.Message}");
System.Windows.MessageBox.Show(
$"数据库修复失败: {ex.Message}",
"修复失败",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
UpdateMainStatus("数据库修复失败");
}
}, "数据库修复");
}
///
/// 执行清空所有数据
///
private void ExecuteClearAllData()
{
SafeExecute(() =>
{
try
{
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
if (pathDatabase == null)
{
System.Windows.MessageBox.Show(
"未找到数据库连接",
"清空数据",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Warning);
return;
}
// 双重确认
var result1 = System.Windows.MessageBox.Show(
"⚠️ 警告:此操作将永久删除所有路径和碰撞记录!\n\n" +
"建议先备份数据。\n\n" +
"是否继续?",
"确认清空数据",
System.Windows.MessageBoxButton.YesNo,
System.Windows.MessageBoxImage.Warning);
if (result1 != System.Windows.MessageBoxResult.Yes)
{
return;
}
var result2 = System.Windows.MessageBox.Show(
"请再次确认:是否永久删除所有数据?\n\n" +
"此操作不可恢复!",
"最终确认",
System.Windows.MessageBoxButton.YesNo,
System.Windows.MessageBoxImage.Warning);
if (result2 != System.Windows.MessageBoxResult.Yes)
{
return;
}
UpdateMainStatus("正在清空数据...");
LogManager.Info("开始清空所有数据");
// 清空所有表
pathDatabase.ClearAllData();
System.Windows.MessageBox.Show(
"所有数据已清空!",
"清空完成",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Information);
UpdateMainStatus("数据已清空");
LogManager.Info("所有数据已清空");
// 刷新状态
RefreshDatabaseStatus();
}
catch (Exception ex)
{
LogManager.Error($"清空数据失败: {ex.Message}");
System.Windows.MessageBox.Show(
$"清空数据失败: {ex.Message}",
"操作失败",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
UpdateMainStatus("清空数据失败");
}
}, "清空数据");
}
#endregion
///
/// 执行体素网格 SDF 测试(使用 MeshSignedDistanceGrid)
///
private async void ExecuteTestVoxelGridSDF()
{
await SafeExecuteAsync(async () =>
{
try
{
UpdateMainStatus("正在执行体素网格 SDF 测试...");
LogManager.Info("开始体素网格 SDF 测试(使用 MeshSignedDistanceGrid)");
// 获取当前文档
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document == null)
{
System.Windows.MessageBox.Show(
"未找到活动文档,请先打开一个 Navisworks 模型",
"体素网格 SDF 测试",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Warning);
UpdateMainStatus("体素网格 SDF 测试取消:无活动文档");
return;
}
// 创建并执行体素网格 SDF 测试命令
// 使用系统配置的网格大小参数
double cellSizeMeters = ConfigManager.Instance.Current.PathEditing.CellSizeMeters;
LogManager.Info($"使用系统配置的体素大小: {cellSizeMeters}米");
var testCommand = new VoxelGridSDFTestCommand(
document,
cellSize: cellSizeMeters, // 使用系统配置的体素大小
samplingRate: 1, // 采样率 1(显示所有体素)
vehicleRadius: 0.6, // 车辆半径 0.6米(必须 >= 体素大小才能看到膨胀效果)
vehicleHeight: 1.8 // 车辆高度 1.8米
);
var result = await testCommand.ExecuteAsync();
if (result.IsSuccess)
{
// 显示测试结果
System.Windows.MessageBox.Show(
$"体素网格 SDF 测试成功!\n\n{result.Message}\n\n详细信息请查看日志。",
"体素网格 SDF 测试结果",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Information);
UpdateMainStatus("体素网格 SDF 测试完成");
LogManager.Info($"体素网格 SDF 测试成功: {result.Message}");
}
else
{
System.Windows.MessageBox.Show(
$"体素网格 SDF 测试失败:\n{result.Message}",
"体素网格 SDF 测试",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
UpdateMainStatus($"体素网格 SDF 测试失败: {result.Message}");
LogManager.Error($"体素网格 SDF 测试失败: {result.Message}");
}
}
catch (Exception ex)
{
LogManager.Error($"体素网格 SDF 测试异常: {ex.Message}", ex);
System.Windows.MessageBox.Show(
$"体素网格 SDF 测试出现异常:\n{ex.Message}",
"错误",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
UpdateMainStatus($"体素网格 SDF 测试异常: {ex.Message}");
}
}, "体素网格 SDF 测试");
}
///
/// 执行体素路径规划测试(3D A*)
///
private async void ExecuteTestVoxelPathFinding()
{
await SafeExecuteAsync(async () =>
{
try
{
UpdateMainStatus("正在执行体素路径规划测试...");
LogManager.Info("开始体素路径规划测试(3D A*)");
// 获取当前文档
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document == null)
{
System.Windows.MessageBox.Show(
"未找到活动文档,请先打开一个 Navisworks 模型",
"体素路径规划测试",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Warning);
UpdateMainStatus("体素路径规划测试取消:无活动文档");
return;
}
// 使用系统配置的网格大小参数
double cellSizeMeters = ConfigManager.Instance.Current.PathEditing.CellSizeMeters;
LogManager.Info($"使用系统配置的体素大小: {cellSizeMeters}米");
// 根据可通行体素样本选择测试起点和终点
// 起点:体素(77, 41, 9) -> 世界(-116.35, 4.94, 50.16) - 模型中心、最高层
// 终点:体素(107, 11, 8) -> 世界(-67.13, -44.27, 48.52) - 偏右下、低一层
// 注意:VoxelToWorld返回的是体素左下角坐标,需要加上半个体素尺寸偏移到中心点
double voxelSizeInModelUnits = cellSizeMeters * UnitsConverter.GetMetersToUnitsConversionFactor(document.Units);
double halfVoxel = voxelSizeInModelUnits / 2.0;
// 起点:模型中心、最高层Z=9
var startPoint = new Autodesk.Navisworks.Api.Point3D(-200 + halfVoxel, -24.27 + halfVoxel, 42 + halfVoxel);
// 终点:偏右下、低一层Z=8
var endPoint = new Autodesk.Navisworks.Api.Point3D(-116.35 + halfVoxel, 0 + halfVoxel, 45 + halfVoxel);
LogManager.Info($"测试起点: ({startPoint.X:F2}, {startPoint.Y:F2}, {startPoint.Z:F2})");
LogManager.Info($"测试终点: ({endPoint.X:F2}, {endPoint.Y:F2}, {endPoint.Z:F2})");
// 创建并执行体素路径规划测试命令
var testCommand = new VoxelPathFindingTestCommand(
document,
cellSize: cellSizeMeters, // 体素大小(米)
vehicleRadius: 0.6, // 车辆半径 0.6米
vehicleHeight: 1.8, // 车辆高度 1.8米
startPoint: startPoint, // 起点
endPoint: endPoint // 终点
);
var result = await testCommand.ExecuteAsync();
if (result.IsSuccess)
{
// 显示测试结果
System.Windows.MessageBox.Show(
$"体素路径规划测试成功!\n\n{result.Message}\n\n详细信息请查看日志和3D视图中的路径可视化。",
"体素路径规划测试结果",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Information);
UpdateMainStatus("体素路径规划测试完成");
LogManager.Info($"体素路径规划测试成功: {result.Message}");
}
else
{
System.Windows.MessageBox.Show(
$"体素路径规划测试失败:\n{result.Message}",
"体素路径规划测试",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
UpdateMainStatus($"体素路径规划测试失败: {result.Message}");
LogManager.Error($"体素路径规划测试失败: {result.Message}");
}
}
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}");
}
}, "体素路径规划测试");
}
///
/// 读取选中对象的Transform信息,并测试旋转
///
private void ExecuteReadTransformTest()
{
try
{
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
var selection = doc.CurrentSelection.SelectedItems;
if (selection.Count == 0)
{
System.Windows.MessageBox.Show("请先选择一个对象!", "提示",
System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
return;
}
var item = selection[0];
var modelItems = new Autodesk.Navisworks.Api.ModelItemCollection { item };
// === 读取初始状态 ===
var transform1 = item.Transform;
var components1 = transform1.Factor();
var bbox1 = item.BoundingBox();
var center1 = bbox1.Center;
var info = $"=== 初始状态 ===\n";
info += $"对象: {item.DisplayName}\n";
info += $"包围盒中心: ({center1.X:F3}, {center1.Y:F3}, {center1.Z:F3})\n";
info += $"Transform.Translation: ({components1.Translation.X:F3}, {components1.Translation.Y:F3}, {components1.Translation.Z:F3})\n";
info += $"Transform.Rotation: {components1.Rotation}\n\n";
// === 应用旋转override ===
// 绕Z轴旋转45度(π/4弧度)
double angle = Math.PI / 4; // 45度
var rotationTransform = new Autodesk.Navisworks.Api.Transform3D(
new Autodesk.Navisworks.Api.Rotation3D(
new Autodesk.Navisworks.Api.UnitVector3D(0, 0, 1),
angle
)
);
// 应用override(false=增量模式)
doc.Models.OverridePermanentTransform(modelItems, rotationTransform, false);
info += $"=== 应用旋转后(绕Z轴45度)===\n";
// === 重新读取状态 ===
var transform2 = item.Transform;
var components2 = transform2.Factor();
var bbox2 = item.BoundingBox();
var center2 = bbox2.Center;
info += $"包围盒中心: ({center2.X:F3}, {center2.Y:F3}, {center2.Z:F3})\n";
info += $"Transform.Translation: ({components2.Translation.X:F3}, {components2.Translation.Y:F3}, {components2.Translation.Z:F3})\n";
info += $"Transform.Rotation: {components2.Rotation}\n\n";
info += $"=== 对比 ===\n";
info += $"包围盒中心变化: ({center2.X - center1.X:F3}, {center2.Y - center1.Y:F3}, {center2.Z - center1.Z:F3})\n";
info += $"item.Transform是否变化: {!transform1.Equals(transform2)}\n";
LogManager.Info(info);
System.Windows.MessageBox.Show(info, "Transform测试",
System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
}
catch (Exception ex)
{
System.Windows.MessageBox.Show($"错误: {ex.Message}", "错误",
System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
LogManager.Error($"读取Transform失败: {ex.Message}\n{ex.StackTrace}");
}
}
///
/// 执行坐标系探索命令
///
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 辅助方法
///
/// 安全执行异步操作
///
private async Task SafeExecuteAsync(Func action, string operationName = "未知操作")
{
try
{
await action();
}
catch (Exception ex)
{
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
UpdateMainStatus($"{operationName}失败: {ex.Message}");
}
}
///
/// 安全执行同步操作
///
private void SafeExecute(Action action, string operationName = "未知操作")
{
try
{
action();
}
catch (Exception ex)
{
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
UpdateMainStatus($"{operationName}失败: {ex.Message}");
}
}
///
/// 验证ViewModel状态是否正常
///
public bool IsValidState()
{
return _uiStateManager != null && LogLevels != null;
}
///
/// 获取ViewModel状态信息
///
public string GetStateInfo()
{
return $"UIStateManager: {(_uiStateManager != null ? "已初始化" : "未初始化")}, " +
$"日志级别数量: {LogLevels?.Count ?? 0}";
}
#endregion
#region 清理资源和IDisposable实现
///
/// 释放资源
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// 释放资源的具体实现
///
/// 是否正在释放托管资源
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
try
{
// 调用现有的清理逻辑
Cleanup();
LogManager.Info("SystemManagementViewModel已正确释放资源 (IDisposable)");
}
catch (Exception ex)
{
LogManager.Error($"SystemManagementViewModel释放资源时发生异常: {ex.Message}", ex);
}
}
_disposed = true;
}
}
public void Cleanup()
{
try
{
LogManager.Info("开始清理SystemManagementViewModel资源");
// 取消订阅文档相关事件
UnsubscribeFromDocumentEvents();
// 停止性能监控Idle任务,替代DispatcherTimer清理
try
{
IdleEventManager.Instance.UnregisterTask("SystemManagement_PerformanceMonitor");
LogManager.Info("SystemManagementViewModel性能监控Idle任务已停止");
}
catch (Exception ex)
{
LogManager.Warning($"停止性能监控Idle任务时出现警告: {ex.Message}");
}
// 清理可能的一次性任务
try
{
IdleEventManager.Instance.UnregisterTask("SystemManagement_CheckUpdate");
IdleEventManager.Instance.UnregisterTask("SystemManagement_GenerateReport");
LogManager.Debug("SystemManagementViewModel一次性Idle任务已清理");
}
catch (Exception ex)
{
LogManager.Debug($"清理一次性Idle任务时出现提示: {ex.Message}");
}
LogManager.Info("SystemManagementViewModel资源清理完成");
}
catch (Exception ex)
{
LogManager.Error($"SystemManagementViewModel清理失败: {ex.Message}");
}
}
#endregion
}
}