本次提交包含三个主要改进: 1. XY平面膨胀算法(VoxelGrid.cs) - 实现简单迭代形态学膨胀 - 只在水平方向(XY平面)的4邻域膨胀 - 不在Z方向(垂直方向)膨胀 - 符合车辆物流场景:车辆只侧面/顶部碰撞障碍物 2. 3D体素路径规划(VoxelPathFinder.cs) - 集成RoyT.AStar库进行3D A*路径规划 - 支持体素网格上的路径搜索 - 添加VoxelPathFindingTestCommand测试命令 3. UI和测试改进 - 删除旧的包围盒测试命令(VoxelGridTestCommand.cs) - 更新SystemManagementView UI - 添加体素路径规划测试功能 核心设计原则: - 门模型在SDF生成前被排除(留出通道空洞) - SDF阶段只标记几何体内部为障碍物 - 安全间隙仅在XY平面膨胀阶段应用 - 避免Z方向的错误膨胀 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1153 lines
44 KiB
C#
1153 lines
44 KiB
C#
using System;
|
||
using System.Collections.ObjectModel;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Input;
|
||
using NavisworksTransport.UI.WPF.ViewModels;
|
||
using NavisworksTransport.UI.WPF.Collections;
|
||
using NavisworksTransport.Core;
|
||
using NavisworksTransport.Core.Config;
|
||
using NavisworksTransport.Utils;
|
||
using NavisworksTransport.Commands;
|
||
|
||
namespace NavisworksTransport.UI.WPF.ViewModels
|
||
{
|
||
/// <summary>
|
||
/// 系统管理ViewModel - 处理插件系统管理功能
|
||
/// </summary>
|
||
public class SystemManagementViewModel : ViewModelBase, IDisposable
|
||
{
|
||
#region 私有字段
|
||
|
||
private readonly UIStateManager _uiStateManager;
|
||
|
||
// 网格可视化开关字段
|
||
private bool _showWalkableGrid = false;
|
||
private bool _showObstacleGrid = false;
|
||
private bool _showUnknownGrid = false;
|
||
private bool _showDoorGrid = false;
|
||
// 路径可视化模式字段
|
||
private bool _isStandardLineMode = true;
|
||
private bool _isVehicleSpaceMode = false;
|
||
|
||
// 日志管理字段
|
||
private ObservableCollection<string> _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";
|
||
|
||
// 🔧 修复:添加定时器字段以便在清理时停止
|
||
// 性能监控相关字段 (已改为Idle事件管理)
|
||
private DateTime _lastPerformanceUpdate = DateTime.MinValue;
|
||
private DateTime _startTime;
|
||
|
||
// 🔧 修复:添加释放状态标志
|
||
private bool _disposed = false;
|
||
|
||
#endregion
|
||
|
||
#region 公共属性
|
||
|
||
/// <summary>
|
||
/// 是否显示可通行网格点
|
||
/// </summary>
|
||
public bool ShowWalkableGrid
|
||
{
|
||
get => _showWalkableGrid;
|
||
set
|
||
{
|
||
if (SetProperty(ref _showWalkableGrid, value))
|
||
{
|
||
OnGridVisualizationChanged();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 是否显示障碍物网格点
|
||
/// </summary>
|
||
public bool ShowObstacleGrid
|
||
{
|
||
get => _showObstacleGrid;
|
||
set
|
||
{
|
||
if (SetProperty(ref _showObstacleGrid, value))
|
||
{
|
||
OnGridVisualizationChanged();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 是否显示未知区域网格点
|
||
/// </summary>
|
||
public bool ShowUnknownGrid
|
||
{
|
||
get => _showUnknownGrid;
|
||
set
|
||
{
|
||
if (SetProperty(ref _showUnknownGrid, value))
|
||
{
|
||
OnGridVisualizationChanged();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 是否显示门网格点
|
||
/// </summary>
|
||
public bool ShowDoorGrid
|
||
{
|
||
get => _showDoorGrid;
|
||
set
|
||
{
|
||
if (SetProperty(ref _showDoorGrid, value))
|
||
{
|
||
OnGridVisualizationChanged();
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 是否使用标准连线模式
|
||
/// </summary>
|
||
public bool IsStandardLineMode
|
||
{
|
||
get => _isStandardLineMode;
|
||
set
|
||
{
|
||
if (SetProperty(ref _isStandardLineMode, value))
|
||
{
|
||
if (value)
|
||
{
|
||
IsVehicleSpaceMode = false;
|
||
OnPathVisualizationModeChanged();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 是否使用车辆通行空间模式
|
||
/// </summary>
|
||
public bool IsVehicleSpaceMode
|
||
{
|
||
get => _isVehicleSpaceMode;
|
||
set
|
||
{
|
||
if (SetProperty(ref _isVehicleSpaceMode, value))
|
||
{
|
||
if (value)
|
||
{
|
||
IsStandardLineMode = false;
|
||
OnPathVisualizationModeChanged();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 日志级别集合
|
||
/// </summary>
|
||
public ObservableCollection<string> LogLevels
|
||
{
|
||
get => _logLevels;
|
||
set => SetProperty(ref _logLevels, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选中的日志级别
|
||
/// </summary>
|
||
public string SelectedLogLevel
|
||
{
|
||
get => _selectedLogLevel;
|
||
set
|
||
{
|
||
if (SetProperty(ref _selectedLogLevel, value))
|
||
{
|
||
// 将字符串转换为LogLevel枚举并设置
|
||
if (Enum.TryParse<LogLevel>(value, out var level))
|
||
{
|
||
LogManager.SetLogLevel(level);
|
||
LogManager.Info($"日志级别已更改为: {value}");
|
||
UpdateMainStatus($"日志级别已设置为: {value}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 插件版本
|
||
/// </summary>
|
||
public string PluginVersion
|
||
{
|
||
get => _pluginVersion;
|
||
set => SetProperty(ref _pluginVersion, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Navisworks版本
|
||
/// </summary>
|
||
public string NavisworksVersion
|
||
{
|
||
get => _navisworksVersion;
|
||
set => SetProperty(ref _navisworksVersion, value);
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 内存使用情况
|
||
/// </summary>
|
||
public string MemoryUsage
|
||
{
|
||
get => _memoryUsage;
|
||
set => SetProperty(ref _memoryUsage, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 运行时间
|
||
/// </summary>
|
||
public string RunningTime
|
||
{
|
||
get => _runningTime;
|
||
set => SetProperty(ref _runningTime, 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 TestVoxelGridSDFCommand { get; private set; }
|
||
public ICommand TestVoxelPathFindingCommand { get; private set; }
|
||
|
||
#endregion
|
||
|
||
#region 构造函数
|
||
|
||
public SystemManagementViewModel() : base()
|
||
{
|
||
try
|
||
{
|
||
// 获取UI状态管理器实例
|
||
_uiStateManager = UIStateManager.Instance;
|
||
|
||
// 验证关键组件是否正常初始化
|
||
if (_uiStateManager == null)
|
||
{
|
||
LogManager.Error("UIStateManager初始化失败");
|
||
throw new InvalidOperationException("UIStateManager初始化失败");
|
||
}
|
||
|
||
// 初始化日志级别集合
|
||
LogLevels = new ThreadSafeObservableCollection<string>();
|
||
|
||
// 初始化命令
|
||
InitializeCommands();
|
||
|
||
// 初始化系统管理设置
|
||
InitializeSystemManagementSettingsAsync();
|
||
|
||
LogManager.Info("SystemManagementViewModel构造函数执行完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
|
||
|
||
// 在构造函数中尽量保证对象处于可用状态
|
||
UpdateMainStatus("初始化失败,请检查日志");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 带主ViewModel参数的构造函数,支持统一状态栏
|
||
/// </summary>
|
||
/// <param name="mainViewModel">主ViewModel,用于统一状态栏</param>
|
||
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<string>();
|
||
|
||
// 初始化命令
|
||
InitializeCommands();
|
||
|
||
// 初始化系统管理设置
|
||
InitializeSystemManagementSettingsAsync();
|
||
|
||
LogManager.Info("SystemManagementViewModel构造函数执行完成 - 支持统一状态栏");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"SystemManagementViewModel构造函数异常: {ex.Message}", ex);
|
||
|
||
// 在构造函数中尽量保证对象处于可用状态
|
||
UpdateMainStatus("初始化失败,请检查日志");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 初始化
|
||
|
||
/// <summary>
|
||
/// 初始化命令
|
||
/// </summary>
|
||
private void InitializeCommands()
|
||
{
|
||
try
|
||
{
|
||
// 系统管理命令
|
||
ViewLogCommand = new RelayCommand(() => ExecuteViewLog());
|
||
OpenSettingsCommand = new RelayCommand(() => ExecuteOpenSettings());
|
||
CheckUpdateCommand = new RelayCommand(() => ExecuteCheckUpdate());
|
||
GeneratePerformanceReportCommand = new RelayCommand(() => ExecuteGeneratePerformanceReport());
|
||
DiagnosticCommand = new RelayCommand(() => ExecuteDiagnostic());
|
||
|
||
// 功能测试命令
|
||
TestVoxelGridSDFCommand = new RelayCommand(() => ExecuteTestVoxelGridSDF());
|
||
TestVoxelPathFindingCommand = new RelayCommand(() => ExecuteTestVoxelPathFinding());
|
||
|
||
LogManager.Info("系统管理命令初始化完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"初始化命令失败: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 网格可视化设置变更事件处理
|
||
/// </summary>
|
||
private void OnGridVisualizationChanged()
|
||
{
|
||
try
|
||
{
|
||
LogManager.Info($"网格可视化设置已更改: 通行={ShowWalkableGrid}, 障碍物={ShowObstacleGrid}, 未知={ShowUnknownGrid}, 门={ShowDoorGrid}");
|
||
|
||
// 通知路径规划管理器更新网格可视化
|
||
var pathPlanningManager = GetPathPlanningManager();
|
||
if (pathPlanningManager != null)
|
||
{
|
||
// 应用新的可视化设置
|
||
pathPlanningManager.UpdateGridVisualizationSettings(
|
||
showWalkable: ShowWalkableGrid,
|
||
showObstacle: ShowObstacleGrid,
|
||
showUnknown: ShowUnknownGrid,
|
||
showDoor: ShowDoorGrid);
|
||
|
||
UpdateMainStatus("网格可视化设置已更新");
|
||
}
|
||
else
|
||
{
|
||
LogManager.Warning("无法获取路径规划管理器,网格可视化设置可能不会立即生效");
|
||
UpdateMainStatus("网格可视化设置已保存");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"应用网格可视化设置失败: {ex.Message}", ex);
|
||
UpdateMainStatus("网格可视化设置应用失败");
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 路径可视化模式变更事件处理
|
||
/// </summary>
|
||
private void OnPathVisualizationModeChanged()
|
||
{
|
||
try
|
||
{
|
||
var renderPlugin = PathPointRenderPlugin.Instance;
|
||
if (renderPlugin != null)
|
||
{
|
||
var mode = IsVehicleSpaceMode ? PathVisualizationMode.VehicleSpace : PathVisualizationMode.StandardLine;
|
||
renderPlugin.VisualizationMode = mode;
|
||
|
||
LogManager.Info($"路径可视化模式已更改: {(IsVehicleSpaceMode ? "车辆通行空间" : "标准连线")}");
|
||
UpdateMainStatus("路径可视化模式已更新");
|
||
}
|
||
else
|
||
{
|
||
LogManager.Warning("无法获取PathPointRenderPlugin实例");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"应用路径可视化模式失败: {ex.Message}", ex);
|
||
UpdateMainStatus("路径可视化模式更新失败");
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 获取路径规划管理器实例
|
||
/// </summary>
|
||
/// <returns>路径规划管理器或null</returns>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化系统管理设置
|
||
/// </summary>
|
||
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";
|
||
UpdateMainStatus("系统管理初始化完成");
|
||
});
|
||
|
||
// 启动性能监控
|
||
StartPerformanceMonitoring();
|
||
|
||
LogManager.Info("系统管理设置初始化完成");
|
||
}, "初始化系统管理设置");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 启动性能监控 (已优化为Idle事件)
|
||
/// </summary>
|
||
private void StartPerformanceMonitoring()
|
||
{
|
||
// 如果已经释放,不启动监控
|
||
if (_disposed)
|
||
{
|
||
LogManager.Info("SystemManagementViewModel已释放,跳过性能监控启动");
|
||
return;
|
||
}
|
||
|
||
_startTime = DateTime.Now;
|
||
_lastPerformanceUpdate = DateTime.MinValue;
|
||
|
||
// 使用IdleEventManager注册性能监控任务,替代DispatcherTimer
|
||
const string taskId = "SystemManagement_PerformanceMonitor";
|
||
|
||
IdleEventManager.Instance.RegisterTask(
|
||
taskId,
|
||
UpdatePerformanceMetrics, // 要执行的操作
|
||
30000, // 30秒间隔 (毫秒)
|
||
5 // 中等优先级
|
||
);
|
||
|
||
LogManager.Info("SystemManagementViewModel性能监控已启动 (Idle事件模式)");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新性能指标 (Idle事件回调方法)
|
||
/// </summary>
|
||
private void UpdatePerformanceMetrics()
|
||
{
|
||
try
|
||
{
|
||
// 检查释放状态,避免在释放后继续更新UI
|
||
if (_disposed)
|
||
{
|
||
LogManager.Info("SystemManagementViewModel已释放,停止性能监控更新");
|
||
IdleEventManager.Instance.UnregisterTask("SystemManagement_PerformanceMonitor");
|
||
return;
|
||
}
|
||
|
||
// 更新内存使用
|
||
var process = System.Diagnostics.Process.GetCurrentProcess();
|
||
var memoryMB = process.WorkingSet64 / (1024 * 1024);
|
||
MemoryUsage = $"{memoryMB} MB";
|
||
|
||
// 更新运行时间
|
||
var runTime = DateTime.Now - _startTime;
|
||
RunningTime = $"{runTime.Hours:D2}:{runTime.Minutes:D2}:{runTime.Seconds:D2}";
|
||
|
||
// 记录上次更新时间
|
||
_lastPerformanceUpdate = DateTime.Now;
|
||
|
||
LogManager.Debug($"性能指标已更新: 内存={MemoryUsage}, 运行时间={RunningTime}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"性能监控更新失败: {ex.Message}");
|
||
|
||
// 发生异常时停止监控,避免持续错误
|
||
if (!_disposed)
|
||
{
|
||
IdleEventManager.Instance.UnregisterTask("SystemManagement_PerformanceMonitor");
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 命令实现
|
||
|
||
|
||
/// <summary>
|
||
/// 查看日志
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}, "查看日志");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打开设置
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}, "打开设置");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查更新 (已优化为Idle事件监听)
|
||
/// </summary>
|
||
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事件监听)");
|
||
}, "检查更新");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成性能报告 (已优化为Idle事件监听)
|
||
/// </summary>
|
||
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事件监听)");
|
||
}, "生成性能报告");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行环境诊断
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}, "环境诊断");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 环境诊断方法 - 快速检查API是否可用
|
||
/// </summary>
|
||
/// <returns>诊断报告</returns>
|
||
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();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行体素网格 SDF 测试(使用 MeshSignedDistanceGrid)
|
||
/// </summary>
|
||
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 测试");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行体素路径规划测试(3D A*)
|
||
/// </summary>
|
||
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(-165.56 + halfVoxel, -44.27 + halfVoxel, 50.16 + 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}");
|
||
}
|
||
}, "体素路径规划测试");
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 辅助方法
|
||
|
||
/// <summary>
|
||
/// 安全执行异步操作
|
||
/// </summary>
|
||
private async Task SafeExecuteAsync(Func<Task> action, string operationName = "未知操作")
|
||
{
|
||
try
|
||
{
|
||
await action();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
|
||
UpdateMainStatus($"{operationName}失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全执行同步操作
|
||
/// </summary>
|
||
private void SafeExecute(Action action, string operationName = "未知操作")
|
||
{
|
||
try
|
||
{
|
||
action();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"{operationName}发生异常: {ex.Message}", ex);
|
||
UpdateMainStatus($"{operationName}失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证ViewModel状态是否正常
|
||
/// </summary>
|
||
public bool IsValidState()
|
||
{
|
||
return _uiStateManager != null && LogLevels != null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取ViewModel状态信息
|
||
/// </summary>
|
||
public string GetStateInfo()
|
||
{
|
||
return $"UIStateManager: {(_uiStateManager != null ? "已初始化" : "未初始化")}, " +
|
||
$"日志级别数量: {LogLevels?.Count ?? 0}";
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 清理资源和IDisposable实现
|
||
|
||
/// <summary>
|
||
/// 释放资源
|
||
/// </summary>
|
||
public void Dispose()
|
||
{
|
||
Dispose(true);
|
||
GC.SuppressFinalize(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 释放资源的具体实现
|
||
/// </summary>
|
||
/// <param name="disposing">是否正在释放托管资源</param>
|
||
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资源");
|
||
|
||
// 停止性能监控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
|
||
}
|
||
} |